Unraveling HTTP Parameter Pollution

By Júlia Rocha 6 min read

Understanding HTTP Parameter Pollution (HPP) helps us see how this vulnerability affects many modern applications. Learn how to prevent it.

Did you know it can hide an attack?

Today, we dive into this not-so-well-known vulnerability, explain why it happens, share a real-world experience, and offer mitigation strategies.

What is HTTP Parameter Pollution, or HPP?

HTTP Parameter Pollution is a vulnerability that occurs when an application receives query parameters in a crafted way that makes it process the request unexpectedly, leading to disastrous outcomes.

But here’s the catch: most applications crash or spew error messages when they encounter unexpected inputs, but in applications vulnerable to HPP, malicious inputs are processed as though nothing unusual happened. But the results cause the damage.

No strict standards govern HTTP parameters or how to interpret multiple inputs.

RFC 3986, Uniform Resource Identifier (URI): Generic Syntax, mentions that a query is just a URI component used to fetch or point to a resource, whatever is located at that URI.

When an application’s intended query format is altered, developers might not have considered it, resulting in unexpected outputs. All of this depends on how HTTP requests and related query parameters are parsed, which developers may overlook and unintentionally leave their products vulnerable to HPP.

Understanding HPP

Let’s look at a real-life HPP bug we encountered in a popular app. It used OTP-based authentication: a user supplied an email, and an OTP was sent to that email.

Upon entering the OTP on the next screen, the login was granted.

Say the login endpoint was “/API/v0/send-otp”. The following is the POST request body for generating the OTP:

{
	"email" : "abc@xyz.com",
	"gen_otp" : "yes",
	"key" : "some_base64_string"
}

Pretty straightforward:

  • The backend logic receives the email.
  • The backend sends a corresponding OTP to that email.
  • The submission screen is shown.

From an attacker’s perspective, there are multiple ways to fiddle with this request in hopes of generating unusual outputs. We tried several crafted requests, but none of these worked. Two of which are shown below:

{
	"email" : "abc@xyz.com",
	"gen_otp" : "yes",
	"key" : "some_base64_string"
	"email" : "qwe@xyz.com",
	"gen_otp" : "yes",
	"key" : "some_base64_string",
} // attempt to make the application parse two emails in a single request
{
	"email" : "abc@xyz.comnqwe@abc.com",
	"gen_otp" : "yes",
	"key" : "some_base64_string"
} // delimiting the email parameters with `n` so that backend sends same OTP to both.

We were almost ready to give up, but we tried one last delimiter (and felt dumb for not thinking of it sooner). Instead of n, we used a, (a comma). The request looked like this:

{
	"email" : "abc@xyz.com,qwe@abc.com",
	"gen_otp" : "yes",
	"key" : "some_base64_string"
}

Lo and behold, we received the same OTP on two different emails! Taking over accounts after this was trivial, since there was no 2FA.

We didn’t have access to the application source code, but we can guess that the comma somehow made the application think there were two emails to send the OTP to.

I hope this example clarifies how HPP works.

Categories of HTPP Parameter Pollution

Now HPP can be split into categories:

  • Server-side HPP

    When the attacker directly targets the application and sends a request with polluted parameters, it is called server-side HPP. Our real-life example in the previous section was server-side HPP.

  • Client-side HPP

    While server-side HPP directly attacks the vulnerable application, client-side HPP also involves a middle stage: the victim user.

    An attacker crafts a malicious URL that leads to a webpage with polluted parameters.

    Let’s take an example.

    Assume that in a banking application, the password reset page is at /resetPass?username=test.

    When you visit it, the webpage shows your username and a hyperlink to send a reset code to your email.

    This hyperlink is in the form: <a href = “/sendCode?username=test&[email protected]“> Send reset code to your email </a>.

    Since the application is vulnerable to HPP, the attacker forges the following URL: /resetPass?username=test&[email protected].

    This leads to a page with an injected link: <a href=”/sendCode?username=test&[email protected]&[email protected]“>Send reset code to your email</a>.

    When the user clicks this hyperlink, the backend application will treat [email protected] as the valid email and send the reset code to the attacker.

    This is just one scenario to clarify client-side HPP (where victim interaction is involved).

Types of HTPP Parameter Pollution

There are three types of client-side HPP:

  1. Reflected HPP

    The example we gave above is a case of reflected HPP, where the victim needs to interact with the malicious URL to reach the webpage with polluted hyperlinks.

    Reflected attacks fail if the adversary can’t make the victim click these URLs. Attackers usually achieve this through phishing or social engineering. The victim believes they are interacting with legitimate resources and clicks them.

  2. Stored HPP

    This happens when malicious input is stored in an application database (unlike reflected HPP, where things happen on the fly).

    If an attacker can set [email protected] in the web application, then whenever /resetPass is accessed, the reset-password links will always include the attacker’s email in the polluted parameter, and anyone using the password reset functionality would be exploited.

    The attacker wouldn’t have to resort to phishing, social engineering, or other less reliable routes.

  3. DOM-based HPP

    When the polluted parameters are injected into JavaScript (instead of a request response), it is known as DOM-based HPP.

    It is called DOM-based because, when a webpage loads, the browser creates a DOM object for the relevant JavaScript.

    If the injection point is inside the DOM object, the webpage creates the DOM object with the malicious payload, and the resulting JavaScript becomes polluted.

Mitigation Strategies

Now we know what HTTP parameter pollution is and the varieties that exist.

HPP is the problem. What is the solution?

Developers need to know how the platform they work on parses multiple HTTP parameters. That’s the key to handling unexpected/polluted parameters.

The image below lists a few of the popular web servers with their parsing functionalities:

Popular Webservers and how they parse parameters

Even if developers use custom APIs, they should be aware of unexpected parameter combinations.

Further, to prevent client-side HPP (reflected, stored, or DOM-based), proper URL encoding and input sanitization are necessary to ensure uniform parsing on the backend.

Remember, treat every input as malicious!

Conclusion

Although HTTP parameter pollution is less popular than other, more significant vulnerabilities like XSS and CSRF, that doesn’t diminish the negative impact a successful HPP exploitation can have.

HPP is the first step of an attack that can lead to sensitive information exposure (data leakage), account takeovers, and many other devastating effects on an organization.

This article introduces this bug class, which is relatively lesser-known, and we encourage further research for a deeper understanding.