Super Global Confusion
Summary
In the context of WordPress, and PHP more generally super global confusion refers to the unintended consequence of merging of global variables. For WordPress this occurs because $_REQUEST
is created by combining data from $_GET
, $_POST
. An attacker can exploit this behavior to manipulate input data by sending conflicting parameters through GET and POST requests, potentially bypassing security checks and altering application behavior unexpectedly.
Proof of Concept
This can be demonstrated with a simple proof-of-concept script below, where we print out the a
variable from the GET
, POST
and REQUEST
super globals:
<?php
include 'wp-load.php';
echo "GET: " . $_GET['a'] . "<br>\n";
echo "POST: " . $_POST['a'] . "<br>\n";
echo "REQUEST ". $_REQUEST['a']. "<br>\n";
If we make a request using curl to send the a
variable via both GET and POST methods we get the following output:
❯ curl 'http://wordpress.local:1337/test.php?a=hello' -X POST --data 'a=friend'
GET: hello<br>
POST: friend<br>
REQUEST friend<br>
We can see that the POST variable takes priority over the GET variable. This can allow us to perform a super global confusion attack when an application uses a variable from REQUEST where they are relying upon sanitization or protection that is applied to the GET variable.
Source
For those interested this occurs in WordPress is inside the function that adds ‘magic quotes’ to the user-supplied variables when array_merge
is called with the GET and POST superglobals:
function wp_magic_quotes() {
// Escape with wpdb.
$_GET = add_magic_quotes( $_GET );
$_POST = add_magic_quotes( $_POST );
$_COOKIE = add_magic_quotes( $_COOKIE );
$_SERVER = add_magic_quotes( $_SERVER );
// Force REQUEST to be GET + POST.
$_REQUEST = array_merge( $_GET, $_POST );
}