ModSecurity SQL注入攻擊

來源:互聯網
上載者:User

標籤:

ModSecurity是一個入侵探測與阻止的引擎,它主要是用於Web應用程式所以也可以叫做Web應用程式防火牆.它可以作為Apache Web伺服器的一個模組或單獨的應用程式來運行。ModSecurity的目的是為增強Web應用程式的安全性和保護Web應用程式避免遭受來自已知與未知的攻擊。本文主要介紹了針對開源WAF的一次滲透測試比賽中的思路。

1. 文章背景

ModSecurity SQL Injection Challenge(ModSecurity發起的一個針對開源WAF的一次滲透測試比賽)

 

owasp-modsecurity-crs(OWASP針對ModSecurity編寫的權威rule)

https://github.com/SpiderLabs/owasp-modsecurity-crs

2. 繞過思路分析

0×1:

目標應用系統: Acunetix Acuart Site

注入點: ?artist=1‘;

 

 

 

 

分析:

注入點很明顯,通過測試可以知道這個注入點為數字型的注入,各種拼接都可以進行,但是普通的注入方法無一例外都會觸發Mod的攔截規則。

這裡採用mysql注釋+CRLF繞過思路來進行注入

Mysql Comment Syntax

    1) "#"用於單行注釋

    2) "– "用於單行注釋,但要注意使用這種風格的注釋符必須保證在"雙橫線"後面跟上一個"空格或控制符Control Char(控制符可以是空格, Tab定位字元, 分行符號Newline…)"(在使用的時候要注意URL編碼,例如分行符號的URL編碼為%0D%0A)。關於這種"Double Dash注釋符"在Mysql的官方文檔中還有一點細節要注意(重點就是新版的Mysql解析引擎的改進避免了"基於減號導致的注釋型注入")

    3) "/* */"C風格的注釋符,這種注釋允許跨行注釋(即允許在注釋符中添加分行符號,例如: /*..%0D%0A..*/)

mysql> SELECT 1+1; # This comment continues to the end of line mysql> SELECT 1+1; -- This comment continues to the end of line mysql> SELECT 1/* this is an in-line comment */ + 1; mysql> SELECT 1+ /* this is a multiple-line comment */ 1;

 

 

回到我們的注入點上來看看,我們使用mysql注釋+CRLF來進行payload的構造(注意URL編碼):

?artist=0+div+1+union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A1%2C2%2Ccurrent_user

對其URL轉義如下(注意分行符號的解析):

0 div 1 union#foo*/*bar

select#foo

1,2,current_user

這句sql語句到了Mysql的解析引擎後會再次被解析為:

0 div 1 union select 1,2,current_user

可以看到,注釋符之間進行了就近原則的交錯組合,Mysql的Sql Parser則選擇進行了忽略。

而ModSecurity CRS的規則如下:

 

 

注意到這個":replaceComments",我們知道,ModSecurity使用Regex來對Input Sql進行匹配檢測,對Select、Union在敏感位置的出現都進行了攔截,但是ModSecurity有一個特點(或者叫優點),它會對輸入進行"正常化",正常化的本意本來是防禦"基於編碼格式、解析順序"的繞過的。

例如:

Mod可以抵抗這種形式的繞過: 

SEL/**/ECT

在"正常化"之後,攻擊者的本來目的就暴力在了Mod的檢測下,這個時候再上規則就可以檢測出來了,可以說,正常化是一個很好的防禦思路。

但是這裡卻導致了另一種的"繞過"

問題的關鍵就在於ModSecurity對注釋的理解和Mysql的解析引擎理解不同

(這似乎又回到了那個老問題: 同一個商務規則在不同的系統中的理解語義不同往往可能導致繞過)

:replaceComments

Unterminated comments will also be replaced with a space (ASCII 0x20). However, a standalone termination of a comment (*/) will not be acted upon.

也就是說,Mod會忽略前向半開注釋並把後向半開注釋當成單行注釋(如果它沒有找到後向半開的閉合注釋時)

Mod的攔截日誌中可以看到如下記錄:

 

 

 

這樣,在Mod看來,我們輸入的Payload就變成了:

"0 div 1 union#foo* "

但是在Mysql看來,我們的sql語句其實是:

0 div 1 union select 1,2,current_user

防禦方法:

1) 將原來的去除注釋方法改為對SQL注釋的匹配

# # -=[ Detect SQL Comment Sequences ]=- # SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* \ "(\/\*\!?|\*\/|\-\-[\s\r\n\v\f]|(?:--[^-]*-)|([^\-&])#.*[\s\r\n\v\f]|;?\\x00)" \ "phase:2,rev:‘2.2.2‘,id:‘981231‘,t:none,t:urlDecodeUni,block,msg:‘SQL Comment Sequence Detected.‘,capture,logdata:‘%{tx.0}‘,tag:‘WEB_ATTACK/SQL_INJECTION‘,tag:‘WASCTC/WASC-19‘,tag:‘OWASP_TOP_10/A1‘,tag:‘OWASP_AppSensor/CIE1‘,tag:‘PCI/6.5.2‘,setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.sql_injection_score=+1,setvar:‘tx.msg=%{rule.msg}‘,setvar:tx.%{rule.id}-WEB_ATTACK/SQL_INJECTION-%{matched_var_name}=%{tx.0}"

 

 

但是這種方法從本質上又回到了"黑名單模式"的範疇中,有可能再次導致別的形式的繞過

 

2) 使用多行匹配(MultiMatch Action)+正常化方法(ReplaceComments) 

SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "(?i:\buser_tables\b)" \ "phase:2,rev:‘2.2.2‘,capture,multiMatch,t:none,t:urlDecodeUni,t:replaceComments,ctl:auditLogParts=+E,block,msg:‘Blind SQL Injection Attack‘,id:‘959918‘,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×2:

目標應用系統: Cenzic Crack Me Bank

注入點: (POST)

注入Payload:

 

 

 

繞過分析:

這裡採用了"片段注入法(分段SQL注入)",或者是我們常說的"Split And Balance原則"。例如:

對於最簡單的情況,可以使用字串串連技術將較小的部分構造成一個字串。不同的資料庫使用不同的文法來構造字串

oracle: ‘selec‘||‘t‘ sqlserver: ‘selec‘+‘‘; mysql: ‘selec‘+‘t‘

 

 

(這就是所謂的split and balance思想)

還要注意的是,加號和空格要先進行URL編碼後再發送

這種技術的好處是可以將原本完整的Payload分成幾段,利用ModSecurity對SQL語義的理解不全來進行規則繞過。常常用於進行"二值邏輯"的盲注推理。

回到我們的注入點上來看:

對於Mod來說,我們的攻擊Payload為:

hUserId=22768&FromDate=a1%27+or&ToDate=%3C%3Eamount+and%27&sendbutton1=Get+Statement

而對於Mysql的解析引擎來說,它會自動去除、轉換這些串連控制符,從而變成:

hUserId=22768&FromDate=a1%27+or&ToDate=<>amount and%27&sendbutton1=Get Statement

防禦方法:

1) 這裡有個概念叫"String Termination/Statement Ending Injection Testing"。攻擊者在進行SQL注入檢測的時候常常會使用一些"終止符",例如單引號、NULL等等,並通過觀察頁面是否報錯來獲知當前頁面是否存在注入點。

為了防禦這種注入,我們可以使用以下CRS規則:

# # -=[ String Termination/Statement Ending Injection Testing ]=- # # Identifies common initial SQLi probing requests where attackers insert/append # quote characters to the existing normal payload to see how the app/db responds. # SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* \ "(?i:(\!\=|\&\&|\|\||>>|<<|>=|<=|<>|<=>|xor|rlike|regexp|isnull)|(?:not\s+between\s+0\s+and)|(?:is\s+null)|(like\s+null)|(?:(?:^|\W)in[+\s]*\([\s\d\"]+[^()]*\))|(?:xor|<>|rlike(?:\s+binary)?)|(?:regexp\s+binary))" \ "phase:2,rev:‘2.2.2‘,capture,t:none,t:urlDecodeUni,block,msg:‘SQL Injection Attack: SQL Operator Detected‘,id:‘981212‘,logdata:‘%{TX.0}‘,severity:‘2‘,tag:‘WEB_ATTACK/SQL_INJECTION‘,tag:‘WASCTC/WASC-19‘,tag:‘OWASP_TOP_10/A1‘,tag:‘OWASP_AppSensor/CIE1‘,tag:‘PCI/6.5.2‘,setvar:‘tx.msg=%{rule.msg}‘,setvar:tx.sql_injection_score=+%{tx.notice_anomaly_score},setvar:tx.anomaly_score=+%{tx.notice_anomaly_score},setvar:tx.%{rule.id}-WEB_ATTACK/SQL_INJECTION-%{matched_var_name}=%{tx.0}"

 

 

2) 注意到我們的攻擊Payload中一個Mysql邏輯運算子: "<>"。攻擊者可以利用邏輯運算子進行"盲注推理"。例如,我們常見的傳統盲注手段:

and (ascii(substring((select username from admin),1,1)))>97

(這種就是將逐個字元轉成ASCII值然後用二分尋找法進行猜測)

 

UPDATE table SET views = ‘1‘ WHERE id = -2441 OR (ORD(MID((SELECTIFNULL(CAST(FirstName AS CHAR),0x20) FROM nowamagic.`tb2` ORDER BY id LIMIT 1,1),2,1))>112)#

(同樣的思路,換了一個函數)

為了防禦這種注入,我們可以使用以下CRS規則

# # -=[ SQL Operators ]=- # SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* \ "(?i:(\!\=|\&\&|\|\||>>|<<|>=|<=|<>|<=>|xor|rlike|regexp|isnull)|(?:not\s+between\s+0\s+and)|(?:is\s+null)|(like\s+null)|(?:(?:^|\W)in[+\s]*\([\s\d\"]+[^()]*\))|(?:xor|<>|rlike(?:\s+binary)?)|(?:regexp\s+binary))" \ "phase:2,rev:‘2.2.2‘,capture,t:none,t:urlDecodeUni,block,msg:‘SQL Injection Attack: SQL Operator Detected‘,id:‘981212‘,logdata:‘%{TX.0}‘,severity:‘2‘,tag:‘WEB_ATTACK/SQL_INJECTION‘,tag:‘WASCTC/WASC-19‘,tag:‘OWASP_TOP_10/A1‘,tag:‘OWASP_AppSensor/CIE1‘,tag:‘PCI/6.5.2‘,setvar:‘tx.msg=%{rule.msg}‘,setvar:tx.sql_injection_score=+%{tx.notice_anomaly_score},setvar:tx.anomaly_score=+%{tx.notice_anomaly_score},setvar:tx.%{rule.id}-WEB_ATTACK/SQL_INJECTION-%{matched_var_name}=%{tx.0}"

 

 

0×3:

目標應用系統: IBM demo.testfire.net site

注入點: (POST)

 

 

 

注入Payload:

 

 

 

 

 

 

 

 

 

這裡使用了HPP(HTTP Parameter Pollution)注入技術,關於HPP,有很多相關的資料:

 

 

 

https://www.owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf

回到我們的注入Payload上來,我們注意到after這個欄位出現了3次,其中後2次的出現其實是產生了逗號的作用,以此來進行繞過。要注意的一點是,HPP攻擊和具體的應用系統內容有很大關係,在不同的系統上表現不太一致:

https://www.trustwave.com/spiderlabs/advisories/TWSL2011-006.txt

防禦方法:

我們可以採用以下的CRS規則來防禦HPP攻擊:

# -=[ Rules Logic }=- # The ruleset below is not looking for attacks directly, but rather is a crude normalization # function that mimics ASP.NET with regards to joining the payloads of parameters with the # same name. These rules will create a new TX:HPP_DATA variable that will hold this data. # If you have enabled PARANOID_MODE, then this variable data will also be searched against # attack filters. # # -=[ References ]=- # # SecRule ARGS "^" "chain,phase:2,t:none,nolog,pass,capture,id:‘900032‘,rev:‘2.2.9‘,setvar:tx.%{matched_var_name}=+1" SecRule TX:/^ARGS:/ "@gt 1" "chain,t:none" SecRule MATCHED_VARS_NAMES "TX:(ARGS:.*)" "chain,capture,t:none,setvar:tx.hpp_names=%{tx.1}" SecRule ARGS ".*" "chain,t:none,capture,setvar:tx.arg_counter=+1,setvar:‘tx.hppnamedata_%{tx.arg_counter}=%{matched_var_name}=%{tx.0}‘" SecRule TX:/HPPNAMEDATA_/ "@contains %{tx.hpp_names}" "chain,setvar:tx.hpp_counter=+1,setvar:tx.hpp_counter_%{tx.hpp_counter}=%{matched_var}" SecRule TX:/HPP_COUNTER_/ "ARGS:(.*)?=(.*)" "capture,setvar:‘tx.hpp_data=%{tx.hpp_data},%{tx.2}‘"

 

 

0×4:

目標應用系統: Cenzic Crack Me Bank

注入點: (POST)

注入Payload:

 

 

 

思路分析:

這裡採用了"半開注釋符(Unterminated Comments)"+"Mysql注釋符代碼執行(MySQL Comment Extensions for conditional code execution)"技術來進行繞過

半開注釋符我們之前說過了,是利用Mod的replaceComments來進行敏感關鍵字的繞過。而"Mysql注釋符代碼執行"則是Mysql的一個運行機制。

Mysql的官方文檔如下:

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允許C風格的注釋符,並允許在其中寫入Mysql擴充,即插入可執行sql代碼)

/*! MySQL-specific code */

Mysql的Paerser引擎會自動解析這種格式中的sql代碼,同時其他的資料庫(例如MSSQL、ORACLE會自動忽略這些注釋),也就是說,這是Mysql特有的特性:

select 1 union/*! select */version();

select 1 union/*!32302 select */version();

防禦方法:

和 0×1 一樣,採用使用多行匹配(MultiMatch Action)+正常化方法(ReplaceComments) 

0×5:

目標應用系統: IBM demo.testfire.net site

注入點: (COOKIE)

注入Payload:

 

 

 

注入分析:

注入點並沒有什麼特別的,關鍵在與這裡採用了COOKIE注入

防禦方法:

 

 

 

關於這個COOKIE注入,我想延伸幾點想法:

在注入點的選擇中,HTTP中的任何欄位、任何位置都"有可能"產生SQL注入,這裡只能說有可能,因為是否能否產生注入,和具體的應用系統的環境有關,即應用系統會使用哪些欄位帶入資料進行執行

"GPCS"的作用:

在php.ini中有一項配置: variables_order = "GPCS"(具體的順序和字元和具體你的配置有關)

如果在php.ini中開啟了"register_globals"這個選項,則PHP會按照"$GET"、"$POST"、"$COOKIE"、"SERVER"的順序來把這些全域資料中國的子鍵抽取出來,註冊到本地變數的的符號表中,即全域變數本地化。這個順序很重要,這往往是很多本地變數覆蓋漏洞利用的關鍵

3.  HTTP中的任意位置都有可能產生SQL注入,看下面的例子:

 

Create New Admin Exploit FOR php168 v4.0SP

這個例子中,注入點發生在"X-FORWARDED-FOR"這個欄位中,這本來是應用系統用來做記錄登入使用者的IP、代理IP的業務功能,但是因為沒有過濾嚴格,導致了注入的發生

0×6:

目標應用系統: Acunetix Acuart Site

注入點: ?artist=1‘

 

注入Payload:

?artist=%40%40new%20union%23sqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsql%0Aselect%201,2,database%23sqlmap%0A%28%29

Payload分析:

這裡採用了"Mysql注釋(MySQL Comment )"+"換行繞過(New Line trick )"的組合方法來進行Mod的繞過(本質上是對Mod所使用的Regex的繞過)

在Mod看來,我們的Payload如下:

[email protected]@new union#sqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsql

select 1,2,database#sqlmap

()

然而,當這段SQL代碼進入Mysql的解析引擎的時候,Mysql看到的是這樣的形式:

[email protected]@new union select 1,2,database()

防禦方法:

我們知道,SQL(Structure Query Language)是一種及其靈活的命令式語言,各個元素之間的組合可以有很多種,採用正則REGEX的方法來進行匹配常常無法做到精確指導,為瞭解決這個問題,我們有兩種思路

 

1) 採用高階的SQL解析方法,例如AST:

 

2) 改進正則,採用敏感關鍵字匹配的方法

SecRule REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* \ "([\~\!\@\#\$\%\^\&\*\(\)\-\+\=\{\}\[\]\|\:\;\"\‘\′\’\‘\`\<\>].*){4,}" \ "phase:2,t:none,t:urlDecodeUni,block,id:‘981173‘,rev:‘2.2.1‘,msg:‘Restricted SQL Character Anomaly Detection Alert - Total # of special characters exceeded‘,capture,logdata:‘%{tx.1}‘,setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.sql_injection_score=+1,setvar:‘tx.msg=%{rule.msg}‘,setvar:tx.%{rule.id}-WEB_ATTACK/RESTRICTED_SQLI_CHARS-%{matched_var_name}=%{tx.0}"

 

 

0×7:

目標應用系統: Acunetix Acuart Site

注入點: ?artist=1‘

1.png

注入Payload:

1.png

1.png

Payload分析:

這裡採用了"Mysql錯誤回顯"+"Tab鍵分隔繞過"的組合方法來進行Mod的繞過,這裡的關鍵點是沒有使用傳統的空格來進行"Split And Balance"。

這裡要提的是黑名單思想,對"Split And Balance"的防禦如果採用黑名單容易產生繞過:

https://docs.google.com/document/d/1rO_LCBKJY0puvRhPhAfTD2iNVPfR4e9KiKDpDE2enMI/edit?pli=1#Allowed_Intermediary_Character_30801873723976314

如果一定要採用黑名單,則必須進行嚴格的代碼審計和測試,保證黑名單的完整性

例如,在Mysql中允許的分隔字元為:

09

0A

0B

0C

0D

A0

防禦方法:

採用完整的"准空格分隔字元"黑名單CRS

SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* \ "(?i:(?:,.*[)\da-f(\"|‘|`|′|’|‘)](\"|‘|`|′|’|‘)(?:(\"|‘|`|′|’|‘).*(\"|‘|`|′|’|‘)|\Z|[^(\"|‘|`|′|’|‘)]+))|(?:\Wselect.+\W*from)|((?:select|create|rename|truncate|load|alter|delete|update|insert|desc)\s*\(\s*space\s*\())" \ "phase:2,capture,multiMatch,t:none,t:urlDecodeUni,t:replaceComments,block,msg:‘Detects MySQL comment-/space-obfuscated injections and backtick termination‘,id:‘981257‘,tag:‘WEB_ATTACK/SQLI‘,tag:‘WEB_ATTACK/ID‘,logdata:‘%{TX.0}‘,severity:‘2‘,setvar:‘tx.msg=%{rule.id}-%{rule.msg}‘,setvar:tx.anomaly_score=+5,setvar:‘tx.%{tx.msg}-WEB_ATTACK/SQLI-%{matched_var_name}=%{tx.0}‘,setvar:‘tx.%{tx.msg}-WEB_ATTACK/ID-%{matched_var_name}=%{tx.0}‘

 

 

3. 總結

Blacklist filtering is not enough — 不要依賴黑名單機制

應該使用多種方法進行縱深防禦

https://www.trustwave.com/application-security/

對輸入驗證採用安全模型,包括正常化、資料類型,資料格式,資料長度

https://www.trustwave.com/web-application-firewall/

WAF作為一個防禦手段,從某種程式上來說只是增加了攻擊者的攻擊成本,並不能從根本上解決注入的發生,要解決注入漏洞的產生,保護敏感性資料,必須多管齊下,從應用系統、WAF、資料庫防火牆的角度去思考

原文地址:http://www.41443.com/HTML/wangzhananquan/20141212/235953.html

ModSecurity SQL注入攻擊

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.