Wiz Research는 전 세계 웹사이트의 70%를 구동하는 인기 범용 스크립팅 언어인 core PHP에서 여러 개의 치명적인 취약점을 발견했습니다. 성공적으로 악용될 경우, 공격자가 영향을 받는 서버를 장악하고 민감한 데이터를 훔치거나 해당 웹사이트를 변조할 수 있게 합니다.
PHP는 웹의 근간입니다. WordPress, Joomla, Drupal, Wikipedia의 MediaWiki 등 많은 웹사이트에 동력을 공급하는 프로그래밍 언어입니다.
이러한 취약점에는 메모리 노출(memory disclosure)과 애플리케이션 위에서 실행되는 것과는 별개로 **PHP 자체 내에서의 인증되지 않은 원격 코드 실행(unauthenticated remote code execution)**이 포함되어 있어, 영향을 받는 모든 웹사이트가 즉각적인 위험에 처하게 합니다. 지난 10년간 출시된 모든 PHP 버전이 이 취약점들 중 적어도 하나에 영향을 받으며, 버전 5.4까지 거슬러 올라갑니다. 공격자들은 이를 원격으로, 경우에 따라 상당히 쉽게 악용할 수 있습니다. 즉각적인 패치가 강력히 권고됩니다.
2026년 10월 21일, PHP는 core 엔진의 여러 메모리 안전성 취약점을 수정하는 패치를 출시했습니다.
이러한 발견들은 PHP에서, 어쩌면 소프트웨어 역사상 가장 심각한 취약점들 중 하나로 평가됩니다. 근본적인 결함은 수십 년 동안 존재해 왔지만, 그 악용 가능성을 입증하기 위해서는 인간 연구자가 실제로 달성할 수 있는 한계에 가까운 매우 복잡한 일련의 단계가 필요했습니다. Frontier AI 모델들은 이 장벽을 크게 낮추어 오랫동안 지속된 결함을 취약점(exploit)으로 만들었습니다.
본 포스트에서는 frontier AI가 지난 10년 이상 PHP 코드베이스에 숨겨져 있던 취약점을 발견하고 수정하는 데 어떻게 도움이 되었는지 설명합니다. 아래 설명된 문제들은 모두 10여 년 전에 결정된 핵심 아키텍처 결정에서 비롯되었으며, 심각도가 CVSS 9.2에 달하는 두 개의 CVE로 분류되었습니다. 이 작업은 고객을 보호하고, 변종(variants)을 찾고, 탐지 및 완화 조치를 배포하며, 조정된 공개를 위해 패치를 검증하는 교차 산업적 노력으로 확대되었습니다.
거의 모든 PHP 버전이 이 문제들 중 적어도 하나에 영향을 받으며, PHP 5.4로 거슬러 올라가는 릴리스도 포함됩니다. 이러한 취약점은 인증되지 않은 공격자가 영향을 받는 서버에서 코드를 실행하거나 민감한 프로세스 메모리를 읽을 수 있게 할 수 있습니다. 해당 메모리에는 다른 요청이나 서버 자체에 속하는 비밀번호, 인증 토큰, API 키 및 인증서가 포함될 수 있습니다.
PHP는 웹의 많은 부분을 담당하는 프로그래밍 언어로, WordPress, Drupal, 그리고 위키피디아를 구동하는 소프트웨어인 MediaWiki에 동력을 공급합니다. 핵심 엔진의 결함은 자체 애플리케이션 코드가 안전하더라도 이 생태계 전반의 웹사이트에 영향을 미칠 수 있습니다.
일부 취약점은 보안에 대한 근본적인 가정을 뒤흔들기 때문에 전환점이 됩니다. 2014년, Heartbleed는 인터넷을 보호하는 공유 인프라의 취약성을 노출했습니다. 2021년에는 Log4Shell이 소프트웨어 종속성이 얼마나 깊숙이 내재되어 있어 조직들이 식별하기 어려울 정도로 광범위한 노출을 만들 수 있는지 보여주었습니다. 우리는 PHP2Shell이 AI 시대에 유사한 전환점이 될 수 있다고 믿으며, 이는 AI가 오랫동안 존재해 온 취약점의 실제 악용 가능성을 어떻게 변화시킬 수 있는지 보여줍니다. 익스플로잇(exploit)을 구축하려면 여러 결함을 연결하고 반복적인 테스트와 디버깅을 통해 각 대상의 메모리 레이아웃에 적응해야 했습니다. Frontier 모델은 이 과정을 실질적으로 만드는 데 결정적이었으며, 몇 시간 만에 여러 애플리케이션 전반에 걸쳐 작동하는 익스플로잇을 개발하고 조정할 수 있게 해주었습니다. 이러한 작업을 수행하는 데 필요한 시간과 전문 지식이 감소함에 따라, 복잡성이 더 이상 의미 있는 장벽을 제공하지 못하게 되어 실제로 무엇이 취약한지에 대한 정의를 바꿀 수 있습니다.
Wiz Research는 발견, 조정 및 패치 검증 작업에 기여한 PHP 팀, Calif, 그리고 OpenAI에게 감사를 표합니다. OpenAI와 Calif는 또한 이 취약점의 역사, 기술적 세부 사항, 공개 프로세스에 대한 통찰력을 담은 블로그도 게시했습니다. PHP 역시 게시했습니다.
또한, 패치를 즉시 적용할 수 없는 고객들을 위해 가이드를 준비하고 즉각적인 완화책을 제공해 준 Automattic, Akamai, AWS, Cloudflare, Fastly, Google, Imperva, Microsoft, Vercel 및 다른 많은 분들께 진심으로 감사를 표합니다.
공개된 모든 취약점은 PHP가 요청을 처리하는 과정에서 치명적인 오류(fatal errors)를 다루는 방식의 버그로 인해 발생하는 메모리 안전성 문제입니다. 특히 메모리 부족 오류(out-of-memory errors)와 관련이 있습니다. 이러한 버그들은 요청이 예기치 않게 끝난 후 내부 PHP 상태가 손상된 채 남아 있게 할 수 있습니다. 이후의 요청이나 워커가 이 오래된(stale) 상태를 재사용하면서 메모리 노출 또는 손상을 초래할 수 있습니다.
아래 표에서는 우리가 PHP에 보고한 각 버그가 어떤 종류의 영향을 미칠 수 있는지 보여줍니다. 아래 나열된 애플리케이션들은 RCE 시연을 위해 선택한 대상입니다. 이들은 대표적인 대상이며, 취약한 코드가 PHP 자체에 있기 때문에 이러한 CMS(콘텐츠 관리 시스템) 중 하나를 사용할 필요는 없습니다.
| 추적 ID | 버그 | 공격자가 달성할 수 있는 것 | 우리가 입증한 내용 |
|---|
| CVE-2026-109618 | Upload-progress unserializer use-after-free 원격 프로세스-메모리 노출 | 프로세스 메모리를 손상시키고 코드를 실행할 수 있음 | 인증되지 않은 PHP 워커 메모리 노출 |
| CVE-2026-109619 | Fatal-error backtrace use-after-free OPcache 타입 혼란 | 프로세스 메모리를 손상시키고 코드를 실행할 수 있음 | 공유 PHP 상태를 손상시키고 코드를 실행할 수 있음 |
본 블로그는 이 문제의 문제가 되는 패턴을 따르는 취약한 버그 네 가지 사례(두 개의 CVE로 그룹화됨)만을 다루지만, PHP 코드베이스에는 추적되었거나 아닐 수 있는 다른 변종들이 존재합니다. 이러한 변종들은 악용에 대한 서로 다른 요구사항을 가지고 있으며, 다양한 유형의 영향을 초래할 수 있습니다. 어쨌든, PHP 팀이 제공한 패치는 문제의 핵심에서 이를 수정하고 패치된 릴리스에서 모든 변종을 제거합니다.
저희는 이 취약점들을 하나의 익스플로잇 스크립트인 php2shell로 결합하여, 테스트 당시 최신 컨테이너 이미지를 사용하는 WordPress(wordpress:latest), Drupal(drupal:latest), 그리고 Joomla(joomla:latest) 배포판에서 인증 없이 원격으로 코드를 실행할 수 있음을 시연했습니다.
이러한 플랫폼들은 영향 범위를 보여주지만, 취약점 자체는 PHP에 있습니다. 악용은 애플리케이션 코드의 결함에 의존하지 않습니다. 심지어 영향을 받는 PHP 버전을 사용하는 간단한 “Hello World” 애플리케이션도 취약할 수 있습니다.
별도로, 저희는 공격자들이 원격 코드 실행을 달성할 필요 없이 비밀번호, 토큰, API 키를 포함하여 PHP 프로세스의 메모리에서 민감한 데이터를 읽어낼 수 있음을 시연했습니다.
Wordpress, Joomla, 그리고 Drupal에 대한 PHP2Shell 시연:
취약한 코드는 10년 이상 존재해 왔습니다. 이러한 결함들을 작동하는 익스플로잇으로 만드는 과정은 여러 버그를 연결하고 PHP가 요청 간에 메모리를 할당하고 재사용하는 방식을 고려해야 했습니다. 메모리 버그는 악명 높을 정도로 복잡하며, PHP 버전, 구성 및 애플리케이션 동작의 차이가 익스플로잇이 의존하는 가정을 무너뜨릴 수 있습니다. 한 배포판에서 작동하는 공격은 다른 배포판에서 작동하려면 상당한 조정이 필요할 수 있으며, 각각 추가적인 분석, 테스트 및 디버깅을 요구합니다. AI 이전에는 이러한 수동 작업은 구현하기 어려웠고 확장하기는 더욱 어려웠습니다.
AI가 등장하면서 이는 더 이상 장벽이 아닙니다. LLM은 다양한 PHP 버전, 구성 및 메모리 레이아웃에 맞춰 익스플로잇(exploit)을 조정하는 데 도움을 줄 수 있습니다. 테스트 및 디버깅 도구를 사용하여 모델은 실패를 분석하고 조정을 반복함으로써 각 타겟에 필요한 전문가의 노력을 줄입니다. 이는 여러 배포 환경에 걸쳐 공격을 확장하는 진입 장벽을 크게 낮춥니다.
이는 발견과 악용(exploitation) 모두의 경제성을 변화시킵니다. AI가 복잡한 익스플로잇을 개발하고 조정하는 데 필요한 노력을 줄임에 따라, 한때 악용하기 비현실적으로 보였던 취약점들이 실행 가능한 목표가 됩니다.
저희는 이 연구 전반에 걸쳐 Wiz Atlas, Gemini 4 Argon 및 GPT-5.6 Sol을 사용했습니다. 특히 Gemini 4 Argon은 취약점 발견, 익스플로잇 개발, 공격 탐지 및 패치 검증에 매우 귀중한 기여를 했습니다.
Gemini 4 Argon을 활용하여 Wiz 팀은 최첨단 AI가 사이버 방어에 어떻게 판도를 바꾸는지 보여주었습니다. 10년 이상 동안 이러한 중요한 취약점들은 취약점 발견과 악용이 믿을 수 없을 만큼 복잡했기 때문에 해결되지 않은 상태로 남아 있었습니다. Gemini 4 Argon이 방어자들이 이 간극을 메우는 데 도움을 주고, 취약점을 찾아 패치하는 것을 도와주게 되어 기쁩니다.
Raluca Ada Popa, Google DeepMind의 Gemini 보안 책임자
공개되기 전에 Wiz Research는 PHP 팀, Calif 및 OpenAI와 발견, 조정 및 패치 검증 작업을 수행했습니다. 또한 저희는 고객이 즉시 업데이트할 수 없는 조직을 위해 고객 가이드라인, 탐지 규칙 및 기본 완화책(out-of-the-box mitigations)을 준비하기 위해 Google Cloud, Cloudflare, AWS, Microsoft, Automattic, Fastly, Akamai, Imperva, Vercel 등 많은 파트너와 협력했습니다.
핵심 PHP의 취약점은 단일 애플리케이션을 훨씬 넘어섭니다. PHP는 클라우드, 호스팅 제공업체, 콘텐츠 전송 네트워크(CDN) 및 수백만 개의 독립적으로 관리되는 서버에 걸쳐 실행됩니다. 기술적 세부 사항이 공개되기 전에 노출을 줄이기 위해서는 전체 생태계에 걸친 조정된 작업이 필요했습니다.
PHP의 세션 모듈은 업로드 진행 상황 처리 과정에서 동일한 사전 초기화(pre-initialization) 창 동안 세션 데이터를 디코딩할 수 있습니다. 이 디코더는 요청 소유의 장부 기록을 BG(unserialize)에 저장합니다.
치명적인 할당 실패(fatal allocation failure)가 이 경로를 중단시키고, 요청 힙(request heap)을 파괴하며, unserializer의 전역 상태를 노출시킵니다.
동일한 워커(worker)가 처리하는 나중에 요청에서 PHP는 공격자가 되찾은 메모리를 활성 unserializer 장부 기록으로 소비할 수 있습니다. 이 오래된 상태(stale state)는 강력한 메모리 손상 원시 요소(memory-corruption primitive)가 됩니다. 우리는 이를 메모리 노출(memory disclosure)과 결합하여 주소 불확실성을 제거했고, WordPress, Drupal, 그리고 Joomla에서 인증되지 않은 원격 코드 실행(unauthenticated remote code execution)을 달성했습니다.
WordPress, Drupal, Joomla 체인은 대표적인 시연 사례입니다. 근본적인 원시 요소는 PHP 엔진 수준에 존재하며 취약한 버전을 사용하는 모든 PHP 애플리케이션에 영향을 미칠 수 있습니다.
이러한 문제들은 애플리케이션 계층 아래에서 실행되므로, 애플리케이션 로그에는 맥락이 거의 포함되어 있을 수 있습니다. 시스템이 패치될 때까지 방어자들은 비정상적인 멀티파트 요청(multipart requests)에 이어 메모리 제한 오류 또는 반복되는 HTTP 500 응답, 예상보다 크거나 잘못된 PHPSESSID 응답 쿠키, 그리고 설명할 수 없는 PHP 워커 변동에 특히 주의를 기울여야 합니다. 이러한 신호들은 조사 방향을 제시할 수 있습니다. PHP 보안 업데이트를 적용하는 것이 유일하고 완전한 해결책입니다.
PHP는 요청 시작 시점(request startup)에 RFC1867 멀티파트 요청을 파싱하며, 정상적인 모듈 초기화가 완료되기 전입니다. 세션 업로드 진행 상황 처리는 이 초기에 세션 상태를 초기화하고 PS(id)에 세션 ID를 게시할 수 있습니다. 메모리 부족 오류(out-of-memory error)는 정리 작업이 완료되기 전에 요청을 중단시킬 수 있습니다. 그러면 PHP는 요청 힙을 파괴하고, PS(id)가 해제된 할당을 가리키도록 남길 수 있습니다.
동일한 워커가 처리하는 나중 멀티파트 요청은 정상적인 세션 초기화가 해당 포인터를 재설정하기 전에 업로드 진행 상황 정리 경로에 도달할 수 있습니다. PHP는 오래된 포인터와 길이를 활성 zend_string으로 신뢰합니다.
그리고 복구된 힙 내용을 PHPSESSID 응답 쿠키에 URL 인코딩합니다. 이 공격은 애플리케이션이 session_start()를 호출하지 않아도 작동하므로, 취약점이 특정 애플리케이션에 국한되지 않습니다 (application-agnostic). 우리는 공격자의 요청 범위를 벗어난 데이터를 포함하는 살아있는 워커 메모리의 공격자 크기 영역을 인증 없이 노출하는 것을 시연했습니다.
영향을 받는 버전에서 PHP는 EG(last_fatal_error_backtrace)에 가장 최근의 치명적인 오류의 백트레이스(backtrace)를 유지합니다. 치명적인 메모리 부족 오류는 요청 힙을 파괴할 수 있지만, 이 실행기 전역 값(executor-global value)을 정의 해제하지는 않습니다. 워커는 이전 요청의 메모리를 가리키는 전역 값을 가진 채 생존합니다.
만약 같은 워커가 다음 요청 초기에 진단 정보를 방출하면, 실행기가 해당 상태를 재초기화하기 전에 포인터에 접근할 수 있습니다. PHP는 그 후 불안정한 백트레이스를 파괴하거나 업데이트하고 공격자가 복구한 메모리를 따릅니다. 결과적으로 발생하는 교차 요청 사용 후 해제(cross-request use-after-free)는 제어된 메모리 손상으로 발전될 수 있습니다. 우리는 이 원시 기능을 사용하여 Drupal에 대한 인증 없는 원격 코드 실행(remote code execution)을 시연했습니다.
OPcache는 컴파일된 PHP 구조체를 공유 메모리에 영구 저장하고, 워커별 런타임 포인터 맵에 인덱스를 할당합니다. 워커들은 공유 프론티어(shared frontier)를 통해 해당 인덱스를 조정합니다. zend_accel_script_persist() 동안 PHP는 프로세스 로컬의 CG(map_ptr_last)를 진행시킵니다.