PHP2셸 (PHP2Shell)

두 가지 치명적인 PHP 버그인 CVE-2026-109618과 CVE-2026-109619는 인증되지 않은 공격자가 HTTP를 제공하는 모든 SAPI에서 코드를 실행할 수 있게 합니다. 서버를 확인하는 방법, 8.5.12/8.4.27/8.3.36/8.2.35로 패치하는 방법, 그리고 이 우회 방법이 실제로 무엇을 커버하는지 알아보세요.

Ashley Innocent

Ashley Innocent

23 October 2026

PHP2셸 (PHP2Shell)

Apidog 엔터프라이즈

온프레미스 배포

SSO & RBAC

SOC 2 준수

Apidog Enterprise 살펴보기

2026년 10월 21일, PHP 프로젝트는 인증되지 않은 공격자가 웹 서버에서 코드를 실행할 수 있게 하는 두 가지 치명적 버그에 대한 긴급 릴리스를 배포했습니다. 이 두 취약점은 CVE-2026-109618과 CVE-2026-109619로 추적되며 PHP2Shell이라는 이름으로 불립니다. 둘 다 CVSS v4.0에서 9.2점을 기록했고, HTTP를 제공하는 모든 PHP 환경에 영향을 미치며, 아마존의 허니팟은 패치가 존재하기 나흘 전인 10월 17일에 익스플로잇 시도들을 기록했습니다.

PHP는 서버 사이드 언어가 알려진 웹사이트 중 69.3%에서 실행됩니다(W3Techs). PHP API, Laravel이나 Symfony 백엔드, WordPress 사이트, 또는 PHP가 내장된 컨테이너 이미지를 운영하고 있다면, 이번 건은 여러분의 일입니다.

이 가이드에서는 이 버그들이 무엇을 하는지, 어떤 버전이 영향을 받는지, 서버를 어떻게 확인하는지, 완화 조치가 실제로 무엇을 해 주는지, 그리고 패치 후 API가 여전히 작동하는지 어떻게 검증하는지 다룹니다.

button

TL;DR

질문 답변
무엇인가? PHP의 요청 처리에서 발생하는 두 가지 메모리 안전성 버그로, 연쇄적으로 원격 코드 실행에 이어짐
CVE CVE-2026-109618 (메모리 부족 시 손상), CVE-2026-109619 (오래된 상태, use-after-free)
심각도 각각 CVSS v4.0 9.2 (초기에 유출된 ID는 10.0이라고 했으나 PHP 측은 그것이 잘못되었다고 밝힘)
인증 필요? 아니오
영향 범위 HTTP를 제공하는 모든 SAPI: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP, LiteSpeed
수정 버전 8.5.12, 8.4.27, 8.3.36, 8.2.35
PHP 8.1 및 그 이하 공식 릴리스 없음; 7.4, 8.0, 8.1용 최소한의 소스 백포트 제공; 5.4부터 7.3까지는 아무것도 없음
익스플로잇 되었나? 10월 17일부터 시도가 관측됨(아마존), Cloudflare가 초기 공격을 보고
해결책 업그레이드하고 모든 워커를 재시작. 우회 조치는 위험을 줄여줄 뿐 완전히 막지는 못함

PHP2Shell이 실제로 무엇인가

두 버그는 하나의 근본 원인을 공유합니다. 요청이 비정상적으로 종료될 때 PHP가 메모리를 손상된 상태로 남겨둘 수 있고, 그 뒤 정리 코드가 그 손상된 상태를 신뢰한다는 점입니다.

CVE-2026-109618: 요청 시작 중 메모리 부족으로 인한 손상. PHP가 폼 데이터를 $_POST로 파싱할 때, Zend 엔진의 해시 테이블 코드는 새 키를 할당하기 전에 항목 카운터를 증가시킵니다. Datadog의 분석은 이를 zend_hash.c의 _zend_hash_str_add_or_update_i()까지 추적합니다. 만약 그 할당이 memory_limit을 초과하면, PHP는 치명적 오류를 발생시키고 삽입을 포기합니다. 이제 카운터에는 설정된 적 없는 버킷이 포함됩니다. 종료 시 PHP는 $_POST를 파괴하면서 카운트된 모든 버킷을 실제 존재하는 것으로 취급합니다.

API 팀이 걱정해야 할 부분은 이것입니다. 이 현상은 여러분의 코드가 단 한 줄도 실행되기 전, PHP가 아직 요청 본문을 파싱하는 동안 발생합니다. 여러분의 인증 미들웨어, 요청 제한기, 입력 검증은 이 요청을 보지 못합니다. Datadog은 파일 업로드가 아닌 평범한 application/x-www-form-urlencoded 본문으로 이를 재현했습니다.

CVE-2026-109619: 요청 간에 남는 오래된 전역 상태. PHP는 요청별 메모리를 가리키는 워커 전역 상태를 일부 유지합니다. 만약 치명적 오류가 그 상태의 초기화를 방해하거나, 늦은 종료 진단이 정리 이후에 그 상태를 다시 생성하면, 같은 워커에서 처리되는 다음 요청이 해제된 메모리를 읽게 됩니다. PHP는 두 가지 경로를 확인했습니다:

PHP 보안 팀은 mod_php를 가장 높은 위험으로 평가합니다. 시연된 익스플로잇이 애플리케이션 코드가 로드되기 전에 단일 비인증 요청으로 발동하기 때문입니다.

누가 발견했나 (그리고 왜 AI가 헤드라인에 오르는가)

이 버그들은 PHP 5.4.0에서 도입된 코드까지 거슬러 올라가므로, 10년 넘게 코드베이스에 남아 있었습니다. PHP 재단은 Calif, OpenAI, Wiz의 공로를 인정했습니다.

Decrypt와 The Next Web의 보도에 따르면, Calif의 연구원 Ryan Austin이 8월에 OpenAI의 GPT-5.6 Sol의 도움을 받은 소스 감사 중에 이 결함들을 발견했습니다. OpenAI는 자사 팀이 9월에 “Patch the Planet” 작업의 일환으로 더 완전한 버전을 발견했다고 밝혔습니다. Wiz는 Gemini 4 Argon, Wiz Atlas, GPT-5.6 Sol을 사용해 두 버그를 독자적으로 발견했다고 합니다. 공로를 두고 논쟁이 있지만, 핵심은 변하지 않습니다. AI 지원 감사가 이제 핵심 인프라에서 10년 된 메모리 버그를 찾아내고 있으며, 공격자들도 같은 모델을 보유하고 있습니다.

타임라인: 패치가 하루 일찍 나온 이유

날짜 (2026) 무슨 일이 있었나
8월~9월 Calif, OpenAI, Wiz가 비공개로 버그를 신고
10월 17일 아마존의 MadPot 허니팟이 익스플로잇 시도를 기록
10월 20일 CVE ID가 Hacker News와 소셜 미디어에 유출됨; PHP가 사전 공지 게시; CERT-EU가 권고 2026-018 발행
10월 21일 14:00 UTC PHP가 수정 버전 배포, 유출 이후 10월 22일에서 앞당김; CISA가 경보 발행; Cloudflare가 초기 공격 보고
10월 22일 두 CVE 모두 아직 CISA의 KEV 카탈로그에 없음

아마존은 공개 날짜가 아니라 10월 17일부터 조사를 권고합니다(Tenable의 FAQ가 전체 타임라인을 추적합니다). 릴리스 시점에 PHP 팀은 유출 이후 나타난 개념 증명 코드를 검사했으며 작동하는 익스플로잇은 발견하지 못했다고 밝혔습니다. 이후 watchTowr는 두 버그를 모두 재현했다고 말했습니다. 발견하는 어떤 “PoC” 저장소든 의심하고 대하세요. 검증되지 않은 익스플로잇 코드에는 종종 악성코드가 포함됩니다.

영향을 받았나? 5분 안에 확인하기

1. 노트북이 아니라 트래픽을 처리하는 런타임을 확인하세요. CLI 바이너리는 FPM이나 Apache 모듈과 버전 및 설정이 다를 수 있습니다.

# On the server or inside the running container
php -v
php-fpm -v
# Apache mod_php: check the loaded module version
apachectl -M 2>/dev/null | grep -i php

또는 보호된 라우트에서 한 번 노출시켰다가 이후 제거하세요:

<?php echo PHP_VERSION, ' ', PHP_SAPI;

2. 수정 버전과 비교하세요.

브랜치 취약 수정 버전
8.5 < 8.5.12 8.5.12
8.4 < 8.4.27 8.4.27
8.3 < 8.3.36 8.3.36
8.2 < 8.2.35 8.2.35
7.4 ~ 8.1 전부 소스 백포트만, 또는 벤더 LTS
5.4 ~ 7.3 전부 수정 없음

Debian, Ubuntu, Red Hat 및 기타 배포판은 업스트림 버전 문자열을 바꾸지 않고 수정 사항을 백포트하는 경우가 많습니다. php -v가 더 오래된 숫자를 보여준다면, 당황하기 전에 배포판의 권고를 읽어보세요.

3. 숨어 있는 PHP를 목록화하세요. 몇 달 전에 FROM php:8.3-fpm으로 빌드한 컨테이너, 벤더 어플라이언스, 직접 컴파일한 빌드, 잊힌 서브도메인의 관리자 패널 등입니다. Cisco는 이미 자사 제품군을 확인하라는 권고를 발행했습니다. Shodan은 인터넷에 노출된 PHP 호스트를 190만 개 이상으로 집계하며, 한 연구원은 130만 개 이상이 취약할 수 있다고 추정합니다.

패치하는 방법

# Debian / Ubuntu (Ondřej Surý PPA or distro packages)
sudo apt update && sudo apt install --only-upgrade 'php8.*'

# RHEL / Rocky / Alma with Remi
sudo dnf upgrade 'php*'

# Official Docker image: rebuild on a fixed tag
docker pull php:8.4.27-fpm
docker build --pull -t my-api:patched .

그런 다음 대부분의 팀이 잊는 단계를 수행하세요. 모든 PHP 워커를 재시작하거나 교체하세요. 실행 중인 FPM 풀은 메모리에 옛 바이너리를 유지합니다. php-fpm을 재시작하고, Apache를 리로드하고, 모든 컨테이너를 롤링하세요. CVE-2026-109619는 워커 내부에서 요청 간에 유지되는 상태에 관한 것이므로, 재시작하지 않은 워커는 여전히 취약합니다.

8.1 이하에서는 세 가지 선택지가 있습니다. 벤더 LTS 패키지, PHP 소스 백포트로 빌드, 또는 8.2+로 업그레이드입니다. CISA는 패치할 수 없는 PHP 시스템을 오프라인으로 전환할 것을 권고했으며, 영국 NCSC와 FBI도 같은 입장을 밝혔습니다.

오늘 패치할 수 없다면 적용할 완화 조치

이것들은 시간을 벌어줍니다. PHP 코어 팀의 Gina Peter Banyard는 BleepingComputer에 어떤 완화 조치도 공격을 완전히 차단하지는 못한다고 말했습니다.

CVE-2026-109618의 경우:

CVE-2026-109619의 경우:

엣지 계층에서: Cloudflare는 무료 요금제를 포함한 모든 요금제에 알려진 벡터에 대한 WAF 규칙을 배포했습니다. CTO는 그것들이 임시적이라고 말했습니다.

어떤 php.ini 변경이든 이후에는 모든 워커를 재시작해야 하며, 그렇지 않으면 적용되지 않습니다.

이미 공격을 당했다는 징후

Datadog의 탐지 지침은 결국 네 가지 신호로 요약됩니다:

상태 코드를 믿지 마세요. Datadog의 정교한 익스플로잇은 HTTP 200을 반환했고 워커는 계속 실행되었습니다. 로그를 10월 17일까지 거슬러 검색하세요.

패치 후 API가 여전히 작동함을 증명하세요: 에이전트가 실행하게 하세요

압박 속에서 프로덕션 PHP를 패치하는 것은 마이너 버전 업이 뭔가를 바꿨다는 걸 뒤늦게 알게 되는 지름길입니다. 수정 사항을 롤아웃하기 전과 후에 스테이징에서 API 테스트 스위트를 실행하고, 코딩 에이전트가 Apidog CLI로 이를 수행하도록 하세요.

설정 (한 번만):

npm install -g apidog-cli
apidog auth login --with-token <your-access-token>
apidog test-suite list --project <projectId>

Claude Code, Codex 또는 Cursor에 보낼 한 줄 프롬프트:

PHP2Shell 대응으로 방금 스테이징의 PHP를 8.4.27로 업그레이드했습니다. Apidog CLI를 사용해 스테이징 환경에 대해 회귀 테스트 스위트를 실행하고, HTML 및 JUnit 리포트를 작성하고, 실패한 엔드포인트를 요약해 주세요. 그런 다음 nginx의 client_max_body_size를 초과하는 본문을 가진 POST가 PHP에 도달하지 않고 프록시에서 413으로 거부되는지 확인해 주세요.

에이전트가 실행하는 것:

apidog test-suite run <testSuiteId> --project <projectId> -e <stagingEnvId>

apidog run --test-suite <testSuiteId> --project <projectId> -e <stagingEnvId> \
  -r cli,html,junit --out-dir ./php2shell-reports --upload-report

-r은 리포터를 선택하고, --out-dir은 리포트가 저장될 위치를 지정하며, --upload-report는 Apidog 앱에서 열 수 있는 요약을 업로드합니다. --notification-failed-event <targetId>를 추가하면 뭔가 깨졌을 때만 팀에 알림을 보냅니다. 같은 apidog run 명령을 CI에 넣으면 다시 빌드되는 모든 PHP 이미지가 배포 전에 테스트됩니다. Claude Code 설정 가이드와 CI/CD 파이프라인 워크스루에서 두 가지 모두를 자세히 다룹니다.

이전 버전에서 한 번 스위트를 실행해 기준선을 확보하고, 업그레이드 후에 한 번 실행해 비교하세요. 실패할 거라 예상하지 못했던 테스트가 실패한다면, 사용자보다 먼저 알게 될 것입니다. Apidog 다운로드로 CLI가 실행하는 스위트를 구축하고 관리하세요.

FAQ

PHP2Shell이 실제로 익스플로잇되고 있나요? 아마존은 10월 17일부터 시도를 보았고 현재 광범위하게 익스플로잇되고 있다고 밝혔으며, Cloudflare와 watchTowr도 공격을 보고했습니다. CISA는 10월 22일 기준으로 익스플로잇을 확인하지 않았습니다.

우리 프레임워크가 보호해 주나요? 아닙니다. CVE-2026-109618은 Laravel, Symfony, WordPress가 로드되기 전, PHP가 본문을 파싱하는 동안 발동합니다.

공유 호스팅을 쓰고 있습니다. 어떻게 해야 하나요? 호스팅 업체의 상태 페이지를 확인하세요. SiteGround 등은 패치했다고 밝혔습니다. 만약 여러분의 업체가 아무 말도 하지 않았다면 문의하세요.

session.upload_progress.enabled=0이면 충분한가요? 아닙니다. 하나의 CVE에 대한 한 가지 경로만 커버합니다. 패치하세요.

시크릿을 교체해야 하나요? CVE-2026-109619는 메모리 노출을 허용합니다. 10월 17일 이후 로그에 침해 징후가 보인다면, PHP 프로세스가 읽을 수 있었던 데이터베이스 비밀번호, API 키, 세션 시크릿을 교체하세요.

핵심 요약

8.5.12, 8.4.27, 8.3.36 또는 8.2.35로 업그레이드하세요. 모든 워커를 재시작하세요. 잊고 있던 PHP를 찾아내세요. 10월 17일까지 거슬러 로그를 확인하세요. 그런 다음 API 테스트를 실행해 수정이 다음 장애가 되지 않도록 하세요. PHP가 8.1 이하라면, 이번 주가 마침내 그 버전에서 벗어날 때입니다.

Apidog에서 API 설계-첫 번째 연습

API를 더 쉽게 구축하고 사용하는 방법을 발견하세요