PHP2Shell 히어로 카드: 실패한 요청에서 원격 코드 실행까지, CVE-2026-109618 및 CVE-2026-109619
Engineering & Research

OrcaCyber Research - PHP2Shell: 실패한 요청이 어떻게 원격 코드 실행으로 이어졌는가

작성자

Rowan Sterling

게시일

최신 모델 · 20모든 모델 보기 →
벤치마크: Artificial Analysis · 매일 업데이트
모든 게시물로 돌아가기

이번 조사에서의 개념 증명은 OrcaCyber Zero 및 OrcaCyber Ultra 모델을 사용하여 작성되었습니다. 연구 번들에는 소스 수준 분석, 공개 익스플로잇을 각색한 것을 활용한 통제된 재현, 메모리 노출 아티팩트, 프로세스 크래시, 그리고 명령 실행 증거가 문서화되어 있습니다. 제공된 파일에는 각 모델이 어떤 단계를 수행했는지가 독립적으로 기록되어 있지 않으며, 모델 귀속 정보는 연구팀이 제공한 것입니다.

치명적인 메모리 부족 상태는 요청을 안전하게 종료해야 한다. 여기서는 네이티브 상태가 일부만 초기화된 동안 PHP를 중단시켜, 다음 요청까지 지속되는 참조를 남길 수 있었다. 그 결과 테스트 환경에서 정보 노출부터 원격 코드 실행에 이르는 결과를 초래하는 요청 간 메모리 수명 위반이 발생했다.

주요 증거 한눈에 보기

• 대상 — PHP 8.4.26, Apache/mod_php, 단일 워커, 격리된 Docker 랩.

• 크래시 로그 — 제공된 발췌본에서 SIGABRT 1건과 SIGSEGV 워커 종료 3건이 확인됩니다.

• HTTP 응답 — URL 디코딩된 PHPSESSID 값의 819,200바이트.

• 실행 증명 — code>uid=33(www-data) gid=33(www-data) groups=33(www-data)/code>.

• 회귀 — 보고서는 패치된 PHP 8.4.27에서의 네 차례 실패한 시도를 설명합니다. 원시 실행 기록은 함께 제공되지 않습니다.

출처: 업로드된 REPORT.md, crash_evidence.log, leak_attempt.resp, rce_proof_8426.txt. 아래에 설명된 증거 자료는 해당 아티팩트를 조판된 증거 패널로 재현한 것이며, 사진이나 실제 터미널 스크린샷이 아닙니다.

1. 취약점: 요청 경계 소유권 실패

두 가지 관련 문제는 중단된 요청 초기화와 오래된 런타임 전역 포인터에 관한 것입니다. 관련 PHP 아키텍처에서는 multipart/form-data 처리와 세션 업로드 진행 콜백이 일반 사용자 애플리케이션 코드보다 먼저 실행될 수 있습니다. 예외적인 제어 흐름 전환은 code>zend_bailout()/code>을 포함하여, 예상된 정리를 건너뛰고 상태가 나중에 해제되거나 재사용되는 메모리를 가리키도록 남길 수 있습니다.

보안 불변 조건: 요청 B에 노출된 워커 전역 참조는 소유권과 수명이 요청 A와 함께 종료된 메모리를 절대 참조해서는 안 됩니다. 보고된 실패는 이 불변 조건을 위반합니다.

시연된 엔드포인트는 단순히 OK를 반환하는 최소한의 PHP 페이지였으며, 익스플로잇 시나리오는 애플리케이션 수준의 SQL 인젝션, 파일 포함, 또는 역직렬화 엔드포인트에 의존하지 않았다.

2. 기술적 순서

• A1 — 중단. 멀티파트 및 업로드 진행률 처리는 정리 중 OOM을 유발하여 오래된 세션 상태를 남깁니다.

• B1 — 누출. 후속 요청으로 인해 세션 쿠키 직렬화가 유효한 세션 ID를 초과하여 읽게 됩니다.

• 주소 복구. 유출된 포인터 값을 사용하여 해당 빌드에서 관련 라이브러리 및 힙 레이아웃을 추론합니다.

• A2/B2 — 손상. 추가로 두 번의 요청 시퀀스가 형태를 이루고, 종료 시 사용된 오래된 데이터를 리디렉션합니다.

• 결과. 조정된 공개 익스플로잇은 www-data 권한으로 명령 실행을 보고합니다.

Five-step diagram of the PHP2Shell chain from OOM interruption to command execution as www-data, reconstructed from the research bundle

증거 자료: 제공된 파일이 실제로 보여주는 내용

증거 A — Apache 로그에서 발생한 워커 종료

• code>[core:notice] [pid 1:tid 1] AH00051: 자식 프로세스 pid 54가 시그널 Abort(6)로 종료되었습니다. /etc/apache2에 코어 덤프가 생성되었을 수 있습니다/code>

• code>[core:notice] [pid 1:tid 1] AH00051: 자식 pid 55가 신호 Segmentation fault(11)로 종료됨, /etc/apache2에 coredump가 남았을 가능성 있음/code>

• code>[core:notice] [pid 1:tid 1] AH00051: 자식 pid 58 종료 신호 Segmentation fault (11), /etc/apache2에 코어덤프 가능성 있음/code>

• code>[core:notice] [pid 1:tid 1] AH00051: 자식 pid 61이(가) 신호 Segmentation fault (11)로 종료되었습니다. /etc/apache2에 코어 덤프가 있을 수 있습니다/code>

crash_evidence.log(2026년 10월 23일)에서 조판된 발췌. 다수의 워커 종료는 메모리 안전성 실패를 뒷받침하지만, 크래시만으로는 RCE를 입증할 수 없습니다.

• code>HTTP/1.1 200 OK/code>, 바이너리 데이터는 생략했습니다.

• code>서버: Apache/2.4.69 (Debian)/code>

• code>X-Powered-By: PHP/8.4.26/code>

• code>Set-Cookie: PHPSESSID=[바이너리 데이터 생략됨]/code>

• 인코딩된 쿠키 길이: 2,330,754바이트.

• URL 디코딩된 값: 819,200바이트.

측정값은 leak_attempt.resp에서 직접 계산되었습니다. 바이너리 값은 유출된 프로세스 내용을 재현하지 않기 위해 의도적으로 생략되었습니다.

별첨 C — 체결 증명

code>uid=33(www-data) gid=33(www-data) groups=33(www-data)/code>

rce_proof_8426.txt의 정확한 내용은 제공된 그대로입니다. 이는 보고된 실행 결과를 뒷받침하지만 전체 명령/세션 기록은 아닙니다.

Evidence summary card: four worker exits, an 819,200-byte URL-decoded session cookie, and uid=33 execution context

별첨 D — 세션 수명 주기 수정

• code>static inline void php_rinit_session_globals(void)/code>

• code>@@ -121,6 +120,7 @@ static inline void php_rinit_session_globals(void)/code>

• code>* 요청 시작 시, RINIT 이전에, 사용자가 없을 때 세션을 다시 인코딩합니다/code>

• code>/* RINIT 전에 실행됩니다: 사용자 코드는 호출될 수 없습니다. php_session_unserialize_init() 참조 *//code>

• code>/* RINIT 이전에 실행되므로 이 항목들을 미리 정리해야 합니다 *//code>

• code>php_rinit_session_globals();/code>

session.c.diff에서 선택된 소스 diff 줄입니다. 이 변경은 일반 RINIT보다 더 이른 시점에 세션 전역 상태를 명시적으로 재설정합니다.

3. 증거가 중요한 이유

메모리 노출은 프로세스 충돌과 익스플로잇 체인 사이의 연결고리를 제공한다. 내장된 바이너리 데이터가 포함된 비정상적인 크기의 세션 값은 런타임이 유효하지 않은 메모리를 Zend 문자열로 해석하는 것과 일치한다. 연구 보고서는 누출된 윈도에서 코드 및 힙 주소를 추출하는 방법을 추가로 설명한다. 증거 번들은 원시 응답을 포함하지만 복구된 모든 주소를 입증하는 독립 실행형 스크립트는 포함하지 않는다.

RCE 아티팩트는 {{1}}www-data{{/1}} 보안 컨텍스트를 보여줍니다. 이는 루트 액세스, 프로덕션 환경의 침해 또는 임의의 PHP 배포 환경에 대한 완전한 이식성을 입증하지 않습니다. 단일 워커 실험실 구성은 요청 시퀀싱과 워커 선호도가 메커니즘에 영향을 미치기 때문에 중요합니다.

4. 단순한 증상이 아닌 근본적인 라이프사이클에 대한 수정

제공된 PHP 패치 커밋 01a40e89fbfc("Avoid state corruption via bailout")의 소스 diff는 조기 세션 전역 초기화, 할당자 OOM 처리 변경, 더 광범위한 재설정/정리 로직을 보여 줍니다. 이러한 변경은 중단된 요청 후 네이티브 상태가 유효하지 않은 상태로 남는 것을 방지하는 것을 목표로 합니다. 쿠키 인코딩 경로만 수정하는 것만으로는 그 자체로 이 메모리 소유권 보장을 복원하지 못합니다.

연구 보고서에 따르면 PHP 8.4.27을 대상으로 한 시도에서는 네 차례의 시행에서 비정상 쿠키, 크래시 또는 RCE 증명이 나오지 않았다. 실제 패치된 버전의 트랜스크립트는 이 번들에 없으므로, 그 비교는 독립적으로 검사 가능한 증거 자료가 아니라 연구자의 관찰로 보고된다.

5. 방어 행동

• 즉시. 영향을 받는 지원 대상 PHP 라인을 보안 문제가 수정된 릴리스로 업그레이드하고, 공급업체 권고를 통해 정확한 패키지 상태를 확인하십시오.

• 노출 감소. 사용하지 않는 경우 멀티파트 입력을 제한하고 다음을 비활성화하는 것을 고려하십시오: code>session.upload_progress/code>; 이는 패치를 대체하지 않습니다.

• 탐지.요청 초기화 중 크래시, 예기치 않은 500 오류, 크기가 너무 큰 code>Set-Cookie/code> 응답 헤더를 검토하세요.

• 보증. 프로덕션을 대표하는 작업자 풀로 재테스트하고 이전 세션 상태가 요청 간에 지속될 수 없음을 검증하세요.

6. OrcaCyber 연구 방법론

가치 있는 연구 과제는 개별적인 안전하지 않은 작업을 찾아내는 것만이 아니라, 요청 파싱, 할당자 동작, 영속적인 네이티브 전역 변수, 직렬화, 그리고 종료 전반에 걸쳐 완전한 불변식 위반을 추적하는 것입니다. 이 조사에서 OrcaCyber Zero와 OrcaCyber Ultra는 PoC를 만드는 데 사용되었으며, 이는 연구팀이 밝힌 바입니다. 공개 아티팩트 세트는 기술적 재현을 뒷받침하지만, 모델별 실행 추적을 제공하거나 자율적인 취약점 발견을 입증하지는 않습니다.

증거 사다리: 소스 가설 → 도달 가능한 트리거 → 런타임 실패 → 정보 노출 → 실행 증명 → 수정 버전 회귀 검증. 이 순서는 취약점 설명이나 단순 크래시 결과보다 더 강한 신뢰를 형성합니다. 또한 소스 파일이나 원시 실행 로그가 없을 때 불확실성을 명확히 보고하도록 장려합니다.

7. 범위 및 제한 사항

이 간행물은 승인된 격리형 Docker 랩을 설명합니다. 이 익스플로잇은 이전에 공개된 PHP2Shell 연구를 기반으로 하며, 제공된 보고서에 로컬 적응 내용이 문서화되어 있습니다. 번들에는 스크립트, diff, 응답 바이트, 로그, 증명 출력이 포함되지만 전체 업스트림 익스플로잇 체크아웃, 원본 스크린샷, 완전한 원시 패치 회귀 기록은 포함되지 않습니다. 실제 피해자나 고객이 침해되었다고 주장하지 않습니다.

소스 및 아티팩트

주요: 제공된 php2shell-report-bundle.tar.gz(REPORT.md; report-CVE-2026-109618.md; report-CVE-2026-109619.md; crash_evidence.log; leak_attempt.resp; rce_proof_8426.txt; PHP 소스 diff). 공개 맥락: PHP 보안 권고 GHSA-w8hw-w9fx-j79w 및 GHSA-6wmf-4rv5-p3rp; PHP 보안 릴리스 공지. 공개 익스플로잇 출처: 9bie/php2shell-bypass-aslr-exp. 연구 저장소: orcacyber-php2shell-research.

The public orcacyber-php2shell-research GitHub repository README on the OrcaCyber PHP2Shell defender research artifacts and its defensive scripts

핵심 요점: 요청 하나가 실패했고, 포인터는 살아남았으며, 다음 요청은 그것을 신뢰했다. 이 취약점을 이해하는 데 어려운 부분은 관찰 가능한 증거로 그 연결을 입증하는 것이다.

이 글에서 비교한 모델1

이 글에서 자동 인식