A Case of Polluting HTTP Parameters
Recently a friend came to me and told me about a scenario which he had used to deploy his web application. He had built his application using PHP on Apache. There was a front-end server directly accessible to the internet and a back-end server only accessible to the front-end server. The PHP application deployed on the front end server included PHP files kept on the back-end server and showed it on the browser. The included PHP files were hard coded in the code of the PHP application running on the front-end server and this front end application took a GET parameter as input.
Now, this scenario kind of caught my interest. I recently read about HTTP parameter pollution and I thought this attack might work in this case. So I began digging and experimenting. And I came up with a demonstration which shows how will this attack work when someone is using a setup similar to the setup described above to bypass a hard coded value in the code. I know this is not recon stuff ,but still its interesting.. 😉
We will see 4 PHP codes here :-
1.) hpp.php – The main application deployed on the front-end server, which remotely includes a PHP code (cms.php) kept on the back-end server.
2.) cms.php – A PHP code kept on the back-end server which receives an input from hpp.php in the “function” parameter and includes a PHP code (set to normaluser.php) meant for a normal user locally.
3.) normaluser.php – A PHP code kept on the back-end server meant for a normal user and included by cms.php .The ping command was set in this case to show that the normal user can only use the ping service.
4.) adminuser.php – A PHP code meant for an admin user. This code can run any OS command directly to show that this code really is for the admin 😉 .
Now, we can see that the normaluser.php and adminuser.php codes are vulnerable to OS command injection and XSS flaws, but I wont discuss them here because they are not the subject we want to talk about right now. This scenario was tested on the same server (my local server), cause I didn’t had two servers to make a front-end and a back-end server 🙂 . I used the session variables here to make myself feel like the back-end web applications are really not accessible directly, but only through the front-end web application 😉 . The random variable (which is not really random) was chosen just to demonstrate that the “auth” session variable will get set only when cms.php is called by hpp.php and not directly.
Lets talk a little about HPP. HPP i.e. HTTP parameter pollution is an injection attack which consists of injecting query string delimiters and overriding or adding HTTP GET or POST parameters. This attack consists of client side HPP and server side HPP. We are discussing server side HPP here.
Different platforms take multiple HTTP GET, POST or COOKIE parameters with the same name in different ways. In our case, which is PHP on apache, if we provide multiple parameters with the same name to a web application, the application will consider the last parameter with the same name and use that instead of all the other parameters with the same name occurring before it.
Lets move on with the testing part. Opening hpp.php shows us the following:-
Entering an IP and hitting enter shows us the following:-
We can see that the normaluser.php script got included and executed. Lets see what input this application takes using a web proxy:-
We can see that the application takes a POST parameter named “b” which contains the IP we entered.
Now, looking at the hpp.php code and referring back to the discussion we just had about different platforms processing multiple parameters with same names in different ways, if we can make hpp.php take another “function” parameter containing a different PHP application other than normaluser.php, then hpp.php will remotely include cms.php with two “function” parameters in the URL and the one that comes at the last position will be processed by cms.php.
So, how do we go about it.
Open hpp.php and again input an IP and hit enter while intercepting the request using a web proxy as shown:-
Inject a “%26function%3dadminuser.php” after the IP as shown:-
to get the following output:-
All righty!! So what just happened.. It can be clearly seen that this time adminuser.php is included. Basically, “%26function%3dadminuser.php” is equivalent to “&function=adminuser.php”; the only difference being that the query string delimiters have been URL encloded. When we inject “%26function%3dadminuser.php” in the POST parameter, hpp.php URL decodes this value to “&function=adminuser.php” and the final string in the require_once function i.e. $d becomes “http://localhost:8080/cms.php?function=normaluser.php&cmd=127.0.0.1&function=adminuser.php&rand=12345” which consists of two “function” parameters. According to the behavior of PHP, when cms.php is remotely included with these two parameters with the same name (function), cms.php will process the last parameter, and since the value of the last function parameter is “adminuser.php”, that file is included and executed.
We know that adminuser.php takes an OS command directly, so all we have to do is replace the IP with an OS command to get the required results as shown:-
So we were able to override a hard coded value in the code with one of our own value to get a file of our choice executed. cooooll!!
In this attack, we already took out all the information from the code needed to perform the attack. And it can be seen, it would have been much difficult to guess exactly what we have to inject in the parameter to get the work done.
I actually never tried this attack on my friend’s web application, but it gave me a hint as in how this attack can be so devastating.
Any suggestions and feedbacks are most welcome.
"eSecForte is the authorized distributor/reseller of Metasploit Penetration Testing tool Metasploit Professional and Nexpose in India (Rapid7 Products), Bangladesh, Srilanka"