作者:Alpha 天融信阿尔法实验室
0x00 前言
Discuz!ML是一个由CodersClub.org创建的多语言,集成,功能齐全的开源网络平台,用于构建像“社交网络”这样的互联网社区。
该引擎基于Comsenz Inc.创建的着名的Discuz!X引擎开发。
0x01 漏洞描述
2019年7月11日, Discuz!ML被发现存在一处远程代码执行漏洞,攻击者通过在请求流量的cookie字段中的language参数处插入构造的payload,进行远程代码执行利用,该漏洞利用方式简单,危害性较大。
本次漏洞是由于Discuz! ML对于cookie字段的不恰当处理造成的
cookie字段中的language参数未经过滤,直接被拼接写入缓存文件之中,而缓存文件随后又被加载,从而造成代码执行
简而言之,如下图流程可以简单的理解该漏洞
首先,通过cookie传入payload,构造好的payload被写入template文件中
接着,这个被插入payload的template.php文件被include,造成代码执行
0x02 受影响的系统版本
Discuz! ML v.3.4
Discuz! ML v.3.3
Discuz! ML v.3.2
0x03 漏洞分析
本次漏洞是由于Discuz! ML于对于cookie字段的不恰当处理造成的
程序对cookie中的language字段的操作过程,位于sourceclassdiscuzdiscuz_application.php中
在这里,从cookie中取出language值,未经过滤,直接赋值给$lng变量
接着将$lng值赋值给名为DISCUZ_LANG的常量
在Discuz! ML中,在生成cachefile名时,需要使用到DISCUZ_LANG这个常量进行拼接
由于DISCUZ_LANG常量由cookie中传递而来,并未经过任何过滤,因此DISCUZ_LANG常量可控
在程序运行时,Discuz! ML会将template/default/common目录下的默认模板写入缓存
在这个过程中,程序首先会打开并读取位于template/default/common目录下默认模板中的内容:
这里将读取的header.htm模板中的内容赋值给$template变量
再读取默认模板内容之后,程序接下来通过preg_replace_callback方法对模板内容进行替换与修改
在对默认模板内容进行修改时,注意如下图片中操作
上图操作中,会将’$tplfile’, ‘$fname’, “.time().”, ‘$templateid’, ‘$cachefile’, ‘$tpldir’, ‘$file’这些变量值拼接到名为headeradd的变量中
Headeradd变量随后被拼接到$template中
注意这里的headeradd变量
如上图红圈处,这里将cachefile变量拼接到headeradd变量中,间接的将cachfile变量拼接到template中。
还记得cachefile变量吗?
Cachefile变量的值,其中一部分是可控的
例如上图,我们可以在其中插入形如 sc.’phpinfo().’的payload
这个payload随着headeradd变量,被带入template中
接下来,被污染的template值被写入缓存文件中
如上图可见,最终写入的缓存文件名即为cachefile的值,内容即为template值,Payload已经随着headeradd拼接到template而被写入这个缓存文件中
上图这里看起来比较杂乱,简化起来如下图
当缓存文件被注入如上文payload后,再次加载程序,
当程序执行到位于sourcemoduleforumforum_index.php处时:
可见上图432行,会使用include方法包含 template方法的返回值
跟进Template方法,找到其返回值,即是此处被include中的内容
Template方法位于sourcefunctionfunction_core.php
在其654行处,可见返回cachefile路径
cachefile即为上文被植入payload的文件
由此,被插入payload的缓存文件被include,其中构造好的payload被执行,造成代码执行漏洞
0x04 修复建议
目前官方没有进行修复,请时刻关注:https://bitbucket.org/vot/discuz.ml/commits/all,等待官方补丁。