Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-25243 — CVE-2026-25243 — Redis RESTORE zipmap double-free → remote code execution (ASLR on). | Kitploit
도구/GitHubGitHub/dinosn/cve-2026-25243
Memory ForensicsVulnerability AnalysisExploitationReverse EngineeringPenetration TestingRemote Access ToolPayload DevelopmentBinary Exploitation
GitHubdinosn/cve-2026-25243

CVE-2026-25243

CVE-2026-25243 — Redis RESTORE zipmap double-free → remote code execution (ASLR on).

저장소 보기
132개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-25243 — Redis RESTORE zipmap 이중 해제 → 원격 코드 실행

TL;DR. 잘못된 형식의 DUMP 페이로드가 RESTORE에 전달되면 Redis의 레거시 해시-지맵 로더에서 힙 이중 해제가 발생합니다. 기본 jemalloc에서는 이중 해제가 조용히 발생하며(서버는 계속 실행됨), 이를 제어 가능한 타입 혼동 원시 요소로 전환합니다. 이 저장소는 이를 ASLR이 활성화된 상태에서 원격 코드 실행으로 연결합니다 — Redis 작업자가 system("<attacker string>")을 호출하고 계속 서비스를 제공합니다. DoS가 아닙니다.

root@kitploit:~
# default Redis (DEBUG disabled), ASLR on — the most self-contained exploit (NO libc offsets):
$ python3 exploits/poc_rce_aslr_pie_rop.py --cmd "id > /tmp/pwned_pie 2>&1"
[*] self-cal: blob_base=0x7f352d800009 blob_robj=0x7f353286b8d8 pie_base=0x557ea9149000  (NO libc)
[*] fake dictType F=0x7f352e013c36  g1=0x557ea93cca87 execve=0x557ea91cee80
$ cat /tmp/pwned_pie
uid=0(root) gid=0(root) groups=0(root),...    # <- execve("/bin/sh","-c",<cmd>) as the redis process

ASLR을 무력화하는 누출은 DEBUG를 사용하지 않습니다 — redis.call Lua C-클로저 주소를 읽습니다(EVAL 'return tostring(redis.call)'). 이는 이전 Redis 익스플로잇과 동일한 자체 포함된 DEBUG-프리 기술입니다. 그런 다음 blob_base/blob_robj 그리고 PIE 베이스는 오버리드(고정 오프셋 없음)로부터 런타임에 도출됩니다. PIE-ROP 마무리는 JOP 스택-피벗을 통해 execve@plt를 호출하므로 libc 주소를 전혀 사용하지 않습니다 — 유일한 빌드별 상수는 redis-server 바이너리에서 읽은 PIE-상대 가젯 오프셋으로, 이전 HLL 익스플로잇의 빌드별 가젯 테이블과 정확히 동일합니다. 기본 DEBUG가 비활성화된 서버에서 uid=0(root), ASLR 켜짐, 8/8을 확인했습니다.

두 가지 마무리가 제공됩니다. poc_rce_aslr_pie_rop.py(위)는 가장 자체 포함되어 있습니다 — libc 없음, 완전히 자체 보정됨 — 하지만 execve는 작업자를 대체합니다(리버스 셸 --cmd 사용; 실제 셸에 가장 적합). **poc_rce_aslr_selfcal.py**는 작업자를 유지합니다(system()이 포크됨) 두 개의 libc 버전 오프셋을 대가로. 서버를 계속 살려둘 필요가 있는지에 따라 선택하세요.


버그

RESTORE key 0 <DUMP-페이로드>는 직렬화된 객체를 역직렬화합니다. 레거시 RDB_TYPE_HASH_ZIPMAP (0x09) 유형의 경우, 검증기와 변환기가 길이 필드가 차지하는 바이트 수에 대해 의견이 일치하지 않습니다:

  • zipmapValidateIntegrity()는 실제 인코딩된 크기(과도한 길이의 0xFE 접두사의 경우 5)로 탐색합니다;
  • zipmapNext()는 zipmap → listpack 변환 중 디코딩된 길이가 < 254인 경우 1바이트를 사용합니다.

작은 길이가 과도한 길이의 5바이트 형태로 기록되면 유효성 검사를 통과하지만 zipmapNext()가 4바이트만큼 잘못 스트라이드하게 만듭니다. 동일한 잘못된 스트라이드로 인해 두 가지 결과가 발생합니다: 힙 오버리드(zipmap.c)와 Redis에서만 힙 이중 해제가 rdb.c 해시-지맵 로더에서 발생합니다:

root@kitploit:~
sds field = sdstrynewlen(fstr, flen);
if (!field || dictAdd(dupSearchDict, field, NULL) != DICT_OK || !lpSafeToAdd(lp, flen + vlen)) {
    dictRelease(dupSearchDict);   // (1) dictAdd took ownership of `field` -> freed here
    sdsfree(field);               // (2) freed AGAIN  -> double-free

Valkey는 이를 방어합니다(if (!field_added) sdsfree(field)); 업스트림 Redis는 그렇지 않으므로 이중 해제는 Redis 전용입니다. 수정 사항은 과도하게 인코딩된 짧은 길이를 거부하고 로드 시간 검사를 재정렬합니다.

익스플로잇 체인 (Redis 8.6.2, x86-64, jemalloc, PIE/NX/partial-RELRO)

root@kitploit:~
silent double-free  ->  type-confusion overlap  ->  arbitrary pointer-forge
   ->  forge a hashtable hash's  dict->type  to a fake dictType
   ->  HGET hd "<field>"   ==   dictFind -> type->hashFunction(field)
      libc path  (selfcal): hashFunction = &system            -> system("<cmd>")   (worker survives)
      PIE path   (pie_rop): hashFunction = JOP-pivot g1, field = ROP chain
                            -> leave;ret pivots rsp onto the field
                            -> execve("/bin/sh","-c","<cmd>")  via execve@plt        (no libc, no DEBUG)

가짜 dictType은 주소의 하위 바이트가 공격자 문자열의 sds 헤더와 일치하는 하나의 오프셋에서 16 MB 문자열(SETRANGE) 안에 심어집니다. ASLR은 런타임에 완전히 무력화됩니다:

  • system — 단일 힙-포인터 누출. 권장 경로는 DEBUG-프리입니다: redis.call Lua C-클로저의 주소(EVAL 'return tostring(redis.call)') — 이전 Redis 익스플로잇이 사용한 동일한 자체 포함된 누출. jemalloc 아레나는 libc에서 일정한 오프셋에 위치하므로, system = leaked_robj + Δlibc + system_off입니다. (DEBUG OBJECT는 스크립팅이 비활성화되었지만 DEBUG가 활성화된 경우에만 실험실 편의를 위한 것입니다 — 더 드문 구성.)
  • 16 MB blob의 주소 (독립적으로 무작위화된 mmap) — 버그 자체의 임의 읽기를 사용하여 읽습니다: SET의 dict를 위조하여 해당 멤버가 107 KB SDS_TYPE_32 sds가 되도록 하고, SMEMBERS가 인접한 힙을 오버리드하며, blob의 robj.ptr이 알려진 오프셋에서 읽힙니다.

전체 원시 단계별 분석과 어렵게 얻은 jemalloc / Redis-8.x 세부 정보(클래스-64 경계, dict 항목 태깅, 해시-필드 mstr, 키스페이스 사전 증가)는 WRITEUP.md를 참조하세요.

실험실

root@kitploit:~
docker build -t cve-2026-25243 .
# stock (jemalloc) demo — DoS-or-not? shows the type confusion (no tooling):
docker run --rm -p 6379:6379 cve-2026-25243

# full chain — DEFAULT config (DEBUG disabled), the recommended exploit:
sysctl -w kernel.randomize_va_space=2            # ASLR ON
redis-server &                                   # DEBUG is off by default
python3 exploits/poc_rce_aslr_selfcal.py --host 127.0.0.1 --port 6379 --cmd "id > /tmp/pwned 2>&1"

ASLR 무력화 누출 (DEBUG 없음)

부트스트랩 힙-포인터 누출은 이전 Redis 익스플로잇과 동일한 접근 방식을 따릅니다: redis.call Lua C-클로저 주소를 EVAL 'return tostring(redis.call)'로 누출합니다. Lua 스크립팅은 기본적으로 켜져 있고; DEBUG는 기본적으로 꺼져 있습니다 (enable-debug-command no) — 따라서 Lua 누출이 현실적인 기본이고, DEBUG OBJECT (poc_rce_aslr.py)는 실험실 편의에 불과합니다. 그런 다음 poc_rce_aslr_selfcal.py는 오버리드로부터 런타임에 blob_base와 blob_robj를 도출합니다 (16 MB-blob robj 서명 검색), 따라서 DLUA/DFOBJ는 가까이 있기만 하면 됩니다.

system 마무리의 경우 작은 힙 오버리드에는 libc 포인터가 포함되지 않으므로 libc를 자체 도출할 수 없습니다 — poc_rce_aslr_selfcal.py는 두 개의 libc 버전 오프셋(DLIBC, SYSTEM_OFF)을 유지합니다. poc_rce_aslr_pie_rop.py 마무리는 해당 의존성을 완전히 제거합니다: 동일한 오버리드가 PIE 포인터를 가지고 있습니다(공유된 dictType이 반복적으로 나타남), 따라서 PIE 베이스는 most-common-PIE-value − DICTTYPE_OFF로 자체 보정되며, 체인은 JOP 스택-피벗(mov rbp,rdi; call *0x8(rax) → leave;ret가 rsp를 공격자가 제어하는 HGET 필드로 피벗하며, 이 필드는 바로 execve("/bin/sh","-c",<cmd>) ROP 체인입니다)을 통해 execve@plt로 끝납니다. 유일한 빌드별 상수는 redis-server에서 읽은 PIE-상대 가젯 오프셋입니다 — 이전 HLL 익스플로잇이 ELF 빌드-ID당 가젯 테이블을 키로 사용하는 것과 정확히 같이 /로 대상별로 추출합니다. libc 주소는 사용되지 않습니다.

스크린샷

screenshots/05-pie-rop-libc-free.png (NO libc 자체 보정 + uid=0, 가장 자체 포함된 실행), 01-rce-aslr-on.png (uid=0 결정적 장면), 02-reliability.png (5/5), 03-exploit-chain.png (코드), 04-debug-free-selfcal.png (기본 Redis에서 DEBUG-프리, 자체 보정 system 실행).

영향 및 영향을 받는 버전

  • 원격, 특별한 권한 없음. RESTORE는 일반 명령입니다 — 인증되지 않거나 노출된 Redis(requirepass 없음)에서 연결된 모든 클라이언트가 실행할 수 있습니다; 인증된 인스턴스에서는 ACL -restore 거부가 없는 모든 사용자가 실행할 수 있습니다. 다른 Redis RCE에서 사용되는 데이터 구조 명령과 동일한 액세스 프로필입니다.
  • 확인됨: 조용한 힙 이중 해제, 타입 혼동, 임의 프로세스 메모리 읽기(키/비밀/포인터를 유출하는 정보 누출), 원격 코드 실행(이 저장소).
  • 영향 받는 버전: Redis < {6.2.22, 7.2.14, 7.4.9, 8.2.6, 8.4.3, 8.6.3} — 즉 6.2.x부터 현재 8.x까지; Valkey는 DoS/오버리드만 해당(field_added 가드가 이중 해제를 차단함).

완화 조치

수정된 릴리스로 업그레이드하세요. 업그레이드할 수 없는 경우: RESTORE 제한 (ACL … -restore), Redis를 인증 없이 노출하지 말고, DEBUG를 비활성화하세요.


승인된 보안 연구, 방어자 인식을 위해 공개됨. 소유하지 않거나 명시적 테스트 권한이 없는 시스템에 대해 실행하지 마십시오.

도구 다운로드
파일설명
★ exploits/poc_rce_aslr_pie_rop.py가장 자체 포함됨 — 기본 Redis에서 RCE (DEBUG 꺼짐), libc 오프셋 없음; blob_base/blob_robj/pie_base 자체 보정; JOP 피벗을 통한 execve@plt (작업자 대체됨). 8/8.
★ exploits/poc_rce_aslr_selfcal.py작업자 유지 — 동일한 체인이지만 hashFunction=&system (포크); 두 개의 libc 버전 오프셋 필요 (DLIBC/SYSTEM_OFF). Lua-클로저 누출, blob_base/blob_robj 자체 보정.
exploits/poc_rce_aslr_nodebug.pyDEBUG-프리 (Lua 누출), 하지만 고정 오프셋 사용 (DEBUG 켜짐 상태에서 보정됨)
exploits/poc_rce_aslr.py실험실 편의 변형: DEBUG OBJECT 부트스트랩 누출 (DEBUG 활성화 필요)
exploits/poc_rce_aslr_off.pyASLR 꺼짐 상태에서 RCE (보정된 주소)
exploits/poc_typeconfusion.py이중 해제 → 두 키가 하나의 힙 버퍼를 공유 (도구 없음)
exploits/poc_doublefree.py이중 해제 (ASan: sdsfree에서 힙-사용-후-해제)
exploits/poc_dos_overread.py오버리드 충돌 (ASan)
ROPgadget
objdump