Server-side parameter pollution
Server-side parameter pollution
Some systems contain internal APIs that aren't directly accessible from the internet. Server-side parameter pollution occurs when a website embeds user input in a server-side request to an internal API without adequate encoding. This means that an attacker may be able to manipulate or inject parameters, which may enable them to, for example:
Override existing parameters.
Modify the application behavior.
Access unauthorized data.
You can test any user input for any kind of parameter pollution. For example, query parameters, form fields, headers, and URL path parameters may all be vulnerable.
Testing for server-side parameter pollution in the query string
To test for server-side parameter pollution in the query string, place query syntax characters like #
, &
, and =
in your input and observe how the application responds.
Consider a vulnerable application that enables you to search for other users based on their username. When you search for a user, your browser makes the following request:
GET /userSearch?name=peter&back=/home
To retrieve user information, the server queries an internal API with the following request:
GET /users/search?name=peter&publicProfile=true
Truncating query strings
You can use a URL-encoded #
character to attempt to truncate the server-side request. To help you interpret the response, you could also add a string after the #
character.
For example, you could modify the query string to the following:
GET /userSearch?name=peter%23foo&back=/home
The front-end will try to access the following URL:
GET /users/search?name=peter#foo&publicProfile=true
Injecting invalid parameters
You can use an URL-encoded &
character to attempt to add a second parameter to the server-side request.
For example, you could modify the query string to the following:
GET /userSearch?name=peter%26foo=xyz&back=/home
This results in the following server-side request to the internal API:
GET /users/search?name=peter&foo=xyz&publicProfile=true
If you're able to modify the query string, you can then attempt to add a second valid parameter to the server-side request.
For example, if you've identified the email
parameter, you could add it to the query string as follows:
GET /userSearch?name=peter%26email=foo&back=/home
This results in the following server-side request to the internal API:
GET /users/search?name=peter&email=foo&publicProfile=true
Overriding existing parameters
To confirm whether the application is vulnerable to server-side parameter pollution, you could try to override the original parameter. Do this by injecting a second parameter with the same name.
For example, you could modify the query string to the following:
GET /userSearch?name=peter%26name=carlos&back=/home
This results in the following server-side request to the internal API:
GET /users/search?name=peter&name=carlos&publicProfile=true
The internal API interprets two name
parameters. The impact of this depends on how the application processes the second parameter. This varies across different web technologies. For example:
PHP parses the last parameter only. This would result in a user search for
carlos
.ASP.NET combines both parameters. This would result in a user search for
peter,carlos
, which might result in anInvalid username
error message.Node.js / express parses the first parameter only. This would result in a user search for
peter
, giving an unchanged result.
If you're able to override the original parameter, you may be able to conduct an exploit. For example, you could add name=administrator
to the request. This may enable you to log in as the administrator user.
Labs 🔬
Last updated