[KOR] PHP Critical 0-Day Analysis Reports v2.0

[KOR] PHP Critical 0-Day Analysis Reports v2.0

2026년 10월 21일 CVE-2026-109618과 CVE-2026-109619가 공개됐다. 두 취약점은 수정되지 않은 PHP 엔진에서 발생하며, 일부 공격 경로는 애플리케이션 코드가 실행되기 전에 트리거될 수 있다. 공격에 성공하면 PHP worker 권한으로 원격 코드 실행(RCE)이 가능하다. 두 취약점 모두 CVSS 9.2(Critical)를 부여받았다.

취약점 개요는 다음과 같다.

CVE

심각도

취약점 개요

영향 버전

CVE-2026-109618

Critical (CVSS v4.0 9.2)

OOM 처리 중 longjmp()로 실행 흐름이 중단되면서 PHP 내부 상태가 불완전하게 남는다. 이후 request shutdown이 이 상태를 유효한 데이터로 처리하면 메모리 손상과 RCE로 이어질 수 있다.

PHP < 8.2.35PHP 8.3.0–8.3.35PHP 8.4.0–8.4.26PHP 8.5.0–8.5.11

CVE-2026-109619

Critical (CVSS v4.0 9.2)

요청 메모리를 가리키는 worker global state가 정리되지 않고 남을 수 있다. 같은 worker의 다음 요청이 정상 초기화 전에 이 상태를 사용하면 UAF와 RCE가 발생할 수 있다.

PHP < 8.2.35PHP 8.3.0–8.3.35PHP 8.4.0–8.4.26PHP 8.5.0–8.5.11

현재 여러 분석가가 관련 PoC를 공개하고 있으므로, 실제 공격에 악용되기 전에 패치를 적용할 것을 권고한다. PHP 프로젝트는 즉시 업데이트하기 어려운 환경을 위한 임시 완화책도 제시했지만, 패치 버전으로 업데이트하는 것만이 완전한 조치라고 설명한다. 자세한 내용은 각 공식 보안 권고문을 참고한다.

취약점 상세

CVE-2026-109618

이 취약점은 PHP 엔진의 메모리 부족(Out of Memory, OOM) 처리 과정에서 발생한다.

PHP는 OOM이 발생하면 longjmp()를 사용해 현재 실행 컨텍스트를 빠져나가고 요청 처리를 중단한다. 문제는 일부 내부 상태가 완전히 초기화되기 전에 메모리 할당이 실패할 수 있다는 점이다. 이 경우 PHP는 적절한 초기화를 수행하지 못한 채 컨텍스트를 종료하고, 해당 메모리를 invalid state로 남긴다. 이후 request shutdown이 이 메모리를 읽거나 분기 조건으로 사용하면 메모리 손상이 발생한다. 공격자는 여러 OOM 유도 전략으로 이 상태를 안정적으로 트리거하여 RCE로 발전시킬 수 있다.

공격자가 OOM을 원하는 시점에 발생시키려면 PHP의 memory_limit에 도달할 수 있어야 한다. Advisory에 명시된 방법은 post_max_size 검사를 우회하는 것이다. PHP는 POST 본문을 자동으로 파싱하기 전에 선언된 Content-Length와 post_max_size를 비교하지만, 실제로 소비하는 전체 바이트에 같은 제한을 적용하지 않는다. 따라서 유효한 Content-Length가 없는 multipart 요청 등을 이용하면 초기 검사를 통과한 뒤 계속 데이터를 전달하여 OOM을 유도할 수 있다.

OOM이 발생하는 지점에 따라 HashTable이 불완전한 상태로 남을 수 있다. PHP HashTable의 각 원소는 Bucket에 저장된다. 새 Bucket을 추가할 때 PHP는 Bucket의 초기화가 끝나기 전에 nNumUsed와 nNumOfElements를 먼저 증가시킨다.

  • nNumUsed: HashTable이 순회해야 하는 Bucket 범위

  • nNumOfElements: 현재 유효한 논리적 원소 수

두 카운터를 증가시킨 직후 key 할당에 실패하면, HashTable은 새 Bucket이 존재한다고 기록하지만 해당 Bucket의 key, hash, zval은 초기화되지 않는다.

mod_php는 요청 시작에 실패해도 php_request_shutdown()을 실행하여 $_POST와 $_FILES의 HashTable을 파괴한다. 이 과정에서 nNumUsed를 기준으로 미완성 Bucket까지 순회하고, 그 안의 stale bytes를 정상 포인터나 zval로 해석한다. 공격자는 힙 배치를 조정해 stale bytes가 유효한 포인터·zval로 해석되도록 하여 메모리 손상을 RCE로 발전시킬 수 있다.

CVE-2026-109619

본 취약점은 PHP로의 일부 입력에서 발생하는 Worker와 요청 별 메모리에 대한 수명 차이로 인해 발생하는 Use-After-Free(UAF) 취약점이다. PHP worker는 여러 요청을 연속해서 처리하지만, 각 요청의 heap은 요청 종료 시 해제된다. 반면 Error, Session, Object 및 Extension 관련 global state는 worker에 남아 다음 요청까지 유지될 수 있다. 정상적인 경우에는 요청 메모리를 해제하기 전에 이를 가리키는 global state를 초기화해야 한다. 그러나 OOM과 같은 interruption이 cleanup을 건너뛰면 global state에 dangling pointer가 남는다. 같은 worker가 다음 요청을 처리하면서 이 상태를 정상 초기화보다 먼저 읽거나 해제하면 UAF가 발생한다. 여러 악용 경로가 존재하지만 여기서는 Session global state 경로를 다룬다.

Session upload-progress는 파일 업로드 진행률을 PHP Session에 기록하는 기능이다. Session ID와 PHP_SESSION_UPLOAD_PROGRESS 필드 등 특정 필드를 포함한 multipart 요청으로 이 기능을 트리거할 수 있다. 파일 part의 FILE_START 이벤트가 발생하면 PHP는 Session을 조기에 초기화하고 PS(id)와 PS(http_session_vars)를 설정한다.

  • PS(id): 요청 heap의 Session ID 문자열을 가리키는 포인터

  • PS(http_session_vars): Session 값을 담는 zval로, 내부적으로 요청 heap의 reference와 배열을 가리킬 수 있음

첫 번째 multipart 요청을 파싱하던 중 OOM 등의 interruption이 발생하면 multipart의 END callback이 호출되지 않아 Session 상태 정리가 생략될 수 있다. 요청 heap은 해제되지만 worker의 PS(id)와 PS(http_session_vars)는 초기화되지 않아 해제된 메모리를 계속 참조한다.

두 번째 요청에는 Session ID와 PHP_SESSION_UPLOAD_PROGRESS 필드를 포함하되 실제 파일 part는 넣지 않는다. 그러면 FILE_START를 통한 초기화 없이 END callback에 도달할 수 있다. 이 callback은 이전 요청에서 남은 PS(id)를 읽고 PS(http_session_vars)를 정리하려 한다. 공격자가 요청 데이터로 해제된 heap 영역을 먼저 재점유하면, PHP는 그 데이터를 정상 zend_reference, zval 또는 HashTable로 오인할 수 있다. 이후 PS(http_session_vars)를 파괴하는 과정에서 가짜 내부 구조체의 포인터를 따라가면서 메모리 손상이 발생하고, 이를 함수 또는 핸들러 호출 제어로 발전시키면 RCE가 가능해진다.

PetoWorks 연구원들은 이 내용에 대한 전반적인 분석을 수행하고 LLM을 활용하여 재현을 시도했으며, 두 취약점의 재현 코드를 개발하였다. 재현은 다음과 같이 두 취약점 모두 Crash 발생까지 보였다.

https://drive.google.com/file/d/1jPGII4a1GZq2fAXmCDu6K_y4to-pYf4I/preview

https://drive.google.com/file/d/1Xf0lYXIrvDEMkpuR6Fub23x2gPTlbH_0/preview

취약점 연구와 LLM 활용

CVE-2026-109618의 근본 원인인 OOM 처리 결함은 이미 2024년 PHP 보안 감사 과정에서 확인됐다. 당시에는 구체적인 공격 경로가 밝혀지지 않았으며, 하위 호환성과 새로운 DoS 발생 가능성 등의 문제로 패치가 지연됐다. 이후 2026년 Calif 연구진이 해당 결함을 이용한 RCE를 입증했으며, OpenAI 역시 동일한 근본 원인을 독립적으로 보고했다.

Calif 연구진은 이 과정에서 과거 PHP 취약점에 대한 이해를 바탕으로 LLM을 활용해 OOM 유도 지점과 취약한 실행 흐름을 분석했다. 이는 기존에 알려진 결함도 새로운 공격 경로가 발견되면서 실제 위험성이 드러날 수 있으며, LLM을 활용한 취약점 연구에서도 대상에 대한 깊은 이해가 중요하다는 점을 보여준다.

References

070-4110-1337 (대표번호)
02-861-1337 (세금계산서 문의)
02-861-1338 (Fax)

서울 금천구 가산디지털1로 205-15
SH드림타워 614호

(주) 페토웍스

함께 연구할 동료를 기다립니다

© PetoWorks Inc. 2025

070-4110-1337 (대표번호)
02-861-1337 (세금계산서 문의)
02-861-1338 (Fax)

서울 금천구 가산디지털1로 205-15
SH드림타워 614호

(주) 페토웍스

함께 연구할 동료를 기다립니다

© PetoWorks Inc. 2025

070-4110-1337 (대표번호)
02-861-1337 (세금계산서 문의)
02-861-1338 (Fax)

서울 금천구 가산디지털1로 205-15
SH드림타워 614호

(주) 페토웍스

함께 연구할 동료를

기다립니다

© PetoWorks Inc. 2025