본문으로 이동
메뉴 여닫기
환경 설정 메뉴 여닫기
개인 메뉴 여닫기
로그인하지 않음
지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.

CVE-2026-109619(RCE via Stale Global State)은 PHP 실행 엔진에서 HTTP 요청이 종료된 후에도 해당 요청의 메모리를 참조하는 전역 상태가 남아, 후속 요청에서 이미 해제된 메모리에 접근함으로써 Use After Free와 원격 코드 실행(RCE)을 유발할 수 있는 심각한 보안 취약점이다. 2026년 10월 21일 공개되었으며, CVE-2026-109618과 함께 PHP2Shell 원격 코드 실행 취약점으로 통칭된다.

CVE-2026-109619는 PHP의 요청별 메모리 관리와 워커 프로세스의 전역 상태 관리가 서로 일치하지 않아 발생하는 취약점이다.

PHP의 일부 내부 상태는 개별 HTTP 요청에 할당된 메모리를 참조하면서도 여러 요청을 처리하는 워커 프로세스에 유지된다. 정상적으로는 요청이 종료되기 전에 이러한 참조를 초기화해야 하지만, 치명적 오류나 일부 종료 처리 과정에서는 초기화가 누락될 수 있다.

이후 동일한 워커가 새로운 HTTP 요청을 처리하면서 이전 요청의 메모리 참조를 사용하면 Use After Free 유형의 메모리 손상이 발생한다. 공격자가 메모리 배치를 조작할 수 있는 조건에서는 인증 없는 원격 코드 실행으로 이어질 수 있다.[1]

항목 내용
CVE CVE-2026-109619
공식 취약점 명칭 RCE via stale global state
관련 명칭 PHP2Shell
공개일 2026년 10월 21일
영향 대상 PHP 실행 엔진 및 요청 처리 관련 구성요소
취약점 유형 Use After Free, 전역 상태 관리 오류, 메모리 손상
주요 결과 인증 없는 원격 코드 실행, 프로세스 메모리 정보 노출
CVSS v4.0 9.2 (Critical)
공격 벡터 Network
공격 복잡도 High
공격 요구 조건 Present
필요 권한 None
사용자 상호작용 None
GitHub Advisory GHSA-6wmf-4rv5-p3rp
관련 취약점 CVE-2026-109618
수정 버전 PHP 8.2.35, 8.3.36, 8.4.27, 8.5.12

PHP 보안팀은 Apache mod_php 환경에서 오류 역추적 정보를 이용한 원격 코드 실행을 확인했으며, 세션 업로드 진행률 기능을 이용한 공격은 mod_php와 PHP-FPM 환경 모두에서 검증했다고 밝혔다.[1]

발견 및 공개 경과

편집 원본 편집
  • 2026년 8월
    • Calif와 Wiz Research 등의 보안 연구진이 PHP 실행 엔진의 메모리 관리 및 오류 처리 과정에서 심각한 취약점을 발견했다.
    • 연구 과정에서 인공지능 모델을 이용한 코드 분석과 공격 가능성 검증이 수행되었다.
    • Wiz Research는 PHP의 오류 처리, 세션 상태, OPcache 관련 메모리 처리 문제를 분석하고 여러 애플리케이션 환경에서 원격 코드 실행을 실증했다.[2]
  • 2026년 10월 20일
    • PHP 개발팀이 긴급 보안 업데이트 배포를 예고했다.
  • 2026년 10월 21일
    • CVE-2026-109619의 기술적 내용이 공개되었다.
    • PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35 보안 업데이트가 배포되었다.
    • CVSS v4.0 기준 심각도 9.2점(Critical)이 부여되었다.[3]
  • 2026년 10월 23일
    • PHP 개발팀이 세션 업로드 진행률 기능과 관련된 추가적인 원격 코드 실행 위험을 안내했다.
    • 특정 세션 직렬화 설정을 실행 중에 변경하는 환경에서 발생하는 별도 문제로, CVE-2026-115560이 부여될 예정이라고 밝혔다.
    • 해당 문제는 CVE-2026-109619와 구분되며, 다음 정기 수정 버전에서 별도로 처리할 예정이라고 설명했다.[4]

PHP의 요청별 메모리와 워커 전역 상태

편집 원본 편집

PHP는 웹 서버로부터 HTTP 요청을 전달받으면 요청 처리에 필요한 메모리를 할당한다.

이 메모리는 요청 종료 시 해제되는 것이 일반적이지만, PHP의 워커 프로세스 자체는 이후 다른 요청을 처리하기 위해 계속 실행될 수 있다.

이때 PHP 내부에는 두 종류의 상태가 존재한다.

구분 요청별 상태 워커 전역 상태
수명 개별 HTTP 요청의 처리 기간 워커 프로세스의 실행 기간
관리 대상 요청 변수, 임시 객체, 문자열, 세션 처리 데이터 등 오류 상태, 실행 엔진 상태, 일부 확장 모듈 상태 등
메모리 해제 요청 종료 시 정리 워커 종료 또는 별도 초기화 시 정리
주요 위험 요청 데이터 자체의 손상 이전 요청의 메모리 참조가 후속 요청으로 전달될 가능성

전역 상태에 저장된 포인터가 요청별 메모리를 가리키는 것은 그 자체로 반드시 잘못된 동작은 아니다. 그러나 해당 메모리를 해제하기 전에 참조가 제거되거나 무효화되어야 한다.

CVE-2026-109619에서는 일부 상태가 이 원칙을 지키지 못한다.

특히 다음과 같은 상태가 문제가 될 수 있다.

  • 오류 및 예외 처리 상태
  • 오류 역추적(Backtrace) 정보
  • 세션 처리 상태
  • 세션 데이터의 직렬화 및 역직렬화 관련 상태
  • 객체와 확장 모듈이 유지하는 임시 상태

이러한 상태가 이전 요청의 메모리를 계속 참조하면 후속 요청에서 해당 메모리를 정상적인 객체나 문자열로 잘못 취급할 수 있다.[1]

Use After Free 발생 구조

편집 원본 편집

취약점 발생 과정을 단순화하면 다음과 같다.

[첫 번째 HTTP 요청]

HTTP 요청 수신
       ↓
PHP 워커에서 요청 처리
       ↓
요청별 메모리 할당
       ↓
일부 메모리의 주소가
워커 전역 상태에 저장됨
       ↓
치명적 오류 또는 비정상적인 종료 처리
       ↓
전역 상태 초기화 누락
       ↓
요청별 메모리 해제
       ↓
전역 상태에 잘못된 포인터 잔존


[두 번째 HTTP 요청]

동일 PHP 워커가 새 요청 수신
       ↓
정상적인 요청 초기화 이전에
일부 내부 기능 실행
       ↓
이전 요청의 전역 상태 참조
       ↓
이미 해제된 메모리에 접근
       ↓
Use After Free 발생
       ↓
메모리 정보 노출 또는 손상
       ↓
원격 코드 실행 가능

일반적인 허상 참조(Dangling Pointer) 문제가 여러 HTTP 요청의 경계를 넘어 발생한다는 점이 특징이다.

요청 종료 과정에서 메모리를 정상적으로 해제했더라도 해당 메모리를 가리키는 포인터가 남아 있다면 안전하지 않다.

해제된 메모리 영역이 새로운 데이터로 재사용되면 기존 포인터가 예상하지 못한 객체나 데이터를 참조할 수 있다.

공격자가 힙 메모리의 배치를 의도적으로 조작할 수 있는 경우 이러한 상태를 코드 실행으로 연결할 수 있다.

Producer와 Consumer 구조

편집 원본 편집

PHP 보안팀은 취약점 발생에 필요한 두 가지 역할을 Producer와 Consumer로 구분했다.

Producer(상태 생성자)

  • 요청별 메모리에 저장된 데이터를 워커 전역 상태에서 참조하도록 만드는 내부 동작
  • 치명적 오류나 종료 처리 문제로 인해 해당 참조를 초기화하지 못하는 동작
  • 요청이 종료된 이후에도 유효하지 않은 포인터를 남기는 원인이 됨

Consumer(상태 소비자)

  • 후속 요청에서 이전 전역 상태를 읽거나 해제하거나 이를 기준으로 분기하는 내부 동작
  • 정상적인 요청 초기화가 전역 상태를 덮어쓰기 전에 실행될 수 있음
  • 이미 해제된 메모리를 사용하면서 Use After Free를 유발

실제 취약점이 성립하려면 다음 조건이 결합해야 한다.

  1. 공격자가 도달할 수 있는 PHP 내부 동작이 요청별 상태를 전역 상태에 저장한다.
  2. 요청 종료 과정에서 전역 상태가 초기화되지 않거나, 초기화 이후 다시 유효하지 않은 상태가 저장된다.
  3. 요청별 메모리가 해제된다.
  4. 같은 워커 프로세스가 다음 요청을 처리한다.
  5. 정상적인 상태 초기화 이전에 이전 요청의 전역 상태를 사용하는 동작이 발생한다.

공개된 원격 코드 실행 실증에서는 Producer와 Consumer가 서로 다른 HTTP 요청에서 발생했다.

따라서 단순히 PHP에서 오류가 발생하거나 동일한 워커가 여러 요청을 처리한다는 사실만으로 공격 성공이 보장되는 것은 아니다.[1]

취약점 발생 경로

편집 원본 편집

치명적 오류에 의한 전역 상태 잔존

편집 원본 편집

PHP 보안팀은 다음과 같은 오류가 전역 상태 초기화를 방해할 수 있다고 설명했다.

  • PHP 코드 구문 오류(Parse Error)
  • 컴파일 오류
  • 처리되지 않은 예외 또는 오류
  • require 실패
  • 최대 실행 시간 초과(Maximum execution time exceeded)
  • 메모리 부족(OOM, Out of Memory)
  • 확장 모듈의 실행 도중 발생하는 치명적 오류

이러한 오류가 내부 상태를 전역 영역에 저장한 직후 발생하면 정상적인 초기화나 정리 과정이 끝나지 못할 수 있다.

또한 치명적 오류가 발생하지 않더라도 일부 종료 처리 과정에서 경고나 진단 정보가 새로 생성되면 이미 정리된 전역 오류 상태에 새로운 요청별 데이터가 다시 저장될 수 있다.

따라서 이 취약점은 메모리 부족 오류에만 의존하지 않는다.

CVE-2026-109618이 메모리 부족에 따른 부분 초기화와 메모리 손상을 중심으로 한다면, CVE-2026-109619는 요청 종료와 후속 요청 초기화 사이의 전역 상태 수명 관리 문제가 핵심이다.[1]

PHP 8.5 오류 역추적 정보 경로

편집 원본 편집

PHP 8.5의 fatal_error_backtraces 기능에서는 구체적인 취약 경로가 확인되었다.

이 기능은 치명적 오류가 발생했을 때 오류와 관련된 실행 경로 정보를 기록하기 위한 것이다.

문제는 오류 역추적 정보가 요청별 메모리에 저장되면서도 이를 참조하는 전역 상태가 요청 종료 과정에서 적절하게 초기화되지 않는다는 점이다.

이후 다음 요청의 초기화 과정에서 경고 등의 진단 정보가 생성되면 이전 요청에 속한 오류 역추적 상태에 접근할 수 있다.

  • Producer: 치명적 오류 발생 시 오류 역추적 정보 저장
  • 상태 잔존: 요청 종료 이후에도 역추적 정보를 가리키는 전역 상태 유지
  • Consumer: 후속 요청의 초기화 과정에서 발생하는 진단 정보 처리
  • 공격 결과: Use After Free 및 원격 코드 실행

PHP 보안팀은 이 경로를 Apache mod_php에서 확인된 가장 강력한 실증 사례로 제시했다.[1]

PHP 8.5에서 이 기능이 활성화된 환경은 해당 경로에 노출될 수 있다. 단, 기능 활성화 여부만으로 공격 가능성을 확정할 수는 없으며 후속 요청의 소비 동작 등 추가 조건이 필요하다.

초기화 이전의 INI 진단 정보 처리

편집 원본 편집

PHP는 요청 처리 과정에서 설정값을 적용하면서 잘못되거나 지원이 종료된 설정을 발견하면 경고, 알림, 사용 중단 경고(Deprecation) 등을 생성할 수 있다.

일부 실행 환경에서는 이러한 설정 처리가 일반적인 PHP 요청 초기화 이전에 발생한다.

이때 오류 처리 기능이 이전 요청에서 남은 전역 오류 상태에 접근하면 Use After Free가 발생할 수 있다.

PHP 보안팀이 제시한 관련 설정 예시는 다음과 같다.

설정 또는 기능 위험 조건
auto_detect_line_endings 사용 중단된 설정에 따른 진단 정보 발생
filter.default 기본값이 아닌 설정에서 진단 정보 발생
assert.* PHP 8.3 이상에서 과거 설정 사용
mbstring.http_input 등 일부 문자 인코딩 관련 설정 적용 과정
iconv.internal_encoding 등 일부 구형 문자 인코딩 설정 적용 과정
zend.assertions 잘못되거나 충돌하는 설정값
memory_limit 유효하지 않거나 범위를 초과하는 설정값
date.timezone 유효하지 않은 시간대 설정
open_basedir 로그, 세션 등 관련 경로에 대한 접근 제한 충돌

이들 설정이 존재하기만 하면 취약해지는 것은 아니다. 요청 초기화 이전에 실제 진단 정보가 발생하고, 이전 요청의 유효하지 않은 상태가 존재하는 경우 문제가 된다.

중요한 점은 진단 정보의 표시 여부와 내부 처리 여부가 다르다는 것이다.

다음과 같은 조치만으로는 취약점을 차단할 수 없다.

  • display_errors=Off
  • log_errors=Off
  • error_reporting 수준 변경
  • PHP의 @ 오류 억제 연산자 사용

PHP 내부에서는 경고를 표시하거나 기록할지를 결정하기 전에 이미 오류 관련 전역 상태에 접근할 수 있기 때문이다.[1]

세션 업로드 진행률 처리 경로

편집 원본 편집

PHP는 파일 업로드 진행 상황을 세션에 기록하는 기능을 제공한다.

관련 설정은 다음과 같다.

  • session.upload_progress.enabled
  • session.upload_progress.name
  • session.upload_progress.prefix

해당 기능은 multipart 파일 업로드 요청을 처리하는 과정에서 동작할 수 있다.

정상적인 PHP 스크립트 실행을 위한 세션 초기화보다 앞선 시점에 세션 데이터와 직렬화·역직렬화 관련 내부 상태를 사용할 수 있다는 점이 특징이다.

취약한 환경에서 요청 처리 중 OOM이나 다른 치명적 오류가 발생하면 세션 또는 디코더의 내부 상태가 초기화되지 못하고 남을 수 있다.

이후 동일 워커가 새로운 업로드 요청을 처리할 때 기존 상태에 접근하면서 Use After Free가 발생할 수 있다.

  • Producer: 파일 업로드 처리 과정에서 세션 및 디코더 상태 생성
  • 오류 조건: 상태 생성 이후 메모리 부족 또는 치명적 오류 발생
  • 상태 잔존: 세션 관련 전역 포인터의 초기화 누락
  • Consumer: 후속 요청의 업로드 진행률 처리
  • 공격 결과: 메모리 손상 및 원격 코드 실행

PHP 보안팀은 이 경로의 원격 코드 실행을 mod_php와 PHP-FPM 모두에서 검증했다.

또한 세션 업로드 진행률 기능은 기본적으로 활성화되어 있으며, 공격 경로의 성립에 애플리케이션의 명시적인 session_start() 호출이 반드시 필요한 것은 아니다.

다만 상태를 남기는 요청과 이를 사용하는 후속 요청이 동일한 워커에서 처리되어야 하며, 관련 오류 및 메모리 상태 조건이 충족되어야 한다.[1]

실행 환경별 공격 가능성

편집 원본 편집
실행 환경 확인된 공격 조건 및 영향
Apache mod_php 요청 초기화 전 INI 설정 적용과 진단 정보 처리가 Consumer로 사용될 수 있음. 오류 역추적 및 세션 처리 경로에서 원격 코드 실행 실증
PHP-FPM PHP_VALUE 또는 PHP_ADMIN_VALUE 전달에 따른 초기 진단 정보가 조건부 Consumer가 될 수 있음. 애플리케이션 실행 도중 상태를 남기고 이후 세션 업로드 진행률 기능으로 이를 사용하는 RCE 경로가 검증됨
LiteSpeed LSAPI 특수한 환경 설정이 요청 초기화 이전에 적용될 수 있어 조건부 영향 가능
FrankenPHP 기본 구성에서 동일한 조기 INI 진단 Consumer는 확인되지 않았으나, 다른 내부 상태 및 애플리케이션 경로의 영향 가능성은 남음
php-cgi PHP 공식 보안 공지에서 영향 범위에 포함되며, 구체적인 재현 조건은 실행 구성에 따라 다름

PHP 보안팀은 웹 요청을 처리하는 PHP 설치 전반에 보안 업데이트를 권고했다.[3]

Apache mod_php는 PHP 실행 엔진이 Apache 프로세스 내부에서 동작하는 방식이다.

이 환경에서는 .htaccess와 Apache의 일부 PHP 설정 지시어가 php_request_startup() 이전에 적용된다.

따라서 이전 요청에서 유효하지 않은 오류 상태가 남았다면 다음 요청의 설정 적용 과정에서 이를 참조할 수 있다.

특히 요청 초기화 이전에 오류 진단 처리가 발생하는 환경에서는 애플리케이션 PHP 코드가 실행되기도 전에 취약점이 발동할 수 있다.

일반적인 php.ini의 시작 시점 설정은 매 요청마다 동일하게 재적용되는 것은 아니므로 이를 모두 같은 공격 조건으로 취급해서는 안 된다.

PHP-FPM은 별도의 워커 프로세스가 웹 서버로부터 FastCGI 요청을 받아 처리하는 구조이다.

Apache mod_php와 달리 PHP-FPM은 요청 초기화 자체가 실패하면 해당 워커를 종료하므로, mod_php에서 성립하는 일부 초기화 단계 공격 경로가 그대로 유지되지는 않는다.

그러나 다음과 같은 경로에서는 영향을 받을 수 있다.

  • FastCGI 프런트엔드에서 전달된 PHP_VALUE 또는 PHP_ADMIN_VALUE가 조기 진단 정보를 유발하는 경우
  • 정상적인 요청 초기화 이후 애플리케이션 실행 과정에서 전역 상태가 생성되는 경우
  • 해당 요청에서 치명적 오류가 발생하여 전역 상태가 남는 경우
  • 이후 같은 워커가 새 요청을 처리하면서 세션 업로드 진행률 기능이 이전 상태에 접근하는 경우

PHP 보안팀은 일반적인 dynamic PHP-FPM 풀에서도 애플리케이션의 적절한 오류 발생 경로가 존재하면 세션 업로드 진행률 관련 원격 코드 실행이 가능하다는 점을 검증했다.

다만 PHP-FPM 풀 설정은 일반적으로 워커 시작 시 적용되며, .user.ini는 정상적인 요청 초기화 이후에 적용되므로 이를 조기 INI 진단 경로와 혼동해서는 안 된다.[1]

여러 워커와 재사용 조건

편집 원본 편집

이 취약점의 실증 경로는 Producer 요청과 Consumer 요청을 같은 워커가 처리해야 한다는 조건을 가진다.

  • 워커가 요청마다 종료되는 구성에서는 해당 요청 간 경로가 차단될 수 있다.
  • 워커가 지속적으로 재사용되는 구성에서는 잔존 상태가 후속 요청에 영향을 줄 수 있다.
  • 여러 워커가 존재하는 경우 요청이 특정 워커에 배정될 가능성이 공격 성공률에 영향을 준다.
  • 워커를 주기적으로 재생성하면 잔존 상태가 유지되는 기간을 줄일 수 있다.

다만 워커 재사용 횟수를 제한하는 방법은 해당 공격 경로에 대한 완화책이며 취약한 PHP 자체를 수정하는 것은 아니다.

실제 공격 실증

편집 원본 편집

Wiz Research는 PHP2Shell 연구에서 CVE-2026-109619와 관련된 두 가지 대표적인 메모리 손상 경로를 보고했다.

연구 대상 공격 결과 실증 대상
Fatal-error backtrace Use After Free 메모리 손상 및 원격 코드 실행 Drupal
OPcache Type Confusion PHP 내부 공유 상태 손상 및 원격 코드 실행 WordPress

해당 결과는 취약점이 특정 웹 애플리케이션의 PHP 코드에 국한되지 않고 PHP 실행 엔진 내부에서 발생한다는 점을 보여준다.

연구진은 메모리 배치를 조작하고 여러 내부 결함을 결합해 공격을 구성했으며, 실제 공격 성공 조건은 PHP 버전과 설정, 메모리 배치, 애플리케이션의 동작에 따라 달라질 수 있다고 설명했다.[2]

실제 공격 시도

편집 원본 편집

2026년 10월 24일 기준 PHP2Shell 취약점군을 대상으로 하는 실제 공격 시도가 보고되었다.

  • 2026년 10월 17일
    • Amazon Threat Intelligence가 MadPot 허니팟에서 PHP2Shell 악용 시도를 사후 확인했다.
    • 공식 취약점 공개일보다 4일 앞선 시점이었다.
  • 2026년 10월 21일
    • Amazon이 보안 업데이트 공개 전후 여러 공격 시도를 확인했다.
    • watchTowr도 자사 허니팟 네트워크에서 실제 공격 시도를 관측했다고 발표했다.

Amazon은 발견된 공격 페이로드가 실제 운영 환경에서 성공했는지에 대해서는 추가 검증이 필요하다고 설명했다.[5][6]

이러한 관측은 PHP2Shell 취약점군 전체에 관한 것으로, 확인된 모든 공격 시도가 CVE-2026-109619만을 이용했다고 단정할 수는 없다.

영향받는 버전

편집 원본 편집

2026년 10월 21일 공식 보안 업데이트 기준 영향 범위는 다음과 같다.

PHP 계열 취약한 버전 수정 버전
PHP 8.5 8.5.12 미만 8.5.12 이상
PHP 8.4 8.4.27 미만 8.4.27 이상
PHP 8.3 8.3.36 미만 8.3.36 이상
PHP 8.2 8.2.35 미만 8.2.35 이상
PHP 8.1 이하 공식 보안 지원 종료 버전 배포판 또는 LTS 공급업체의 별도 패치 확인 필요

PHP 개발팀은 취약점의 심각성을 고려해 PHP 7.4, 8.0, 8.1에 대한 최소한의 소스 코드 백포트도 제공했으나, 해당 버전의 새로운 공식 정식 릴리스가 배포된 것은 아니다.[3]

또한 취약점의 세부 공격 경로에 따라 실제 영향을 받는 버전이 다를 수 있다. 예를 들어 fatal_error_backtraces 관련 실증 경로는 PHP 8.5의 기능과 연관되어 있지만, 세션 및 전역 상태 수명 문제는 다른 PHP 버전에서도 발생할 수 있다.

오래된 PHP 버전에서 모든 세부 경로가 동일하게 재현된다는 의미는 아니다.

보안 패치의 기술적 변경

편집 원본 편집

전역 상태 초기화 강화

편집 원본 편집

PHP 개발팀은 두 PHP2Shell 취약점을 해결하기 위해 Zend Engine의 오류 처리 구조와 요청 간 상태 관리 방식을 변경했다.

주요 변경 방향은 다음과 같다.

  • 요청 종료 과정에서 오류 및 예외 관련 전역 상태를 적절하게 초기화
  • 후속 요청 초기화 이전에 접근할 수 있는 내부 상태의 유효성 보장
  • 일부 직렬화 및 역직렬화 상태의 초기화 시점 보강
  • 세션 업로드 진행률 처리 과정의 상태 관리 개선
  • 메모리 부족 상황에서 내부 상태를 손상시킬 수 있는 즉각적인 실행 중단 방식 변경

수정의 핵심은 요청별 메모리를 해제한 뒤 해당 메모리를 참조하는 상태가 워커에 남지 않도록 하는 것이다.

특히 일반적인 PHP 요청 초기화 이전에 수행되는 일부 작업도 안전한 상태를 사용하도록 수정되었다.

관련 소스 코드

편집 원본 편집

공식 수정은 다음 커밋에 포함되었다.

항목 내용
프로젝트 php/php-src
커밋 31c0ea7d7ff1d1fccb6492e52dab544011628065
제목 Avoid state corruption via bailout
주요 변경 OOM 종료 처리 구조 변경 및 전역 상태 초기화 보강
수정 대상 CVE-2026-109618, CVE-2026-109619

해당 커밋은 423개 파일을 변경했으며, PHP 실행 엔진과 확장 모듈의 오류 처리 경로에 걸쳐 수정이 이루어졌다.[7]

단순히 특정 전역 포인터 한 개를 초기화하는 수정이 아니라, 여러 실행 경로에서 요청별 메모리와 워커 전역 상태가 충돌하지 않도록 하는 구조적인 변경이다.

패치 효과와 한계

편집 원본 편집

정식 보안 패치는 2026년 10월 공개된 PHP2Shell 취약점군의 확인된 공격 경로를 수정하기 위한 것이다.

그러나 개별 설정이나 기능을 단순히 비활성화하는 조치는 특정 경로만 차단할 수 있다.

또한 2026년 10월 23일 별도로 안내된 CVE-2026-115560은 특수한 세션 직렬화 설정에서 발생하는 추가 문제이므로, 이미 PHP2Shell 업데이트를 적용한 환경에서도 해당 조건에 해당하는지 확인할 필요가 있다.[4]

정식 보안 업데이트

편집 원본 편집

CVE-2026-109619의 근본적인 해결 방법은 보안 수정이 포함된 PHP 버전으로 업데이트하는 것이다.

  • PHP 8.5 → 8.5.12 이상
  • PHP 8.4 → 8.4.27 이상
  • PHP 8.3 → 8.3.36 이상
  • PHP 8.2 → 8.2.35 이상
  • PHP 8.1 이하 → 지원되는 PHP 버전으로 업그레이드하거나 공급업체의 수정 패치 적용

패치 설치 후에는 기존 워커 프로세스가 취약한 코드를 계속 실행하지 않도록 PHP-FPM 또는 웹 서버 프로세스를 재시작해야 한다.

운영체제 배포판이 보안 수정을 백포트하는 경우에는 PHP 버전 문자열을 유지할 수 있으므로 패키지 릴리스와 보안 공지를 확인해야 한다.

임시 완화 조치

편집 원본 편집

PHP 보안팀이 제시한 주요 조치는 다음과 같다.

조치 목적 한계
session.upload_progress.enabled=0 확인된 세션 업로드 진행률 관련 공격 경로 차단 다른 전역 상태 관련 경로는 차단하지 못함
fatal_error_backtraces=0 PHP 8.5의 오류 역추적 관련 공격 경로 차단 PHP 8.5의 특정 Producer만 제거
잘못되거나 사용 중단된 INI 설정 수정 초기화 이전에 발생하는 경고 및 진단 정보 감소 다른 Consumer가 존재할 수 있음
외부 입력으로 유발되는 치명적 오류 수정 전역 상태가 남는 Producer 경로 감소 모든 오류 처리 경로를 제거하는 것은 불가능
실행 시간 초과 가능성 감소 일부 치명적 중단 경로 제거 다른 치명적 오류에는 영향 없음
워커 재사용 횟수 제한 이전 요청 상태가 후속 요청으로 전달될 가능성 축소 실행 성능 저하 및 다른 취약 경로 잔존 가능

이러한 조치는 취약점 전체에 대한 완전한 해결책이 아니다.[1]

세션 업로드 진행률 비활성화

편집 원본 편집

세션 업로드 진행률 기능을 사용하지 않는 경우 다음 설정을 적용할 수 있다.

session.upload_progress.enabled=0

이 설정은 요청 본문을 처리하기 전에 적용되어야 한다.

PHP 공식 보안팀은 다음과 같은 위치에 설정할 것을 권고했다.

  • php.ini
  • PHP-FPM 풀 설정
  • Apache 서버 설정

반면 다음 방법에만 의존해서는 안 된다.

  • 애플리케이션 코드의 ini_set()
  • PHP-FPM의 .user.ini

해당 설정이 적용되는 시점보다 앞서 취약한 세션 처리 기능이 실행될 수 있기 때문이다.

설정 변경 후에는 기존 PHP 워커를 재시작해야 한다.

PHP 8.5 오류 역추적 비활성화

편집 원본 편집

PHP 8.5에서 즉시 보안 업데이트가 어려운 경우 다음 설정으로 확인된 오류 역추적 관련 공격 경로를 차단할 수 있다.

fatal_error_backtraces=0

이 설정은 PHP 8.5의 특정 Producer 경로에 대한 완화 조치이며, 세션 및 다른 확장 모듈 상태 관련 문제를 해결하지는 못한다.

PHP-FPM 워커 재사용 제한

편집 원본 편집

PHP-FPM에서는 워커가 처리하는 요청 수를 제한하여 요청 간 잔존 상태가 재사용되는 위험을 줄일 수 있다.

pm.max_requests = 1

이 설정은 각 워커가 정해진 요청 수를 처리한 후 재생성되도록 하는 기능을 이용한다.

공식 보안 권고는 성능 영향이 허용되는 경우 이를 검토할 수 있다고 설명했다.

그러나 워커가 요청마다 재생성되면 프로세스 생성 및 초기화 비용이 증가하므로 서비스 성능과 처리량에 영향을 줄 수 있다.

또한 PHP-FPM에 대한 모든 취약 경로가 반드시 동일한 형태의 요청 간 상태 재사용에 의존하는 것은 아니므로 정식 보안 업데이트를 대체할 수 없다.[1]

침해 여부 점검

편집 원본 편집

로그 및 설정 점검

편집 원본 편집

PHP 보안팀은 다음과 같은 로그와 오류를 점검하도록 권고했다.

  • PHP 스크립트 실행 이전에 반복적으로 발생하는 경고 및 사용 중단 경고
  • PHP 확장 모듈 또는 웹 서버 종료 과정에서 발생하는 오류
  • Parse Error 및 처리되지 않은 예외
  • Maximum execution time exceeded
  • 파일 업로드와 세션 처리 과정에서 발생하는 치명적 오류
  • 외부 요청으로 유발되는 특정 애플리케이션 경로의 오류
  • 정상적인 요청 처리 이전에 발생하는 PHP 워커의 비정상 종료

점검용으로 로그 설정을 강화할 경우 다음 설정을 검토할 수 있다.

log_errors=On
error_reporting=E_ALL

다만 이는 격리된 점검 환경에서의 오류 관측을 위한 설정이며, 실제 운영 환경에서는 로그량과 민감정보 기록 가능성 등을 검토해야 한다.

로그에 관련 오류가 없다는 사실만으로 취약점이 없다고 판단해서는 안 된다. 오류 메시지가 기록되기 전에 프로세스 상태가 손상되거나, 기존 로그 설정에서 일부 진단 정보가 누락되었을 수 있기 때문이다.[1]

공격 의심 징후

편집 원본 편집

관련 취약점군의 침해 여부를 조사할 때 다음 징후를 참고할 수 있다.

  • 비정상적으로 반복되는 HTTP POST 요청
  • 세션 업로드 진행률 관련 multipart 요청의 비정상적 증가
  • 치명적 오류 발생 직후 이어지는 의심스러운 요청 패턴
  • PHP 워커의 반복적인 비정상 종료
  • 웹 서버 프로세스에서 발생한 비정상적인 자식 프로세스 실행
  • 웹 루트 또는 임시 디렉터리의 의심스러운 파일 생성
  • PHP 워커에서 발생한 예상하지 못한 외부 네트워크 연결

Amazon Threat Intelligence는 PHP2Shell 공격 탐지 시 PHP_SESSION_UPLOAD_PROGRESS 문자열을 포함한 POST 요청, 비정상적인 프로세스 실행, 파일 변경 등을 점검하도록 권고했다.[5]

다만 관련 요청이나 오류가 관측되더라도 이를 곧바로 공격 성공 또는 CVE-2026-109619의 악용으로 확정할 수는 없다.

취약점 분류 및 심각도

편집 원본 편집

PHP 공식 보안 권고에는 다음 CWE 항목들이 연결되어 있다.

CWE 명칭 관련 내용
CWE-416 Use After Free 이미 해제된 요청별 메모리를 후속 요청에서 사용
CWE-755 Improper Handling of Exceptional Conditions 치명적 오류 등 예외 상황에서 내부 상태를 적절하게 정리하지 못함
CWE-824 Access of Uninitialized Pointer 유효하게 초기화되지 않은 포인터 접근
CWE-1325 Improperly Controlled Sequential Memory Allocation 연속적인 메모리 할당을 부적절하게 제어
CWE-1419 Incorrect Initialization of Resource 자원을 잘못되거나 불완전한 상태로 초기화

가장 직접적인 취약점 유형은 CWE-416(Use After Free)이다.[1]

CVSS v4.0: 9.2 (Critical)

CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N

지표 값 의미
AV N (Network) 네트워크를 통해 공격 가능
AC H (High) 높은 공격 복잡도
AT P (Present) 특정 공격 요구 조건 존재
PR N (None) 사전 권한 불필요
UI N (None) 사용자 상호작용 불필요
VC H (High) 취약한 시스템의 기밀성에 높은 영향
VI H (High) 취약한 시스템의 무결성에 높은 영향
VA H (High) 취약한 시스템의 가용성에 높은 영향
SC/SI/SA N (None) 후속 시스템에 대한 직접적인 영향은 기본 평가에 반영되지 않음

공격 복잡도가 높은 이유는 여러 요청을 통한 상태 조작, 동일 워커 재사용, 메모리 배치 등 추가적인 기술적 조건이 필요하기 때문이다.

그러나 공식 보안팀과 외부 연구진이 원격 코드 실행을 실증했으므로 실제 공격이 불가능하다는 의미는 아니다.

관련 취약점과의 차이

편집 원본 편집
항목 CVE-2026-109618 CVE-2026-109619
공식 명칭 RCE via OOM corruption RCE via stale global state
핵심 원인 메모리 부족에 의한 부분 초기화 및 상태 손상 요청 간 전역 상태의 수명 관리 실패
주요 취약 상태 초기화되지 않은 내부 자료구조 해제된 요청별 메모리를 참조하는 전역 상태
주요 발생 시점 메모리 할당 및 오류 처리 과정 요청 종료와 후속 요청 초기화 사이
대표적인 기술적 특징 OOM, 비정상적인 제어 흐름 중단, 부분 초기화 Producer/Consumer, Use After Free, 전역 포인터 잔존
공격 결과 원격 코드 실행 원격 코드 실행, 메모리 정보 노출
CVSS v4.0 9.2 9.2
수정일 2026년 10월 21일 2026년 10월 21일

두 취약점은 서로 다른 핵심 원인을 가지고 있지만, PHP 내부의 예외 처리와 메모리 관리 구조에서 비롯되므로 실제 공격 과정에서 여러 세부 결함이 결합할 수 있다.

따라서 하나의 공격 실증에 나타나는 모든 메모리 손상 동작을 특정 CVE 하나의 고유한 특징으로 단정하기는 어렵다.

목차