利用redis写webshell

我发在安全脉搏的一篇文章,废话有点多见谅:http://www.secpulse.com/archives/5357.html

最近自己在做一些个人的小创作、小项目,其中用到了mongodb和redis,最初可能对这二者没有深入的认识。都是所谓的“非关系型数据库”,有什么区别么?实际上,在我看来,redis的角色更接近于memcache,而mongodb是一个真正的数据库。redis是一个key-value型数据库,信息以键对应值的关系存储在内存中,比memcache较大的优势就在于其数据结构的多样性。

说它不算一个真正意义上的数据库,因为redis是主要把数据存储在内存中(当然可以把其存储至硬盘上,这也是写shell的必要条件之一),其“缓存”的性质远大于其“数据存储”的性质,其中数据的增删改查也只是像变量操作一样简单。而mongodb却是一个“存储数据”的系统,增删改查数据的时候有“与或非”条件,查询数据的方式也能像SQL数据库一样灵活,这是redis所不具备的。

所以在我的项目中,redis作为session、任务队列的存储器,而mongodb作为数据(包括用户信息等)的存储器。

进入正题,昨天看到freebuf上已经说了redis可能造成的安全问题,提到了写文件,那么我在这里把方法说明一下吧。

redis安装完成以后有自己的命令行,也就是redis-cli,其中包含的命令可以在:http://redis.io/commands 进行查阅。各个客户端基本也就是依照这个命令去增删改查。

之前说了redis的数据主要保存在内存中,当与memcache不同之处在于,我们可以随时执行“save”命令将当前redis的数据保存到硬盘上,另外redis也会根据配置自动存储数据到硬盘上。

这不得不说到redis的持久化运作方案 http://redis.io/topics/persistence ,其中说到的一个RDB,一个AOF。RDB更像一个数据库备份文件,而AOF是一个log日志文件。我们可以设置让redis再指定时间、指定更改次数时进行备份,生成RDB文件;而设置AOF,可以在操作或时间过程后将“日志”写入一个文件的最末,当操作越来越多,则AOF文件越来越大。

二者是相辅相成的,通过二者的配合我们能够稳定地持久地将数据存储于服务器上。

而我们就是利用这些储存数据的操作,来进行任意文件写入。redis的配置中,有几个关键项目:

  • dir 指定的是redis的“工作路径”,之后生成的RDB和AOF文件都会存储在这里。
  • dbfilename RDB文件名,默认为“dump.rdb”
  • appendonly 是否开启AOF
  • appendfilename AOF文件名,默认为“appendonly.aof”
  • appendfsync AOF备份方式:always、everysec、no

经过我的研究发现,我们可以将dir设置为一个目录a,而dbfilename为文件名b,再执行save或bgsave,则我们就可以写入一个路径为a/b的任意文件:

QQ20150313-1@2x.png

当我们获得了一个redis控制台,我们可以调用config set/get等命令对redis的部分配置进行修改。而恰好的是,我们可以通过config set来更改dir和dbfilename。也就是说我们可以不用修改redis.conf,也不用重启redis服务就可以写入任意文件:

config set dir /home/wwwroot/default/
config set dbfilename redis.php
set webshell "<?php phpinfo(); ?>"
save

当我们随便set一个变量webshell的值为"<?php phpinfo(); ?>"后,即可对服务器进行getshell。可见已写入:

QQ20150313-3@2x.png

导出的RDB实际上是一个二进制文件,但因为其中包含<?php phpinfo(); ?>,所以被解析了:

QQ20150313-2@2x.png

在前图中,我们可以看到其实还生成了一个appendonly.aof,这个文件名能不能自定义呢?可惜的是,appendfilename的值并不能使用config set命令定义:

QQ20150313-4@2x.png

但仅有的一个dbfilename已经足够了。所以,以后如果扫到redis未授权访问,先别急着提交乌云。看看服务器有没有web服务,如果有,不妨试试能不能拿下webshell。

赞赏

喜欢这篇文章?打赏1元

评论

Stone 回复

在实际操作中可能会有问题
redis在生产环境里面数据量经常是十分庞大的
save到php文件里会超过php的允许文件大小,导致无法解析
而且save也不支持仅写入某个数据库,而是只能保存整个redis的实例
所以select到某个空数据库来写入shell也是无法试验的

phithon 回复

@Stone:这个我已经在zone里说过了,技术上是完全没问题的,直接flushall全删掉即可。或者先备份再删,之后再进行恢复。

Stone 回复

@phithon:666 学习了

Stone 回复

@phithon:可惜就是没胆量2333

phithon 回复

@Stone:因为你得到回报的不值得你冒险。。

helen 回复

囧囧囧,早发现可以写shell就爽了。。。

captcha