
CVE-2026-109618/109619 — 5개의 RCE 체인 + 탐지 규칙(Suricata, Sigma, ModSecurity). PHP session.upload_progress 사전 인증(pre-auth) 익스플로잇 연구.
CVE-2026-109618 & CVE-2026-109619 — PHP 인증 전 RCE 익스플로잇 및 탐지 툴킷
PHP의 session.upload_progress와 Zend 엔진의 OOM bailout을 악용하는 다섯 가지 독립적인 RCE 체인. 14년간의 취약한 코드 — PHP 5.4.0(2012)부터 8.5.11까지. 인증 전. 일부 체인은 애플리케이션 취약점이 전혀 필요하지 않습니다.
전체 웹사이트의 78% 에 영향을 미칩니다 — WordPress(43%), Joomla, Drupal, Laravel, Magento 및 모든 기본 PHP 설치를 포함합니다.
저자: Qi Deng | 기술 분석: Substack | 날짜: 2026-10-21
| CVE | GHSA | CVSS | 설명 |
|---|---|---|---|
| CVE-2026-109618 | GHSA-w8hw-w9fx-j79w | 9.2 | OOM → longjmp()로 인해 Zend 엔진 상태가 무효화됨 → RCE |
| CVE-2026-109619 | GHSA-6wmf-4rv5-p3rp | 9.2 | FPM 워커 요청 간 전역 상태 잔존 → UAF → RCE |
패치: Commit 3584a98 — Zend 엔진 전반에 걸쳐 300개 파일 변경.
| 체인 | 벡터 | 인증 전 | 조건 | SAPI |
|---|---|---|---|---|
| A | 세션 주입 + LFI | 예 | 앱에 LFI 싱크가 존재 | 전체 |
| B | var_destroy UAF → 핸들러 덮어쓰기 | 아니오 | 앱이 unserialize() 호출 | 전체 |
| C | 핸들러 불일치 → __destruct | 예 | serialize_handler가 다른 두 디렉터리 | FPM |
| D | OOM 손상 → 잔존 EG() | 예 | 없음 — 모든 엔드포인트 | mod_php |
| E | FPM 세션 OOM → 잔존 BG() | 예 | 생산자: 모든 session_start() 엔드포인트; 소비자: 모든 엔드포인트 | FPM |
체인 D가 가장 치명적입니다: 모든 Apache mod_php 설치에 대한 의존성 없는 인증 전 RCE.
체인 E는 FPM에서 거의 동일하게 광범위합니다: 생산자는 session_start()를 호출하는 모든 엔드포인트가 필요하며(거의 보편적 — WordPress, Laravel, Joomla, Drupal 모두 해당), 소비자는 모든 PHP 엔드포인트가 될 수 있습니다 — rfc1867 upload_progress 핸들러는 애플리케이션 코드보다 먼저 SAPI 시작 중에 실행됩니다. 검증됨: nosession.php(코드에 session_start() 없음)가 잔존 BG(unserialize) 상태를 소비할 때 502 크래시를 유발합니다.
세 가지 RCE 익스플로잇(체인 A, B, C)이 exploit/에 포함되어 있습니다:
| 파일 | 체인 | 기능 |
|---|---|---|
chain_a_session_lfi.py | A | 업로드 파일명을 통해 PHP 코드 주입 → LFI가 세션 파일 포함 → RCE |
chain_b_uaf_rce.php | B | var_destroy UAF → EG()를 통해 zif_system 발견 → /proc/self/mem을 통해 var_dump 핸들러 덮어쓰기 → RCE |
chain_c_mismatch_rce.py | C | FPM 워커 PS(serializer) 오염 → 파일명을 통해 직렬화된 객체 주입 → 디코딩 실패 시 __destruct 발동 → RCE |
체인 D와 E 익스플로잇은 유료 구독자에게 제공됩니다.
# Chain A: Session injection + LFI → RCE
python3 exploit/chain_a_session_lfi.py --host TARGET --port 80 --command 'id'
# Chain B: var_destroy UAF → RCE (run on target or via uploaded webshell)
php exploit/chain_b_uaf_rce.php
# Chain C: Handler mismatch → __destruct → RCE
python3 exploit/chain_c_mismatch_rce.py --host TARGET --port 80 --command 'id'
detection/에 미리 작성된 IDS / WAF / SIEM 규칙:
| 파일 | 형식 | 시그니처 |
|---|---|---|
php2shell.rules | Suricata / Snort | 13개 규칙 — 요청, 응답, 정찰 |
php2shell.yaml | Sigma | 5개 규칙 — 웹 로그, 프로세스 생성, 파일 이벤트 |
modsecurity.conf | ModSecurity v2/v3 | 7개 규칙 — Apache/Nginx용 드롭인 |
php2shell.lua | OpenResty Lua | 경량 리버스 프록시 모듈 |
가장 빠른 완화 방법: multipart POST 본문에서 PHP_SESSION_UPLOAD_PROGRESS를 차단하십시오. 정당한 사용이 거의 없으며, 두 CVE 모두의 주요 공격 벡터를 커버합니다.
git clone https://github.com/ikow/php2shell-poc.git && cd php2shell-poc
# Start the lab (PHP-FPM + nginx + Apache mod_php)
cd lab && docker compose up -d
# Verify each chain
python3 ../poc/verify_session_injection.py --target http://127.0.0.1:18080
python3 ../poc/verify_handler_mismatch.py --target http://127.0.0.1:18080
python3 ../poc/verify_oom_trigger.py --host 127.0.0.1 --port 18081
python3 ../poc/verify_fpm_stale_state.py --target http://127.0.0.1:18080
# Run an exploit
python3 ../exploit/chain_a_session_lfi.py --host 127.0.0.1 --port 18080 --command 'id'
php2shell-poc/
├── exploit/
│ ├── chain_a_session_lfi.py # RCE: session injection + LFI
│ ├── chain_b_uaf_rce.php # RCE: var_destroy UAF → handler overwrite
│ └── chain_c_mismatch_rce.py # RCE: handler mismatch → __destruct
├── detection/
│ ├── php2shell.rules # Suricata / Snort IDS rules
│ ├── php2shell.yaml # Sigma SIEM detection rules
│ ├── modsecurity.conf # ModSecurity WAF rules
│ └── php2shell.lua # OpenResty / Nginx Lua WAF module
├── poc/
│ ├── verify_session_injection.py # Verify Chain A
│ ├── verify_uaf_asan.php # Verify Chain B (ASAN)
│ ├── verify_handler_mismatch.py # Verify Chain C
│ ├── verify_oom_trigger.py # Verify Chain D
│ └── verify_fpm_stale_state.py # Verify Chain E
├── lab/
│ ├── docker-compose.yml # PHP-FPM + nginx + Apache mod_php
│ ├── setup.sh # One-click lab setup
│ └── php.ini / php-apache.ini # Vulnerable PHP configs
└── docs/
├── ANALYSIS.md # Full technical analysis
└── substack_article.md # Writeup source
; Immediate — reduces attack surface
session.upload_progress.enabled = Off
session.use_only_cookies = On
유일한 완전한 해결책은 PHP를 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12+로 패치하는 것입니다. OOM 손상(Chain D)은 Zend 엔진 코어에 존재하며, 어떤 INI 설정으로도 해결되지 않습니다.
Wiz는 기본 컨테이너 이미지에서 사전 인증 RCE를 입증했습니다:
| 플랫폼 | 취약 여부 | 비고 |
|---|---|---|
| WordPress | 예 | 코어는 PHP 세션을 사용하지 않지만, WooCommerce와 다수의 플러그인이 사용함 |
| Joomla | 예 | 기본적으로 네이티브 PHP 세션을 사용함 |
| Drupal | 예 | 기본적으로 네이티브 PHP 세션을 사용함 |
| Magento | 예 | 유지보수 모드에서도 취약함 |
| Laravel | 예 | PendingBroadcast는 알려진 __destruct 가젯임 |
이 저장소는 승인된 보안 테스트 및 교육 목적으로만 제공됩니다. Chain D와 E(무의존성 RCE)의 익스플로잇 코드는 분석 문서의 유료 구독자에게 제공됩니다.
MIT