Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-42945 — CVE-2026-42945에 대한 전체 연구 저장소: 힙 버퍼 오버플로우 분석, RCE 익스플로잇(힙 스프레이 + Feng Shui), 탐지 스크립트, NGINX rewrite 모듈 취약점에 대한 패치 가이드 포함. | Kitploit
도구/GitHubGitHub/quantumworld-dpdns-io/cve-2026-42945
Vulnerability AnalysisExploitationWeb SecurityFuzzingPenetration TestingLearning & EducationIncident ResponseBinary ExploitationLabs & Practice
GitHubquantumworld-dpdns-io/cve-2026-42945

CVE-2026-42945

CVE-2026-42945에 대한 전체 연구 저장소: 힙 버퍼 오버플로우 분석, RCE 익스플로잇(힙 스프레이 + Feng Shui), 탐지 스크립트, NGINX rewrite 모듈 취약점에 대한 패치 가이드 포함.

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
Screenshot 2026-05-28 at 4 09 53 PM

CVE-2026-42945 — NGINX Rift

NGINX ngx_http_rewrite_module의 힙 버퍼 오버플로우

MetricValue
CVSS v4.09.2 (위험)
CVSS v3.18.1 (높음) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWE122 — 힙 기반 버퍼 오버플로우
도입됨2008년 6월 — v0.6.27
발견됨2026년 4월 — DepthFirst Research
수정됨2026년 5월 13일 — v1.30.1, v1.31.0
CVE 게시됨2026년 5월 21일
수명약 18년 (미탐지)
수정 커밋524977e7c534e87e5b55739fa74601c9f1102686

목차

  1. 취약점 요약
  2. 근본 원인 분석
  3. 악용 메커니즘
  4. 수정 분석
  5. 영향 받는 버전
  6. 탐지
  7. 완화
  8. 프로젝트 구조
  9. 빠른 시작
  10. 취약한 버전 빌드 및 실행
  11. 오버플로우 트리거
  12. RCE 익스플로잇
  13. 리버스 셸 확인
  14. 패치 적용
  15. 테스트
  16. 퍼징
  17. CI 파이프라인
  18. 문서 색인
  19. 프로젝트 통계
  20. 참고 자료

1. 취약점 요약

인증되지 않은 원격 공격자가 특정 rewrite + set/if/rewrite 구성 패턴을 가진 서버에 조작된 HTTP 요청을 전송하여 NGINX 워커 프로세스에서 결정론적 힙 버퍼 오버플로우를 트리거할 수 있습니다. 오버플로우는 힙 메타데이터(ngx_pool_cleanup_t 포인터)를 손상시켜 힙 스프레이 및 풍수 기법을 통해 **원격 코드 실행(RCE)**을 가능하게 합니다.

트리거 패턴```nginx

server { listen 19321;

location ~ ^/api/(.*)$ {
    rewrite ^/api/(.*)$ /internal?migrated=true;
    set $original_endpoint $1;
}

}

**Key requirements:**
- A `rewrite` directive whose replacement contains `?` (query-string separator)
- A subsequent `set`, `if`, or `rewrite` directive that references an **unnamed PCRE capture** (`$1`, `$2`, etc.)
- The `?` in the rewrite replacement triggers `ngx_http_script_start_args_code` which sets `e->is_args = 1`

### 공격자가 달성할 수 있는 것

| 능력 | 설명 |
|-----------|-------------|
| **서비스 거부(DoS)** | 작업자 프로세스를 결정적으로 충돌시켜 재시작 루프를 유발 (ASLR과 무관하게 작동) |
| **원격 코드 실행(RCE)** | ASLR이 비활성화된 경우(또는 부분 덮어쓰기로 우회 시) nginx 사용자 권한으로 완전한 RCE 달성 |
| **데이터 유출** | 메모리 읽기 프리미티브를 통해 작업자 힙에서 민감한 데이터 추출 |
| **지속성** | 작업자 프로세스 메모리에서 코드 실행을 통해 백도어 설치 |

---

## 2. 근본 원인 분석

### 두 패스 스크립트 엔진

NGINX의 `ngx_http_rewrite_module`은 `src/http/ngx_http_script.c`에서 **두 패스 스크립트 엔진**을 사용합니다.

1. **길이 패스** (`ngx_http_script_run`): 모든 스크립트 코드를 순회하며 필요한 총 버퍼 크기를 계산합니다. 길이를 `le.ip`와 `le.pos`에 기록합니다.
2. **복사 패스** (`ngx_http_script_copy_len`/`_code`): 다시 순회하며 미리 할당된 버퍼(`e->ip`, `e->pos`)에 실제 바이트를 기록합니다.

각 스크립트 코드에는 각 패스에 대한 두 개의 핸들러가 있습니다. 예를 들어:
- `ngx_http_script_copy_len` → `ngx_http_script_copy_code`
- `ngx_http_script_start_args_len` → `ngx_http_script_start_args_code`

### `is_args` 플래그

**엔진 구조체**(`ngx_http_script_engine_t`)의 `e->is_args` 플래그는 복사 패스가 특정 문자를 처리하는 방식을 제어합니다.```c
typedef struct {
    u_char                  *ip;
    u_char                  *pos;
    ngx_http_variable_value_t *sp;
    ngx_str_t               buf;
    int                     flushed;
    unsigned                is_args:1;    // <-- THE BUG
    unsigned                ncaptures:1;
    ngx_uint_t              captures_size;
    // ...
} ngx_http_script_engine_t;

When e->is_args = 1일 때, $N 캡처 참조에 대한 복사 코드는 NGX_ESCAPE_ARGS와 함께 ngx_escape_uri()를 호출하며, 이는 다음을 확장합니다:

  • + → %2B (1바이트 → 3바이트, +200%)
  • % → %25 (1바이트 → 3바이트, +200%)
  • & → %26 (1바이트 → 3바이트, +200%)

버그: 패스 간 플래그 누출

취약한 패턴에 대한 실행 흐름:``` rewrite ^/api/(.*)$ /internal?migrated=true;

1. **재작성 평가** 중에 엔진은 대체 문자열에서 `?`를 만나 `ngx_http_script_start_args_code`를 트리거하여 `e->is_args = 1`을 설정합니다.
2. 재작성은 요청 URI를 수정한 후 다음 지시어로 계속 진행됩니다.
3. **`e->is_args`는 절대 지워지지 않습니다**.

그 다음:```
set $original_endpoint $1;
  1. 새로운 하위 엔진 (le)이 길이 패스를 위해 생성됩니다: ```c ngx_memzero(&le, sizeof(ngx_http_script_engine_t));

이는 올바르게 le.is_args = 0으로 설정하여, 길이 전달이 원시, 이스케이프되지 않은 캡처 길이를 반환하게 합니다.

  1. 복사 전달은 1단계에서 여전히 e->is_args = 1로 설정된 메인 엔진 e를 재사용합니다. 복사 전달은 URI 이스케이프를 적용하여, 원시 길이에 맞게 크기가 지정된 버퍼 내부에서 이스케이프 가능한 각 문자를 1바이트에서 3바이트로 확장합니다 — 힙 오버플로우.

시각적 분석```

Pass 1 (Length — sub-engine le): le.is_args = 0 capture $1 = "A+++++B" → length = 7

Buffer allocated: 7 bytes

Pass 2 (Copy — main engine e): e.is_args = 1 ← LEAKED from rewrite capture $1 = "A+++++B" ngx_escape_uri("A+++++B", NGX_ESCAPE_ARGS): A → A (1 byte) + → %2B (3 bytes) ← EXPANSION + → %2B (3 bytes) + → %2B (3 bytes) + → %2B (3 bytes) + → %2B (3 bytes) B → B (1 byte) total written: 17 bytes buffer size: 7 bytes OVERFLOW: 10 bytes

확장 비율은 `7 + (n_escapable * 2)`이며, 여기서 `n_escapable`은 캡처 내 `+`, `%`, `&`의 개수입니다.

---

## 3. 공격 메커니즘

### 개요

| 단계 | 기법 | 설명 |
|------|-----------|-------------|
| 1 | 오버플로우 | `+` 패딩이 포함된 조작된 URI를 전송하여 힙 버퍼를 오버플로우 |
| 2 | 힙 스프레이 | `/spray`에 대용량 본문을 POST하여 제어된 데이터로 힙을 채움 |
| 3 | Feng Shui | 오버플로우 대상(`ngx_pool_cleanup_t`)이 인접하도록 할당 배치 |
| 4 | 핸들러 변조 | 오버플로우가 `ngx_pool_cleanup_t.handler`를 `system()` 주소로 덮어씀 |
| 5 | 정리 트리거 | 풀 소멸을 기다렸다가 → `system(cmd)`가 공격자 명령을 실행 |
| 6 | 리버스 셸 | 대화형 접근을 위해 리버스 셸 페이로드로 연결 |

### 크로스 요청 Feng Shui

**단일 요청 Feng Shui는 실패**합니다. 오버플로우가 `cleanup` 포인터에 도달하기 전에 풀의 메타데이터(`->d.next`, `->d.failed`)를 손상시키기 때문입니다. 요청 종료 시 풀이 소멸되면, 손상된 메타데이터로 인해 **`system()`이 호출되기 전에 충돌**이 발생합니다.

대신, 익스플로잇은 **크로스 요청 Feng Shui**를 사용합니다:
1. **요청 1 (스프레이)**: `/spray`에 대용량 본문을 POST합니다. 백엔드(`server.py`)가 `X-Delay` 헤더로 응답을 보류하여 연결을 유지하고 힙 할당을 보존합니다. 스프레이는 힙을 가짜 `ngx_pool_cleanup_t` 블록으로 채웁니다.
2. **요청 2 (오버플로우)**: 오버플로우 URI를 전송합니다. 오버플로우는 풀 메타데이터가 아닌 `cleanup` 포인터만 손상시켜, 스프레이된 가짜 블록을 가리키도록 합니다.
3. **풀 소멸**: 스프레이 응답이 완료되면(지연 만료), 풀의 정리 체인이 가짜 블록으로 이동하여 `system(cmd)`를 호출합니다.

### 주소 요구 사항

| 심볼 | 값 (Docker, ASLR 해제) | 설명 |
|--------|--------------------------|-------------|
| `HEAP_BASE` | `0x555555659000` | nginx 힙의 기준 주소 |
| `system@libc` | `0x7ffff6f6e420` | glibc의 `system()` |
| `NGX_CYCLES_POOL` | `0x5555556a4040` | 사이클 풀 포인터 |
| 가짜 정리 주소 | `0x5555556a4030` | 스프레이 대상 주소 |

### ASLR 우회

ASLR을 비활성화하지 않더라도 **DoS**(충돌)는 결정적으로 작동합니다. ASLR이 활성화된 상태에서 RCE를 달성하려면 두 가지 접근 방식이 있습니다:

1. **부분 덮어쓰기**: 1바이트 또는 2바이트 덮어쓰기를 사용하여 동일한 페이지 내에서 포인터를 이동시키고, 남은 니블을 브루트포싱합니다(16~256회 시도).
2. **정보 누출**: `/proc/self/maps`를 읽거나 `log_parser.py` 메모리 분석을 사용하여 레이아웃을 확인합니다.

---

## 4. 수정 분석

### 공식 수정

**커밋**: `524977e7c534e87e5b55739fa74601c9f1102686`  
**파일**: `src/http/ngx_http_script.c`  
**라인**: ~1205 (`ngx_http_script_regex_end_code` 내)```diff
 void
 ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
 {
     ngx_http_script_regex_code_t *code;

     code = (ngx_http_script_regex_code_t *) e->ip;

+    e->is_args = 0;    /* ← THE FIX */

     e->ip += sizeof(ngx_http_script_regex_code_t);
     // ...
 }

이 위치가 올바른 이유

ngx_http_script_regex_end_code는 모든 정규식 평가 후 길이 및 복사 패스 동안 실행됩니다. 여기서 e->is_args = 0을 재설정하면 다음이 보장됩니다:

  • 플래그는 정규식 코드 실행이 완료된 즉시 지워집니다.
  • 이후의 스크립트 코드(set, if, rewrite)는 is_args = 0 상태로 시작합니다.
  • ngx_http_script_start_args_code는 교체 문자열에서 ?를 만나면 여전히 is_args = 1을 설정할 수 있습니다. 이 수정은 해당 기능을 손상시키지 않습니다.

심층 방어 패치

patches/0002-hardening-bounds-check.patch는 ngx_http_script_copy_capture_code에 범위 검사를 추가합니다.```c if (e->pos + len > e->buf.data + e->buf.len) { return; /* gracefully truncate instead of overflowing */ }

### 백포트 패치

| 패치 | Nginx 버전 |
|-------|---------------|
| `patches/0001-fix-is_args.patch` | 1.22.x, 1.24.x, 1.26.x, 1.30.0 |
| `patches/backport-1.22.x.patch` | 1.22.0–1.22.1 |
| `patches/backport-1.24.x.patch` | 1.24.0–1.24.1 |
| `patches/backport-1.26.x.patch` | 1.26.0–1.26.1 |

---

## 5. 영향을 받는 버전

### NGINX 오픈 소스
도구 다운로드