忘记密码?

一键登录

草根吧源码论坛

discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用

查看: 146|回复: 0

discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用

[复制链接]

1706

主题

2177

热度

591

贡献

民审

Rank: 8Rank: 8

发表于 2016-6-30 17:40:08 | 显示全部楼层 |阅读模式 | 百度  360  谷歌 
分享到:
discuz是国内社区、、论坛使用范围最广泛的系统,近期又被爆出了新的漏洞,本文将详细介绍整个漏洞的原理,小伙伴们快来围观啦~


0X01 准备工作

jannock发的discuz有条件远程命令执行,很多大站受影响,网上还没公布细节,在某安全公众号上看到jannock简单的说了一下原理,是ssrf+redis/memcache的问题,一般的站也用不着redis/memcache这种缓解网站压力的应用,所以基本是大站才会受影响,本着学习的态度,顺着这个思路,还原了一下整个漏洞

http://www.wooyun.org/bugs/wooyun-2016-0214429

其中redis和memcache的原理是一样的,drops上有一篇利用memcache攻击的文章 附链接:

http://drops.wooyun.org/papers/8261

我在这里就还原利用redis的攻击方法

讲原理之前先来说说redis/memcache是干嘛的呢?其实可以把它们理解成一个高性能的数据库,当网站的缓存很大的时候,利用redis/memcache来处理缓存可以提高网站的性能,在dz的后台也可以看到是否在使用redis/memcache

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
首先你要自己在服务器上安装redis,然后php默认没有redis扩展,还需要安装phpredis扩展,顺便说一下,phpredis的2.1版本兼容性不太好,安装上去后无法访问网站,用2.28版本就可以了,配置这个环境是花了我一下午的时间,其中很多曲折,都不是重点,安装之后在phpinfo()中能看到redis

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
在dz的配置文件config_global.php中填入redis的地址就可以了,端口全都是默认的6379,prefix是dz中随机生成的,默认无密码

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
都完成之后在dz后台能看到运行情况

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
简单说一下redis的使用吧,启动之后在本机的6379端口会运行起来redis的服务,redis可以理解为一个数据库,数据以key=>value这样的形式储存,其实更像一个数组,使用如下

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程

Redis还支持eval “lua命令”这样来执行,我们在后面会用到,简单的例子如下:

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程

0X02  漏洞原理与复现

简单的说,漏洞就是通过ssrf来操作redis,更改了全局变量的值,导致任意代码执行

当dz设置使用缓存后,初始化时会把缓存内容加入全局变量$_G

Source/class/discuz/discuz_application.php中设置

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程

而在调用缓存的地方source/fucntion/function_core.php中

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
其中,关键点的两个变量我们都可以通过redis修改,来getshell为了方便测试,可改为:

$_G['setting']['output']['preg']['search']=”/.*/e”;
$_G['setting']['output']['preg']['replace']=”phpinfo();”;

我们来看看哪些地方可以触发漏洞,搜索一下output_replace()发现只在function output和function output_ajax中用到了,两个函数中应该都可以触发,挑output_ajax来看看

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
一开始我准备在划线的if前面print_r一下if判断中的全局变量

$_G['setting']['r ewritestatus']

但是什么也打印不出来,最后发现是前面的ob_get_contents()这个函数的问题,这个函数会把输出的值存到缓存中,并不会打印到浏览器页面上,那怎么看这个变量的值呢?还可以把这个变量写到txt文件中,再来查看。 发现正常运行情况下,if判断是不满足的,其中:

$_G['setting']['rewritestatus'] =0

所以我们在修改缓存值的时候还需要把它改为1,接着看看output_ajax()在哪些地方用到了

在/data/template/1_1_common_footer_ajax.tpl.php中:

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
这个文件用到的地方很多,比如在forum_ajax中:

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
这个地方对应的地址是:

/forum.php?mod=ajax&action=getthreadtypes&inajax=yes

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程

然后我们看下如何通过redis修改缓存值,dz使用redis时,全局变量 $_G[‘setting’]放在xxxx_setting中的,其中前缀就是前面 config_global.php 中的prefix的值,那我们这里的全局变量是放在 5Z13gm_setting 中的,我们来看看

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
里面数据很多,我们可以看到这里是序列化之后再放进去的,格式是$a['output']['preg']['search']['plugins']这样的,那么我们写个脚本操作

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
这里我们的redis是没有设置密码的,一般网站会设置密码(通过dz的ssrf的话就不考虑密码的问题,在config_global.php中别人都帮我们设置过了),运行脚本之后,我们再访问:

/discuz/forum.php?mod=ajax&inajax=yes&action=getthreadtypes

成功getshell

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
有的同学会注意到,前缀我们是不知道的啊,那不就不能修改数据了吗?但是redis是支持模糊查询的,可以通过keys方法,举个例子

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
我们是要通过ssrf来操作redis,怎么通过一个链接来操作呢?dz的ssrf是默认调用curl请求,因此会支持gopher或者dict协议,这对我们已经足够了,我们写个脚本发送利用curl发送gopher请求。

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
%0D%0A是换行符,相当于执行下一条指令,这里set前面加了一个x是因为/后面的第一个字符不会被当做指令,我们执行的指令其实是set name cheng

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
这里返回ok就是表示我们执行成功,这样就相当于在命令行中执行redis的指令,有个问题,还是前缀的问题,我们的前缀是可以通过指令keys *_setting获取到,但是ssrf的时候看不到返回值的,我们没有办法获取到返回值,那怎么办?这里我们就要用到lua脚本,前面提到了,redis是可以通过eval来执行lua脚本的,我们看看我们的lua脚本

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程

通过keys方法把xxx_setting保存到v中,然后set v xxxx,这样就不会拥有前缀未知的问题了,gopher的链接就是:

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
执行结果:

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
最后return 1了,说明执行成功,刷新页

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
成功getshell,因为我们破坏了5Z13gm_setting中的数据,会导致网站访问异常

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
利用flushdb命令重置redis中的数据,再刷新才能恢复访问

0X03  遗憾与感想

讲到这里整个漏洞基本复现完了,剩下结合 ssrf 的复现,我在脚本里已经是使用 curl 来发送请求的,所以通过ssrf 来实现应该也不是问题,遗憾的是我手上并没有合适的 ssrf

为什么说ssrf也要合适,因为我们看到我们的链接是:

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程

当中包含了很多特殊字符,而且脚本在里面也不方便去构造满足条件的ssrf,比如dz最新版倒是有一个ssrf,是jannock之前发的一个:

http://www.wooyun.org/bugs/wooyun-2015-0151179

这个漏洞还能利用

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
但是这个利用起来就有条件,比如链接必须是图片链接,最后要是.jpg,协议必须是http

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程
因为是在链接中,还不能包含特殊字符,不然会被xss_check拦截

草根吧 discuz利用ssrf+ 缓存 应用getshell漏洞执行方法和exp利用 discuz,数据库,小伙伴,文章,网上 精品教程

如果能有合适的ssrf,就能够前台getshell了

认真想了想,这个漏洞本质上是通过 gopher 协议操作 redis 修改全局变量,也不好去补,把全局变量不放到redis 中处理?这是一个方法,但是又会降低使用 redis 后网站效率, dz 能做的就是处理好 ssrf 的地方,不要提供跳板让攻击者能够 getshell ,以后 dz 出一个 ssrf 对于这些使用 redis 的大站来说全都是一个 getshell 的威胁,这也挺难受的。 最后提一点, redis 使用的时候一定要设置密码和访问权限, redis 出现未授权访问可以很轻易的拿到 root 权限,具体可以看 wooyun 实例

http://www.wooyun.org/bugs/wooyun-2015-0152710

帖子地址: 

本文来源于草根吧源码论坛 www.caogen8.co,欢迎大家下载。
如果您没有贡献需要充值,可以直接在线充值,点击充值
如果你需要加入本站赞助VIP会员,可以直接在线开通,点击开通
如果找不到您要的资源,请搜索一下,点击搜索
回复

举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆 用百度帐号登录 一键登录:

本版积分规则

收藏帖子 返回列表 搜索
快速回复 返回顶部 返回列表