PHP: Exploitation with $_REQUEST while validating $_GET

While penetration testing and code reviewing a customer’s web-application I came across an interesting bug I’m going to describe in this article.

The application in question supports third party plugins which often follow their own coding-conventions.
During code review, a Cross-Site scripting vulnerability was detected in one of those plugins:

echo "<a href='index.php?plugin=".$_REQUEST['plugin']."'>Link text</a>";

Here the parameter plugin is susceptible to a Cross-site scripting vulnerability because a user supplied parameter is directly reflected back to the user’s browser. While this vulnerability is relatively obvious, actual exploitation is more complicated. This is because the core application itself validates the supplied parameter plugin before the vulnerable code within the plugin is executed. Hence, the Cross-site scripting vulnerability cannot be exploited directly. The validation code in the core application is as follows:

$plugin = $_GET['plugin'];
if(!in_array($plugin, $active_plugins)) {
                die("Plugin is not supported");

The validation code checks if the value of the parameter plugin is defined in an array of active plugin names. Looking closer one can see that only the GET parameter is validated. If instead submitting a POST request containing the parameter plugin or even setting a cookie with that name this is not validated by the above code.

Furthermore, the vulnerable code inside the plugin uses $_REQUEST to fetch the parameter plugin. The $_REQUEST variable contains all the parameters passed in the request via GET ($_GET), POST ($_POST) and cookies ($_COOKIE). The order of merging GET/POST/COOKIE (also the default) is determined by PHP and may be configured in its configuration. This means if there is a POST parameter named plugin, $_REQUEST['plugin'] will return the POST parameter value instead of the GET value.

Knowing this, exploitation of the vulnerability becomes possible and is demonstrated with the following steps:

First fetch a regular request that executes the vulnerable code using a tool like Burp Suite which will be used as an example. Send it to the Repeater tab to enable making changes to the request. If this request is a GET request, change it to a POST request. The context menu item “change request method” of Burp makes this very easy. After this, ensure that there is still a GET parameter plugin (e.g. /?plugin=thumbnails) that will pass the validation code in the core application. After this, add an additional POST parameter named plugin containing the exploit-code:

The complete request then looks as follows:

Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 58


This request passes the validation as a valid GET parameter is used while also exploiting the Cross-Site scripting because of the POST parameter is referenced in the vulnerable code inside the plugin.

Finding this vulnerability is fairly difficult without manually reviewing the source code, because most web application security scanners will not try to send a GET request as a POST request using the same parameter again. It is more likely a manual penetration test would find this, but without any indication for this behavior most penetration testers will not spend valuable time on this test case for each and every request.

Note: The above code is not the same as in the tested system. This is due to confidentiality and to simplify the example.

Author: SecMyth

After learning to inspect security from all perspectives from Prof. Pfitzmann at the University, I am now working as Penetration tester and IT Security Consultant since 2009. I have seen many many different applications, architectures and technologies since then. Web Applications, Web Services, Oracle, MySQL, Linux, SAP R3 are my focus technologies, while my activities are widely spreaded: manual penetration tests, static code analysis, code reviews, consulting, project management

Leave a Reply

Your email address will not be published. Required fields are marked *

four + 6 =