Mercator Configuration SSRF Chained to Internal Redis RCE (CVE-2026-49345)
by hadhub · 2026-07-05
- Severity
- Critical
- CVE
- CVE-2026-49345
- Category
- web
- Affected product
- Mercator (sourcentis/mercator vulnerability-management web app), ConfigurationController::testProvider
- Affected versions
- Not specified in source
- Disclosed
- 2026-07-05
- Patch status
- unpatched
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-07 |
| Author / Researcher | hadhub |
| CVE / Advisory | CVE-2026-49345 |
| Category | web |
| Severity | Critical |
| CVSS Score | Not specified in source |
| Status | PoC |
| Tags | ssrf, redis, rce, gopher, webshell, internal-network-pivot, php, mercator |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | Mercator (sourcentis/mercator vulnerability-management web app), ConfigurationController::testProvider |
| Versions Affected | Not specified in source |
| Language / Platform | PHP web application, exploited via Python 3 requests |
| Authentication Required | Yes — any account holding the configure permission (granted to the default User role) |
| Network Access Required | Yes |
Summary
This repository contains two Python PoCs that abuse an unvalidated provider URL parameter in Mercator’s ConfigurationController::testProvider endpoint, which the server fetches with libcurl. ssrf2scan.py uses the telnet:// scheme to turn the SSRF into a blind TCP port scanner (timing-based open/closed oracle) against hosts reachable from the Mercator server. ssrf2rce.py uses the gopher:// scheme to smuggle raw RESP-encoded Redis protocol commands to an internal Redis instance, using CONFIG SET dir/CONFIG SET dbfilename/SET/SAVE to write a PHP webshell directly into the Mercator webroot, achieving remote code execution. A companion reset-lab.sh restores the lab (deletes the webshell, flushes Redis) between exploit runs.
Vulnerability Details
Root Cause
The provider parameter passed to ConfigurationController::testProvider is fetched server-side via curl without scheme or destination restriction. Because libcurl supports non-HTTP schemes such as telnet:// and gopher://, an authenticated low-privilege user (any account with the configure permission, granted by default to the User role) can make the server originate arbitrary raw TCP connections and protocol payloads to hosts/ports on the internal network.
Attack Vector
- Attacker authenticates to Mercator as a low-privilege account that has the
configurepermission. - Attacker submits a crafted
providervalue (e.g.telnet://target:port#) to the config “test provider” endpoint; the trailing#truncates the appended/api/dbInfosuffix as a URL fragment. - For port scanning (
ssrf2scan.py), the response time to thetelnet://probe (fast TCP RST vs. 10-second curl timeout) is used as an open/closed oracle across a target host and port list. - For RCE (
ssrf2rce.py), the attacker encodes Redis RESP protocol commands and wraps them in agopher://redis-host:6379/_<encoded-bytes>#URL; Mercator’s curl call delivers the raw bytes to Redis, which parses and executes them. - The attacker pipelines
CONFIG SET dir <webroot>,CONFIG SET dbfilename <name>.php,SET <key> <php-webshell-body>, andSAVE, causing Redis to write a PHP webshell file into the web-server-served directory. - The attacker requests the dropped file (e.g.
/poc.php?c=id) to execute arbitrary OS commands via the web server.
Impact
Full server compromise: SSRF enables internal network reconnaissance (port scanning of otherwise unreachable hosts) and, when an internal Redis instance is reachable without authentication/protected-mode, remote code execution via a dropped webshell.
Environment / Lab Setup
Target: Mercator web application (PHP) + colocated internal Redis instance (redis:latest, protected-mode disabled) reachable from the Mercator container's network
Attacker: Python 3 (requests) issuing authenticated HTTP requests to Mercator's "test provider" configuration endpoint
Proof of Concept
PoC Script
See
ssrf2scan.py,ssrf2rce.py, andreset-lab.shin this folder.
| |
ssrf2scan.py logs in, confirms the account has the configure permission, and reports OPEN/CLOSED for each requested host:port based on response timing. ssrf2rce.py logs in, RESP-encodes the given Redis command pipeline, wraps it as a gopher:// URL, and submits it through the same configuration endpoint, causing Redis to persist a PHP webshell into the Mercator webroot that can then be invoked directly over HTTP.
Detection & Indicators of Compromise
Signs of compromise:
- Configuration endpoint logs showing
providervalues usingtelnet://orgopher://schemes - Redis
CONFIG GET dir/dbfilenamereflecting a value under the web server’s document root - New PHP files in the webroot accepting a command parameter (e.g.
?c=) and executingsystem()/exec()
Remediation
| Action | Detail |
|---|---|
| Primary fix | Restrict testProvider’s outbound requests to an allow-listed scheme (http/https) and destination; validate/resolve the host and reject internal/private IP ranges (SSRF filtering) |
| Interim mitigation | Enable Redis protected-mode and require authentication (requirepass), bind Redis to localhost only, and enforce network segmentation so the Mercator host cannot reach internal management services it doesn’t need |
References
Notes
Mirrored from https://github.com/hadhub/CVE-2026-49345-Mercator-SSRF on 2026-07-05.
| |