HTTP parameter pollution (HPP) is the process of manipulating how a website treats the parameters it receives during HTTP requests. The vulnerability occurs when an attacker injects extra parameters into a request and the target website trusts them, leading to unexpected behavior. HPP bugs can happen on the server side or on the client side. On the client side, which is usually your browser, you can see the
effect of your tests. In many cases, HPP vulnerabilities depend on how server-side code uses values passed as parameters, which are controlled by an attacker. For this reason, finding these vulnerabilities might require more experimentation than other types of bugs. In this chapter, we’ll begin by exploring the differences between server-side HPP and client-side HPP in general. Then I’ll use three examples involving popular social media channels to illustrate how to use HPP to inject parameters on target websites. Specifically, you’ll learn the differences between server- and client-side HPP, how to test for this
vulnerability type, and where developers often make mistakes. As you’ll see, finding HPP vulnerabilities requires experimentation and persistence but can be worth the effort.
In server-side HPP, you send the servers unexpected information in an attempt to make the server-side code return unexpected results. When you make a request to a website, the site’s servers process the request and return a response In some cases, the servers don’t just return a web page but also run some code based on information they receive from the URL that is sent. This code runs only on the servers, so it’s essentially invisible to you: you can see the information you send and the results you get back, but the code in between isn’t available. Therefore, you can only infer what’s happening. Because you can’t see how the server’s code functions, server-side HPP depends on you identifying potentially vulnerable parameters and experimenting with them. Let’s look at an example: a server-side HPP could happen
if your bank-initiated transfers through its website by accepting URL parameters that were processed on its servers. Imagine that you could transfer money by entering values in the three URL parameters from, to, and amount. Each parameter specifies the account number to transfer money from, the account number to transfer to, and the amount to transfer, in that order. A URL with these parameters that transfers $5,000
from account number 12345 to account number 67890 might
look like this:
It’s possible the bank could assume that it will receive only one from parameter. But what happens if you submit two, as in the following URL:
This URL is initially structured in the same way as the first example but appends an extra from parameter that specifies another sending account, ABCDEF. In this situation, an attacker would send the extra parameter in the hopes that the application would validate the transfer using the first from
parameter but withdraw the money using the second one. So, an attacker might be able to execute a transfer from an account they don’t own if the bank trusted the last from parameter it received. Instead of transferring $5,000 from account 12345 to 67890, the server-side code would use the second parameter
and send money from account ABCDEF to 67890. When a server receives multiple parameters with the same name, it can respond in a variety of ways. For example, PHP and Apache use the last occurrence, Apache Tomcat uses the first occurrence, ASP and IIS use all occurrences, and so on. Two researchers, Luca Carettoni and Stefano di Paolo, provided a detailed presentation on the many differences
between server technologies at the AppSec EU 09 conference: this information is now available on the OWASP website at OWASP Plan – Strawman
As a result, there is no single guaranteed process for handling multiple parameter submissions with the same name and finding HPP vulnerabilities takes some experimentation to confirm how the site you’re testing works.
The bank example uses parameters that are obvious. But sometimes HPP vulnerabilities occur as a result of hidden server-side behavior from code that isn’t directly visible. For example, let’s say your bank decides to revise the way it processes transfers and changes its backend code to not include a from parameter in the URL. This time, the bank will take two parameters, one for the account to transfer to and the other for the amount to transfer. The account to transfer fromwill be set by the server, which is invisible to you. An example link might look like this:
Normally, the server-side code would be a mystery to us, but for the sake of this example, we know that the bank’s (overtly terrible and redundant) server-side Ruby code looks
user.account = 12345
➋ params << user.account
➌ transfer_money(params) #user.account (12345) becomes params
➍ to = params
➎ amount = params
➏ from = params
This code creates two functions, prepare_transfer and transfer_money. The prepare_transfer function takes an array called params ➊, which contains the to and amount parameters from the URL. The array would be [67890,5000], where the array values are sandwiched between brackets and each value is separated
by a comma. The first line of the function
➋ adds the user account information that was defined earlier in the code to the end of the array. We end up with the array [67890,5000,12345] in
params, and then params is passed to transfer_money
➌. Notice that unlike parameters, arrays don’t have names associated with their values, so the code depends on the array always containing each value in order: the account to transfer to is
first, the amount to transfer is next, and the account to transfer from follows the other two values. In transfer_money, the order of the values becomes evident as the function assigns each array
value to a variable. Because array locations are numbered starting from 0, params accesses the value at the first location in the array, which is 67890 in this case, and assigns it to the variable to
➍. The other values are also assigned to variables at lines ➎ and ➏. Then the variable names are passed to the transfer function, not shown in this code snippet, which takes the values and transfers the money.
Ideally, the URL parameters would always be formatted in the way the code expects. However, an attacker could change the outcome of this logic by passing in a from value to params, as with the following URL:
In this case, the from parameter is also included in the params array passed to the prepare_transfer function; therefore, the array’s values would be [67890,5000,ABCDEF], and adding the user account at ➋ would result in [67890,5000,ABCDEF,12345]. As a result, in the transfer_money function called in prepare_transfer, the from variable would take the third parameter, expecting the user.account value 12345, but would actually reference the attacker-passed value ABCDEF ➍.
Client-side HPP vulnerabilities allow attackers to inject extra parameters into a URL to create effects on a user’s end (client side is a common way of referring to actions that happen on your computer, often via the browser, and not on the site’s servers). Luca Carettoni and Stefano di Paola included an example of this behavior in their presentation using the theoretical URL http://host/page.php?par=123%26action=edit and the following server-side code: