Parameter Pollution - Zero Day

Summary :

HTTP Parameter Pollution (HPP) means to pollute the HTTP parameters of a web application for achieving a specific malicious task. It refers to manipulating how a website treats parameters it receives during HTTP requests. It changes a website’s behaviour from its intended one. HTTP
parameter pollution is a simple kind of attack but it is an effective one.

When you pollute any parameter the code runs only on the server-side which is invisible to use, but we can see the results on our screen. The process in between is a black box.

The term Query String is commonly used to refer to the part between the “?” and the end of the URI as defined in the RFC 3986, it is a series of field-
value pairs. Pairs are separated by “&” or “;” and the usage of semicolon is a W3C recommendation in order to avoid escaping. RFC 2396 defines two classes of characters:

  1. Unreserved: a-z, A-Z, 0–9 and _ . ! ~ * ‘ ( )
  2. Reserved: ; / ? : @ & = + $ ,

Description :

The Zero day described in this write up has been assigned the CVE-2021-43793. Me and my friend ethicalbughunter were hunting on a program hosted in bugcrowd and that program was using Discourse. In a brief, Discourse is an open source Internet forum and mailing list management software application founded in 2013 by Jeff Atwood, Robin Ward, and Sam Saffron.

There is a functionality to create polls (like voting system) in Discourse, so we built a poll with 4 different options and voted for option 1 and intercepted the request where we noticed that the parameter value of the selected option had a long string but it was possible to obtain the long string on the client side. Another thing that grabbed our attention was while intercepting the response, we noticed that the option parameter was an array. Then we voted for option B and intercepted the request and copied the value and saved it in a notepad, then we voted for option C and intercepted the request and appended the parameter using the copied value of option B (e.g optionC=value&optionB=value) and forwarded the request by doing intercept request to response. We saw that an array was created which had both the values of optionC and optionB and we were able to vote for both the options.

Just to double check we reloaded the page and we also copied the URL and opened it in another browser and still both the options had equal votes by one person.

Although the bug was on Discourse which is a third party from our bugcrowd’s program’s perspective, we decided to report it on the main program of Discourse on HackerOne.

Note : The vulnerability got resolved 4 months ago.

What is an array ?

In simple language, an array is a datatype that is used to store multiple values of same type together so that you do not need to specify different datatypes and variables for different values.

For eg. optionsA[]=value1 will be stored in an array as optionsB[value1].

Considering parameter pollution the scenario, would look like options[]=value1&options[]=value2 is considered as a whole array (if vulnerable) and changes will be applied to both at the same time like options[value1,value2].

Anatomy of Parameter Pollution :

The manipulation of the value of each parameter depends on how each web technology is parsing these parameters. Some web technologies parse the first or the last occurrence of the parameter, some concatenate all the inputs and others will create an array of parameters.

Table of web technology parsing different values

What is the difference between occurrences ?

First of all, here we are talking about the parsing results which means how they are treated by the back-end technology.

  1. All occurrences of specific parameter :

This means that if we parse the same name parameters like q=hello&q=”><svg/onload=alert(1)> the check will be performed on both the parameters because they have the same name. In All occurrences, the barrier is if the back-end logic is configured to allow a specific parameter only 1 time then appending another parameter (q=hello&q=”><svg/onload=alert(1)>) of same name will give you an error.

For e.g.,

POST /details HTTP/1.1
Host: site.target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0

id=100&id=101

Response :

HTTP/1.1 403
server: nginx
content-type: application/json
cache-control: no-cache, private

HTTP Parameter Pollution Request :

POST /details HTTP/1.1
Host: site.target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0

id=100,101

HTTP Parameter Pollution Response :

HTTP/1.1 200 OK
server: nginx
content-type: application/json
cache-control: no-cache, private

{

“email”:”yourmail@gmail.com”,“phoneNumber”:+91-9999999999,”email”:”victim@gmail.com”,”phoneNumber”:+91-8888888888

}

As shown in Table of web technology parsing different values above when all the occurrences are checked where you can use the same name parameter only once, then you can simply add another value using comma(,) in the same parameter.

2. First occurrence :

First occurrence means a web application performs input validation on the first parameter which makes it vulnerable to second parameter which should be of same name.

For e.g.,

Request :

GET /search?q=”><svg/onload=alert(1)> HTTP/1.1
Host: site.target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0

Response :

HTTP/1.1 403 Forbidden
server: nginx
content-type: application/json
cache-control: no-cache, private

HTTP Parameter Pollution Request :

GET /search?q=Hello&q=”><svg/onload=alert(1)> HTTP/1.1
Host: site.target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0

HTTP Parameter Pollution Response :

HTTP/1.1 200 OK
server: nginx
content-type: application/json
cache-control: no-cache, private

In the above mentioned polluted request only the first occurrence (q=Hello) is checked and the last occurrence (q=”><svg/onload=alert(1)>) is not sanitized which means it will trigger XSS.

3. Last occurrence :

Last occurrence means a web application performs input validation on the last parameter which makes it vulnerable to first parameter which should be of same name.

For e.g.,

Request :

GET /search?q=”><svg/onload=alert(1)> HTTP/1.1
Host: site.target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0

Response :

HTTP/1.1 403 Forbidden
server: nginx
content-type: application/json
cache-control: no-cache, private

HTTP Parameter Pollution Request :

GET /search?q=”><svg/onload=alert(1)>&q=Hello HTTP/1.1
Host: site.target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0

HTTP Parameter Pollution Response :

HTTP/1.1 200 OK
server: nginx
content-type: application/json
cache-control: no-cache, private

In the above mentioned polluted request only the last occurrence (q=Hello) is checked and the first occurrence (q=”><svg/onload=alert(1)>) is not sanitized which means it will trigger XSS.

4. Becomes an array :

Becomes an array means whatever the input is sent from the client side the server parsed it into an array and displays it. Which means the parameter which you are polluting has an array as datatype, which is also the most vulnerable.

Request :

POST /details HTTP/1.1
Host: site.target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0

id=100

Response :

HTTP/1.1 200 OK
server: nginx
content-type: application/json
cache-control: no-cache, private

{

“email”:[”yourmail@gmail.com”],“phoneNumber”:[+91-9999999999]

}

HTTP Parameter Pollution Request :

POST /details HTTP/1.1
Host: site.target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0

id=100&id=101

HTTP Parameter Pollution Response :

HTTP/1.1 200 OK
server: nginx
content-type: application/json
cache-control: no-cache, private

{

“email”:[”yourmail@gmail.com”,”victim@gmail.com”],“phoneNumber”:[+91-9999999999,+91-8888888888]

}

How did we find this vulnerability ?

  1. We logged into discourse website and clicked on +New Topic button on try.discourse.org
try.discourse.org

2. Then we found an option of Build Poll

Build Poll Option

3. We created a poll with four values

Creating Poll
Creating Poll - 4 Options
Poll Created

4. We voted for option 1 and option 2 for copying the values of both the parameters by intercepting the request

Option 1 - Request
Option 2 - Request
Parameter values copied and pasted in notepad

5. Then we clicked on option 4 and intercepted the request to perform parameter pollution attack

Option 4 - Request

6. After clicking option 4 we intercepted the request using burp and appended the parameters with values of option 1 and 2

Appended

7. Then we decided to check the response so we used the option Do intercept > response to this request and forwarded the request

Checking Response

8. We found that it became and array and all the values of the same parameter (option 1, option 2 and option 4) were processed by an array without any error

Response - Becomes an array
Response - Becomes an array

9. After turning intercept off, we found the below mentioned result

Voted

10. For double check I reloaded the page and also opened the URL in another browser but still the votes were intact

Only 1 Voter
Another Browser - Chrome

Impact :

Any user can choose more than one option for voting by manipulation the request using parameter pollution.

Mitigation :

Make sure to perform an extensive and proper input validation. All user-supplied data, which is reflected in the HTML source code of the HTTP response, should be encoded according to the context in which they are reflected.

Affected Discourse Versions :

Discourse 2.8.0.beta8 and below

Note : It should have a poll feature enabled.

CVE URLs :

  1. https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-43793
  2. https://nvd.nist.gov/vuln/detail/CVE-2021-43793
  3. https://www.cvedetails.com/cve/CVE-2021-43793/
  4. https://github.com/discourse/discourse/security/advisories/GHSA-jq7h-44vc-h6qx (Credited)

Collaboration was done with :

ethicalbughuntr

--

--

--

|Penetration Tester| |Hack The Box| |Digital Forensics| |Malware Analysis|

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Cloud Custodian Policies for CIS AWS Foundations Benchmark (Part-4)

What is GDPR? Is it Applicable in Indonesia?

What is Social Engineering?

Honeypot Using Cowrie and Adbhoney

Indicator of Compromise (IoC) vs. Indicator of Attack (IoA)

Special Surprise from RACA 🚀

XSS in pastebin.com and reddit.com via unsanitized Markdown Output

A Journey Through Security Compliance

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Jerry Shah (Jerry)

Jerry Shah (Jerry)

|Penetration Tester| |Hack The Box| |Digital Forensics| |Malware Analysis|

More from Medium

Writeup: OS command injection, simple case @ PortSwigger Academy

XSS - The LocalStorage Robbery

Stored XSS and HTML Injection in United Nations Web Application

XSS Vulnerability Part 2