phpwind前台getshell--哈希扩展长度攻击实战露面(附poc)
in 漏洞分析 with 0 comment

phpwind前台getshell--哈希扩展长度攻击实战露面(附poc)

in 漏洞分析 with 0 comment

0x01.前言

说起来也是惭愧,从上密码学课开始接触很多密码学方面的攻击
但是实际用到实战上的却寥寥无几
之前我博文中的对哈希扩展长度攻击的详解分析中倒是有个例子
不过那个例子也是我自己写的,自己构造环境自己攻击而已,自娱自乐
但是这次确实是代码审计实战中的哈希扩展长度攻击终于露面,激动不已
最早是二哥在wooyun上发布的这个getshell漏洞,但是细节还没公布
p牛的分析在上周已经出来了,由于上周考试,没来得及看p牛的分析
p牛分析的非常详细,这周看了之后受益匪浅,感触之余也想跟大家分享一下。
p牛没有放poc,我这里就做一点微小的工作,给一下哈希扩展长度攻击的利用代码

0x02.漏洞简要分析

想要看详细分析就移步p牛的博客吧,这里先简单的说一下这个漏洞。
出现漏洞的地方在appKey()这个函数中,我们先看看这个函数
QQ20170520-191337@2x.png
最后return的就是windidkey,我们来详细分析一下它的组成
php md5(md5($apiId.'||'.$secretkey).$time.$str)
其中md5($apiId.'||'.$secretkey)我们是不知道的
$time是我们可控的,在get参数里传进去就可以了
$str的组成是get和post的数据组合到一起
举个例子吧
假如get参数是a=doAvatar&c=avatar然后post参数是uid=undefined
那么这个$str就是:adoAvataocavataruidundefined
这样应该能清楚了吧,我们再来回想一下哈希扩展长度攻击的条件

  1. 首要的就是要知道密钥长度

这里我们把md5($apiId.'||'.$secretkey)看成密钥,长度是32位固定的
然后时间是类似1464789394也是可以知道的
最后$str是可控的,也就是说整个长度我们是知道的
知道了长度我们就能伪造填充值(padding),再在填充值后面加上我们自己伪造的内容

  1. 需要知道伪造前字符串的md5

这个md5很关键,我们是可以找到的,在头像上传界面
QQ20170520-191611@2x.png
右键查看源代码
QQ20170520-191644@2x.png
在源代码中已经给出来了,那我们看看这是$str是多少
在源代码里做一点改动,方便我们查看
QQ20170520-191701@2x.png
再刷新页面
QQ20170520-191711@2x.png
我们看到这里可以看到我们的$str是:
adoAvatarcavatarmapitypeflashuid2uidundefined
也就是说最后加密的内容是
md5(32)+1464789394+adoAvatarcavatarmapitypeflashuid2uidundefined
这一整个字符串的md5是8b8605678cc1df874829ff785dc6b7d5
这里已经满足了第二个条件,可以成功进行哈希扩展长度攻击了
我们知道我们能伪造的字符串md5是这样的:
md5(32)+1464789394+adoAvatarcavatarmapitypeflashuid2uidundefined+somep padding + our data
前面这部分是不能变的,那时间是我们能控制的吗
答案是肯定,我们来看进行windidkey验证的部分
QQ20170520-191722@2x.png
beforeAction这个函数中
$_time是get得到的,是可控的
然后在if中把传进去的windidkey和php自己计算的进行对比,相同就通过,就能执行敏感操作:

if (WindidUtility::appKey($clent['id'], $_time, $clent['secretkey'], $this->getRequest()->getGet(null), $this->getRequest()->getPost()) != $_windidkey)  $this->output(WindidError::FAIL);

再来缕一下思路,我们知道的是
md5(32)+1464789394+adoAvatarcavatarmapitypeflashuid2uidundefined
这一部分的md5值,8b8605678cc1df874829ff785dc6b7d5
然后我们能构造的是
md5(32)+1464789394+adoAvatarcavatarmapitypeflashuid2uidundefined+somep padding + our data
这一部分的md5值
也就是说我们要让后台处理的时候,就是对我们能构造的这部分进行哈希操作。怎么办呢?
这里就体现了安全人员的机智了
我们把get某个变量名叫做adoAvatarcavatarmapitypeflashuid2uidundefined
然后把这个变量的值填写为somep padding,然后在post中加上我们的our data
这时,后台进行hash的字符串就是
md5(32)+1464789394+adoAvatarcavatarmapitypeflashuid2uidundefined+somep padding + our data

0x03.漏洞复现与poc

这里我利用的是刺总在12年发的一个js的哈希扩展长度攻击的脚本,完成了一个攻击函数md5_length_extension()
QQ20170520-191733@2x.png
我们解释一下,其中的secret就是我们未知的那32位的值,这里我们可以随便填,只要是32位就好
然后就是时间1464789394
然后是$str就是adoAvatarcavatarmapitypeflashuid2uidundefined
我们要加在最后的append_data格式其实是a=get&c=app&m=api&id=1
在phpwind中加密的时候就变成了agetcappid1mapi
然后old_md5是我们从头像处获取的8b8605678cc1df874829ff785dc6b7d5
我们来看看最后执行的结果
QQ20170520-191746@2x.png
最后我们猜测出来的md5是3d070e0f121335b4809deef0e799885f
对应的字符串是
32secret+1464789394adoAvatarcavatarmapitypeflashuid2uidundefined%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%B8%02%00%00%00%00%00%00agetcappid1mapi
我们测试一下
QQ20170520-191756@2x.png
我先在appKey中输出一遍,方便我们查看对比,也方便调试
QQ20170520-191823@2x.png
这里的windidkey是我们猜测的md5,来看看结果
QQ20170520-191833@2x.png
我这里把phpwind计算的windidkey打印出来了,跟我们猜测的一模一样
结果是我们查询的config都出来了,真实的secretkey也出来了
拿到了这个,应该可以很轻松的getshell了吧
这里刺总的代码中解释很详细了,懂原理的应该能很容易看懂
我就把利用代码贴上,大家自己去右键查看源代码吧
然后我还准备了一个python版本的,稍微加了点注释,介绍一下用法(源码中也写了用法,不懂的可以回去研究源码)
QQ20170520-191849@2x.png
也得到了正确的md5
-p是从头像处获取的md5
然后-b是之前的字符串被分为几组,之前是87个字符,然后64个位一组,一共是2组
-v是显示细节,最后跟上要加在最后的字符串
值得一提的是这里看不到对87到128的填充结果,因为位数固定,所以填充其实也是固定的
我们可以随便md5一个87位的字符串看填充过程
QQ20170520-191858@2x.png
这一部分是其实就是
%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%B8%02%00%00%00%00%00%00
我们可以看到是一样的结果

0x04.最后说两句

这个利用是真的赞,构造get的变量名
然后把填充内容作为值,这个思路很好,的确值得我们学习
贴poc
hash扩展长度攻击js脚本
hash扩展长度攻击py脚本
演示页面

Comments are closed.