Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
SessionReaper-CVE-2025-54236 — PoC Magento Session Reaper - CVE-2025-54236 | Kitploit
Tools/GitHubGitHub/alexb616/sessionreaper-cve-2025-54236
Vulnerability AnalysisCode AnalysisExploitationWeb Application ExploitationPenetration TestingRed TeamingPayload Development
GitHubalexb616/sessionreaper-cve-2025-54236

SessionReaper-CVE-2025-54236

PoC Magento Session Reaper - CVE-2025-54236

View Repository
1122 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

SessionReaper — CVE-2025-54236

Unified PoC for CVE-2025-54236 ("SessionReaper"), a critical unauthenticated RCE in Magento 2 / Adobe Commerce via nested deserialization in the REST API.

  • CVSS: 9.1 (Critical)
  • Root cause: Improper Input Validation (CWE-20) in ServiceInputProcessor; the exploit primitive is insecure deserialization (CWE-502)
  • Original researcher: Daniel "Blaklis" Le Gall (responsible disclosure via HackerOne)
  • Name coined by: Sansec
  • Fixed in: Adobe APSB25-88 (emergency patch, 2025-09-09)

For authorized security testing only. Use exclusively against systems you own or have explicit written permission to test.


What it does

The tool chains three stages that are common to every vector, plus a trigger:

  1. Gadget generation — phpggc -se -a Guzzle/FW1 <remote_path> <payload.php> builds a serialized object that writes payload.php to <remote_path> when deserialized.
  2. Fake session upload — POST /customer/address_file/upload stores the serialized blob as . Magento disperses uploaded address files by the first characters of the filename, so it lands at (hence the in ).
sess_<SESSID>
media/customer_address/s/e/sess_<SESSID>
s/e/
--save-path
  • save_path redirect — a nested REST payload constructs Session\Config and, via setSavePath() → setOption() → ini_set('session.save_path', ...) (a process-global side effect), points PHP's session handler at the uploaded blob.
  • Trigger — a request carrying Cookie: PHPSESSID=<SESSID> forces session_start() to read and unserialize() the poisoned file, firing the gadget and writing the payload.

  • Vectors

    All three vectors reach the same sink (context → urlBuilder → session → sessionConfig → savePath). They differ only in the endpoint, HTTP verb and Magento module involved — useful when a WAF or a disabled module blocks one endpoint but not another.

    MethodEndpointVerbEntry point into the chain
    order/rest/<store>/V1/guest-carts/abc/orderPUTpaymentMethod → paymentData → Payment\Helper\Data
    checkmo/rest/<store>/V1/guest-carts/abc/set-payment-informationPOSTpaymentMethod → paymentData → Payment\Helper\Data
    address/rest/<store>/V1/guest-carts/abc/estimate-shipping-methodsPOSTaddress → addressConfig → addressHelper → Customer\Helper\Address

    No real cart is required for any vector. ServiceInputProcessor deserializes the method parameters during input resolution — before the service invokes any cart lookup — so a dummy cartId of abc reaches the sink on all three. The subsequent "cart not found" error (404/500) is expected and confirms the deserialization side effect already fired.

    A --sku flag is available if you want the tool to create a real guest cart and add a product before triggering (verified via GraphQL). This is optional and not needed for exploitation — it exists only for environments where you prefer a fully realistic checkout flow. Omit it and the tool uses the dummy abc cart.


    Preconditions

    • File-based session storage (var/session/). Redis- and database-backed sessions are not affected by this specific RCE chain. This is not remotely enumerable, so it must be attempted blind.
    • /customer/address_file/upload reachable without authentication.
    • Target unpatched (pre-APSB25-88 / pre-2.4.x hotfix).

    Requirements

    • Python 3.8+ with requests
    • phpggc — auto-detected in PATH, common install locations, or pulled as the ambionics/phpggc Docker image as a fallback
    • payload.php in the same directory as the script (must start with <?php)
    root@kitploit:~
    pip install requests
    git clone https://github.com/ambionics/phpggc /opt/phpggc   # or: docker pull ambionics/phpggc
    

    Usage

    root@kitploit:~
    # 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
    

    Options

    FlagDefaultDescription
    --host(required)Target base URL
    --method(required)address | checkmo | order
    --storedefaultStore code for the trigger request (and cart, if --sku is used)
    --api-storedefaultStore code in the deserialization endpoint URL (all | es | default | custom)
    --sku(none)Optional. If set, creates a real guest cart with this SKU. Not required.
    --payload-inpayload.phpPHP payload to write on the target
    --payload-out/var/www/html/pub/errors/404.phpRemote write path (must be a web-executable location — see note below)
    --save-pathmedia/customer_address/s/e/savePath injected into the gadget chain
    --phpggc(auto)Explicit path to the phpggc binary
    --proxyhttp://127.0.0.1:8081HTTP proxy (e.g. Burp)
    --no-proxyoffDisable the proxy
    --username / --password(none)Optional customer credentials for a Bearer token

    Store scopes

    The tool uses two independent store codes:

    • --api-store — the scope in the deserialization request URL (/rest/<api-store>/V1/guest-carts/...), where ServiceInputProcessor runs.
    • --store — the scope for the trigger request (GET /<store>/) and, if --sku is used, for the cart requests.

    Store view codes are admin-defined; do not assume es/fr. Enumerate the active store views first — a request against a non-existent scope simply fails.


    Payload target — why pub/errors/404.php

    Magento's default Nginx config only passes seven PHP files to fastcgi_backend:

    root@kitploit:~
    index.php, get.php, static.php,
    errors/report.php, errors/404.php, errors/503.php, health_check.php
    

    Any other .php (including anything dropped into pub/media/) is denied and will never execute. So the payload must overwrite one of these seven whitelisted files rather than drop a new one. pub/errors/404.php is the default because Magento renders it internally on any missing page, so it fires often on a live store.

    OPSEC: overwriting 404.php outright is loud (it runs on every 404). In a real engagement, back-door a whitelisted file subtly instead of clobbering it.


    Notes

    • The tool operates as a guest by default. --username/--password are only needed if you want a Bearer token for a specific setup.
    • Expect a 404/500 on the deserialization request — that is normal and does not mean failure.
    • Cleanup: the temporary /tmp/sess_<SESSID> file is removed on exit.

    References

    • Adobe Advisory APSB25-88
    • Sansec — SessionReaper disclosure
    • Searchlight Cyber (Assetnote) — original RCE PoC
    • Pentest-Tools.com — exploit development write-up
    • NVD — CVE-2025-54236

    Disclaimer

    Provided for authorized security research and testing only. The author assumes no liability for misuse. Do not run against systems without explicit permission.

    Download Tool