Discuz! X系列远程代码执行漏洞分析

文章目录

0x00 漏洞概述


上周有一个朋友问我有没有办法在知道uc的appkey的情况下getshell,刚好我在原来看discuz代码时曾经有过几个相关的想法,但是一直没有仔细去看,接着这个机会去看了下,果然有个很好玩的代码执行漏洞。

0x01 漏洞根源


这个问题的根源在于api/uc.php文件中的updatebadwords方法,代码如下:

方法参数中的$get$post就是用户所传入的内容,从上面代码我们可以看出在解析$post内容之后,将其写入到名为badwords的缓存中。这里代码使用了var_export来避免用户传递单引号来封闭之前语句,注入php代码。

但是这里有两个关键词让我眼前一亮“findpattern”和“replacement”,也就是说这个缓存内容是会被作为执行的。那么如果我向findpattern中传入带有e参数的正则表达式,不就可以实现任意代码执行了吗?

0x02 漏洞触发


全局代码搜了下badwords,用的地方比较少,主要集中在uc的pm和user模块中。这里我用user来举例,在uc_client/model/user.php文件中有一个check_usernamecensor方法,来校验用户名中是否有badwords,如果有的话就将他替换掉,代码如下:


 

可以看到代码中使用了preg_replace,那么如果我们的正则表达式写成“/.*/e”,就可以在使用这个方法的地方进行任意代码执行了。而这个方法在disucz中,只要是添加或者修改用户名的地方都会用到。

0x03 漏洞利用


首先我们们访问api/uc.php(居然可以直接访问,好开心),之后我们会发现uc处理机制中比较讨厌的环节——用户传递的参数需要经过UC_KEY加密:


 

所以这里需要有个前提,需要知道UC_KEY或者可以操控UC_KEY。那么问题来了,我们要怎么达到这个前提呢?

我们在后台中站长->UCenter设置中发现有“UCenter 通信密钥”这个字段,这是用于操控discuz和uc连接的app key,而非高级的uc_server key,不过对于我们getshell来说足够了。在这里修改为任意值,这样我们就获取到了加密用的key值了。

2015081006105261769[1]

从下图我们可以看到,配置文件已经被修改了:

2015081006105247962[1]

然后我们在自己搭建的discuz的api/uc.php文件中添加两行代码,来加密get请求所需要的内容:

这样我们就可以获取到加密后的code值了!

2015081006105368463[1]

然后用post方法向api/uc.php发送带有正则表达式信息的xml数据包,请求头中有两个地方需要注意,一个是formhash,一个是刚才获取的code需要进行一次url编码,否则解密会出现问题。我使用的数据包如下图所示:

发送后可以发现uc_client/data/cache目录下的badwords.php内容变为了我们刚刚设定的正则表达式的样子:

2015081006105364148[1]

之后利用方法就有很多种了,可以通过增加一个用户来实现代码执行,也可以通过发消息的方式来触发,这里我以添加一个用户为例。

2015081006105355692[1]

2015081006105493258[1]

0x04 漏洞总结


漏洞小结

1.影响范围个人评价为“高”,Discuz! X系列cms在国内使用范围极广,几乎所有中小型论坛都是用它搭建的。

2.危害性个人评价为“高”,这个漏洞不只是单纯的后台代码执行,在uc_app key泄露的情况下也是可以利用的,很多转账对于uc_app key重视程度不是很大,所以相对来说危害性还是非常高的。

防护方案

限制用户提交正则表达式的内容,允许提交正则表达式就可以了,就不要让用户提交正则参数了吧。而且纯粹的使用正则表达式替换字符串,str_replace不可以吗?

原文链接:,转发请注明来源!

发表评论

要发表评论,您必须先登录