메뉴
← 기술 블로그
글자 크기
Security2026.10.24

PHP2Shell,
PHP 역사상 가장 위험한
취약점이 터졌다

CVE-2026-109618 / CVE-2026-109619CVSS 9.2 Critical — 인증 없이 원격 코드 실행.PHP 5.4부터 14년간 숨어 있던 결함이 드러났습니다.

지금 PHP를 운영 중이라면,이 글을 읽기 전에 패치부터 하세요.

PHP 공식 팀은 “완전한 완화 조치는 존재하지 않으며,업데이트만이 유일하게 안전한 선택”이라고 밝혔습니다.패치 버전: 8.5.12, 8.4.27, 8.3.36, 8.2.35 (2026년 10월 21일 릴리스).

10월 20일부터 시작된 72시간

2026년 10월 20일,“petecooper”라는 닉네임을 쓰는 누군가가PHP 코어에 존재하는 두 건의 Critical RCE 취약점 정보를공식 공개 전에 유출했습니다.

PHP 보안팀은 원래 10월 22일로 예정했던 공개 일정을하루 앞당겨 10월 21일 14:00 UTC에 긴급 패치를 배포했고,전 세계 정부 기관과 기업이 선제적으로 웹사이트를 내리는전례 없는 상황이 벌어졌습니다.

10/20 오전취약점 정보 사전 유출. watchTowr, VulnCheck 등 보안 연구팀이 재현 착수
10/20 오후PHP 보안팀, 공식 사전 공지 발표. CERT-EU, 싱가포르 CSA 등 각국 CERT 경보 발령
10/21 14:00 UTCPHP 8.5.12, 8.4.27, 8.3.36, 8.2.35 긴급 릴리스
10/21 이후유럽 정부기관 침해 사례 확인. AI 에이전트를 활용한 후속 공격 포착
10/22공개 익스플로잇 도구(PHP2Shell by Calif) 유통 확인

두 개의 CVE, 하나의 공격 체인

PHP2Shell이라 불리는 이 취약점은두 개의 서로 다른 메모리 안전성 결함을하나의 공격 체인으로 엮어 사용합니다.

둘 다 Use-After-Free(CWE-416) 클래스에 속하며,PHP 엔진 자체의 결함이기 때문에위에서 동작하는 애플리케이션 코드와 무관하게 영향을 받습니다.

CVE-2026-109618CRITICAL

OOM 메모리 손상을 통한 원격 코드 실행

RCE via Out-of-Memory Corruption

GHSA-w8hw-w9fx-j79wCWE-416 (Use After Free)CVSS v4.0: 9.2
CVE-2026-109619CRITICAL

해제된 전역 상태를 재사용한 원격 코드 실행

RCE via Stale Global State

GHSA-6wmf-4rv5-p3rpCWE-416 (Use After Free)CVSS v4.0: 9.2

CVE-2026-109618: OOM 메모리 손상

이 취약점의 핵심은PHP가 요청을 파싱하는 도중 메모리가 부족해지면초기화가 완료되지 않은 상태를 정리(cleanup)하면서초기화되지 않은 메모리를 유효한 데이터로 취급한다는 것입니다.

공격 흐름 (3단계)

1단계: OOM 트리거

공격자가 HTTP POST로 특수하게 조작된 폼 필드를 전송합니다.
필드 이름이 PHP 내부에서 여러 번 복사되면서
memory_limit를 초과하도록 설계되어 있습니다.
PHP의 기본 메모리 설정(128M)으로도 충분히 트리거됩니다.

2단계: 미완성 버킷에 데이터 주입

OOM으로 PHP가 longjmp()를 통해 bailout하면,
해시 테이블에 삽입 중이던 버킷이 초기화되지 않은 채 남습니다.
공격자는 이 빈 공간을 자신이 제어하는 데이터로 채웁니다.
PHP 배열은 소멸자 콜백(destructor callback)을 보유하고 있어,
이 콜백을 system()으로 덮어쓸 수 있습���다.

3단계: 정리 단계에서 코드 실행

PHP가 요청 정리(request shutdown) 과정에서
미완성 버킷을 유효한 배열로 인식하고 소멸자를 호출합니다.
소멸자가 system()을 가리키고 있으므로
공격자가 지정한 명령이 웹 워커 권한으로 실행됩니다.

mod_php 환경에서는 단일 HTTP 요청만으로애플리케이션 코드가 실행되기 전에 공격이 성공합니다.PHP-FPM에서는 워커가 초기화 실패 시 바로 종료되기 때문에RCE 난이도가 더 높지만, 애플리케이션 단계의 경로를 통해여전히 공격이 가능합니다.

또한 이 취약점 자체로 서버 메모리 내용이 노출됩니다.PHP의 upload-progress 핸들러가 해제된 워커 메모리를PHPSESSID 응답 쿠키에 포함시켜 반환할 수 있어,다른 요청의 비밀번호, 세션 토큰, API 키,TLS 개인키까지 유출될 수 있습니다.

CVE-2026-109619: Stale Global State

두 번째 취약점은 같은 메커니즘(longjmp bailout)을 사용하지만손상이 남는 위치가 다릅니다.요청 단위 메모리가 아닌 프로세스 범위의 전역 상태에해제된 메모리를 가리키는 포인터가 남습니다.

공격 흐름 (2단계, 요청 2회)

1단계: Poison (오염 요청)

공격자가 session.upload_progress를 포함한 multipart 요청을 보냅니다.
Fatal error(OOM, 타임아웃, 클라이언트 연결 끊기 등)가 발생하면
세션 ID, 핸들러 상태, 세션 변수, upload-progress 상태를 담은
전역 변수가 정상적인 shutdown 루틴으로 초기화되지 않습니다.
메모리는 해제되지만 전역 포인터는 그대로 남습니다.

2단계: Trigger (트리거 요청)

같은 워커가 다음 요청을 받으면
php_session_initialize()가 해제된(stale) 세션 ID를 읽고,
php_session_track_init()가 해제된 세션 값을 소멸시킵니다.
공격자는 해제된 320바이트 할당 영역을
위조된 Zend 호출 구조로 채우고(reclaim spray),
stale 포인터를 통해 system()을 호출합니다.

Session Upload Progress는 PHP 5.4.0부터 존재하며기본값이 활성화(enabled)입니다.따라서 대부분의 기본 설치 환경이 이 취약점의 전제 조건을 충족합니다.

직렬화(serialization) 경로와 세션 경로의 취약 코드는PHP 7.1과 PHP 5.4까지 거슬러 올라갑니다.즉, 14년 동안 잠복해 있던 결함입니다.

이미 실전에서 쓰이고 있다

watchTowr와 Palo Alto Unit 42는PHP2Shell의 실제 악용(in-the-wild exploitation)을 확인했습니다.

Unit 42 관측 사례: 유럽 정부기관 공격

공격자는 초기 침투 후 2시간 만에비밀번호 해시와 MFA 시크릿에 접근했습니다.NTLM-relay 터널을 Active Directory로 구축하고Domain Admin 권한 상승을 시도했습니다.

주목할 점은 후속 공격에에이전틱 AI 공격 플랫폼이 사용되었다는 것입니다.SQL 데이터베이스 정찰, 비밀번호 저장소 타겟팅,LDAP 구성 파일 접근까지AI가 기계 파싱 가능한 출력 형식으로 수행했습니다.

SOCRadar와 VulnCheck도 PHP2Shell 익스플로잇 도구가노출된 공격자 서버에서 발견되었다고 보고했습니다.공개된 도구 중에는 PHP 8.4.26 + Apache mod_php를 대상으로 한원클릭 익스플로잇(aslr_exploit.py)도 포함되어 있습니다.

영향 범위: PHP를 쓰면 전부 해당

PHP 엔진 자체의 결함이기 때문에위에서 동작하는 CMS, 프레임워크, 애플리케이션이아무리 안전해도 영향을 받습니다.

영향 확인된 소프트웨어 (Calif / Sansec 보고)

WordPress7.1.2

PHP 기반 CMS

Magento2.4.9

e-커머스

Drupal11.4.3

CMS

Joomla6.1.4

CMS

Laravel13.11

프레임워크

Symfony8.1

프레임워크

Nextcloud35.0.1

파일 공유

phpMyAdmin5.2.3

DB 관리

MediaWiki1.46.2

위키

Roundcube1.7.4

웹메일

WooCommerce

e-커머스 플러그인

WHMCS

호스팅 관리

영향받는 PHP 런타임 환경

Apache mod_php (가장 위험 — 단일 요청으로 RCE)
PHP-FPM (조건부 — 애플리케이션 경로 필요)
php-cgi, FrankenPHP, LiteSpeed 모두 영향

패치 버전

PHP 공식 보안 패치는 2026년 10월 21일 14:00 UTC에 릴리스되었습니다.패치의 핵심은 commit 506e87fa7d로,“bailout을 통한 상태 손상 방지”를 구현합니다.

구체적으로는 longjmp 대신 clean UnwindExit 경로를 추가하고,할당 실패 추적(ZEND_HAS_OOM()),전역 상태 리셋, oom_rfc1867_* 테스트 배터리를 도입했습니다.

PHP 8.5
8.5.11 이하
8.5.12
PHP 8.4
8.4.26 이하
8.4.27
PHP 8.3
8.3.35 이하
8.3.36
PHP 8.2
8.2.34 이하
8.2.35
PHP 8.1 (EOL)
전 버전
벤더 백포트 확인
PHP 8.0 (EOL)
전 버전
벤더 백포트 확인
PHP 7.x (EOL)
전 버전
벤더 백포트 확인
PHP 5.x (EOL)
전 버전
공식 패치 없음

PHP 8.2 EOL 주의

PHP 8.2는 2026년 12월 31일에 EOL(End of Life)입니다.
이번이 8.2 브랜치에서 받을 수 있는 마지막 보안 패치 중 하나일 수 있습니다.
8.3 이상으로의 마이그레이션을 계획하세요.

버전업이 당장 어렵다면: 임시 완화 조치

PHP 공식 팀은 “완전한 완화 조치는 없다”고 명시했습니다.아래 조치들은 알려진 공격 경로를 줄여주지만모든 변형을 차단하지는 못합니다.

영국 NCSC는 패치할 수 없는 시스템은오프라인으로 전환하는 것을 고려하라고 권고했습니다.

#1

session.upload_progress.enabled = 0

대상: CVE-2026-109619

효과: Session Upload Progress 기반 공격 경로 차단

부작용: 업로드 진행률 표시 기능 비활성화

#2

memory_limit = -1

대상: CVE-2026-109618

효과: OOM 트리거를 통한 메모리 손상 방지

부작용: 단일 요청이 서버 메모리 전체 사용 가능 — 모니터링 필수

#3

fatal_error_backtraces = 0 (PHP 8.5)

대상: CVE-2026-109619

효과: PHP 8.5에서 확인된 백트레이스 기반 공격 경로 차단

부작용: Fatal error 시 백트레이스 미출력

#4

post_max_size / upload_max_filesize 축소

대상: CVE-2026-109618

효과: OOM 조건 도달을 어렵게 만듦

부작용: 대용량 파일 업로드 실패 가능

#5

multipart/form-data 웹서버 레벨 차단

대상: 양쪽 모두

효과: PHP 파서 도달 전 요청 자체를 거부

부작용: 파일 업로드 기능 전면 중단

#6

pm.max_requests = 1 (PHP-FPM)

대상: CVE-2026-109619

효과: 워커 재사용 방지로 Stale State 공격 차단

부작용: 매 요청마다 워커 재생성 — 성능 저하

적용 위치별 설정 방법

mod_php: php.ini 또는 conf.d 하위 .ini에 설정 후 Apache 재시작
PHP-FPM: 풀 설정 파일(예: /etc/php/8.x/fpm/pool.d/www.conf)에
php_admin_flag[session.upload_progress.enabled] = off 추가 후 reload
Docker: Dockerfile에
RUN echo 'session.upload_progress.enabled=Off' > /usr/local/etc/php/conf.d/zz-php2shell.ini
추가 후 리빌드
검증:php -i | grep -E "upload_progress|memory_limit" 로 적용 확인

웹서버 레벨 추가 방어

PHP 파서에 요청이 도달하기 전에웹서버나 WAF에서 multipart/form-data를 차단하면공격 표면을 크게 줄일 수 있습니다.

Nginx — 파일 업로드가 필요 없는 경로에 적용

# 파일 업로드가 필요 없는 server block에 추가

if ($content_type ~* "multipart/form-data") {

return 403;

}

ModSecurity — PHP_SESSION_UPLOAD_PROGRESS 필드 차단

SecRule ARGS_POST_NAMES "@streq PHP_SESSION_UPLOAD_PROGRESS"

"id:1026109618,phase:2,deny,status:403,log,

msg:'PHP upload progress field blocked'"

대응 체크리스트

✓PHP 버전 확인: php -v 로 전체 서버의 PHP 버전 파악
✓패치 적용: 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 로 업데이트
✓즉시 패치 불가 시: session.upload_progress.enabled = 0 설정
✓추가 완화: memory_limit = -1, post_max_size 축소, multipart 차단
✓mod_php 사용 여부 확인: 가능하면 PHP-FPM으로 전환 (공격 난이도 상승)
✓EOL 버전 확인: PHP 7.x, 5.x는 공식 패치가 없으므로 벤더 또는 업그레이드 필수
✓침해 지표(IoC) 확인: 비정상 POST 요청, PHPSESSID 쿠키 크기 이상, 웹 워커 프로세스 이상
✓PHP 8.2 사용 중이라면: 2026년 12월 EOL 전에 8.3+ 마이그레이션 계획 수립

Wiz Research 팀은 이 취약점에 대해“PHP에서 발견된 가장 심각한 취약점이며,소프트웨어 역사상으로도 손꼽힌다”고 평가했습니다.

수십 년간 숨어 있던 결함의 악용 가능성을 증명하는 데극도로 복잡한 단계의 체인이 필요했지만,일단 공개되자 무기화는 빠르게 진행되었습니다.

PHP는 전 세계 웹의 약 70%를 구동합니다.“우리 서비스는 PHP를 안 쓰니까”라고 생각해도의존하는 인프라 어딘가에 PHP가 있을 수 있습니다.phpMyAdmin, Roundcube, Nextcloud 같은 관리 도구를잊지 마세요.

본 글은 리원에이스 기술개발본부가 작성한 기술 콘텐츠입니다. 외부 공유 시 출처를 명시해 주세요.

2026년 10월 24일
리원에이스 기술개발본부