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 );
}