Command Execution via WordPress Pingback and Brotli
Attack Techniques & Methods2026-11-06, 14:02
Researchers demonstrated how WordPress’s built-in pingback feature can be used to reach a vulnerability CVE-2026-111497 in the native Brotli decoder. The flaw is not in WordPress core but in the Google Brotli library, which libcurl uses to process compressed HTTP responses. As a result, a single unauthenticated request to
xmlrpc.php can trigger a vulnerability in the native decoder, potentially crashing the PHP process or, under specific conditions, leading to command execution.What’s the issue?
When processing a pingback, WordPress sends an outbound request to the specified URL. If the remote server responds with the
Content-Encoding: br header, libcurl invokes the native Brotli decoder. In vulnerable library versions (1.0.3–1.2.0), a specially crafted compressed stream triggers an out-of-bounds write (CWE-787).How the exploit works
• Delivery. The attacker sends
pingback.ping to xmlrpc.php, specifying a URL pointing to their own server. No authentication is required; the site only needs to have at least one post that accepts pingbacks.
• Request. WordPress calls wp_safe_remote_get(), which uses libcurl to fetch the specified URL. The attacker’s server responds with a crafted Brotli-compressed stream.
• Decoding. libcurl passes the stream to the native Brotli decoder. The vulnerable version writes beyond the allocated memory.
• Impact. In general, this chain can cause the PHP process to crash, resulting in a denial of service. Under laboratory conditions, on a specific build (WordPress 7.1.3, Debian 13.7, PHP 8.3.36), the researchers achieved command execution. However, this capability depends heavily on memory layout and the versions of all components involved, so it is not universal.It is also worth noting that the payload is not sent in the request to WordPress. It is delivered in the HTTP response from the attacker’s server, so tools that inspect incoming requests do not see the actual exploit payload. In the demonstrated exploit chain, WordPress makes two outbound GET requests to the attacker-controlled URL within a single PHP request. The second request is a retry triggered by the content-decoding error, with Brotli decoding disabled. Its response contains an attacker-controlled header name that WordPress processes using PHP’s
strtolower() function. Due to the memory corruption caused by the first response, this call can be redirected to PHP’s system() function, resulting in command execution.