During an engagement, I found a potential XSS vulnerability on a page. There is an HTML form that is submitted to this page (POST method) and sent parameters are reflected (without encoding) in the response.

If I use a proxy tool (e.g. Burp Suite) and change my request POST body from:



param1=val1" onmouseover="alert(1337)&param2=val2&param3=val3

Then my payload is executed.

I'm trying to create a PoC for this issue by creating a custom HTML page with a hidden form pointing at the vulnerable page that will automatically submit, however, I'm running into the following issues:

  • By default, the values are automatically URL encoded by the browser. This breaks the payload and the XSS doesn't work.
  • I can prevent URL-encoding by changing the form encoding to text/plain but the application does not accept that encoding and returns an empty page.
  • It has to be a POST request with the data in the body, if I use a GET request the application ignores GET parameters.

So, is there a way to prevent the browser from URL-encoding the form values, while keeping the content-type to application/x-www-form-urlencoded?

  • "prevent the browser from URL-encoding the form values, while keeping the content-type to application/x-www-form-urlencoded" - Given that x-www-form-urlencoded clearly says urlencoded you basically ask for browser bugs Jul 6, 2021 at 15:06
  • One of the key mantras of server security is, never trust client submitted data. As you demonstrated yourself, the client can do anything. It's up to the server to escape threat data. Jul 6, 2021 at 15:37
  • @user10216038: I think that's exactly the point the OP was making by pointing out the possible XSS attack. The problem described in the question is not if something is vulnerable but how to exploit a detected vulnerability using a normal browser - because reflected XSS without something useful to reflect to (i.e. a browser) is not useful. Jul 6, 2021 at 15:52
  • Exactly @SteffenUllrich ! I know there is an XSS flaw and the client need to fix it, but it's sometimes hard to make that clear for clients if you don't have a way to exploit the flaw :(
    – Scaum
    Jul 12, 2021 at 8:02
  • @Scaum If you don't have a working PoC, then it's not a vulnerability.
    – user163495
    Aug 6, 2021 at 12:02

3 Answers 3


You didn't wrote which kind of HTTP server you use. If you are using Apache (or you can set up a proxy between the clients and your server with Apache), you can use ModSecurity (mod_security Apache module), and CRS ruleset. CRS has many other advantages, but of course, you can tune these features.

  • ... this is an attempt at XSS, which is an attack. OP certainly doesn't have the ability to put their own proxy (or any other server) between the victim's browser and the vulnerable server!
    – CBHacking
    Jul 7, 2021 at 8:02
  • ah, sorry, I misunderstood him. Thanks for clarification.
    – airween
    Jul 7, 2021 at 11:01

This isn't exactly what you ask for, but: there is a third encoding you can use to POST data from a form. Unlike text/plain, it is a "real" method using structured key+value pairs and intended for actual use, not just testing. Unlike application/x-www-form-urlencoded, it doesn't modify the form's data at all (just wraps formatting around it). This method is multipart/form-data, usually used for file uploads but usable for any type of data.

Now, of course, it's totally possible that won't work. Most servers know how to parse multipart, but don't do it by default except for file uploads. Still, it's worth a shot. The form is constructed exactly the same way, you just use a difference enctype.

One other option, mentioned for completeness: when you submit a POST request using JavaScript (via XHR or Fetch), the body is sent exactly as specified with no extra encoding applied. However, doing this doesn't navigate the page to the response, so it's useless for reflected XSS. However, if there's a vulnerable stored value anywhere, you can use this for stored XSS just fine (assuming it doesn't separately have CSRF protection).

  • Thanks for your input ! Sadly I had tried the multipart/form-data encoding as well, but it's snot working in this case as the server is not expecting this encoding.
    – Scaum
    Jul 12, 2021 at 8:03

So you are trying to perform a CSRF (Cross-Site Request Forgery) attack against a user to trigger XSS (Cross-Site Scripting). From a different page, you're creating a POST-request to the other page with the XSS-payload. Is that correct?

Like Steffen Ullrich points out, any form that uses application/x-www-form-urlencoded will URL-encode the value, so it won't work. You could try to get clever with JavaScript. For example, the following makes my browser send the POST-request that you're looking for:

    var xhr = new XMLHttpRequest();

    xhr.open('POST', 'https://security.stackexchange.com/derp', true);
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    xhr.withCredentials = true;

    xhr.send('param1=val1" onmouseover="alert(1337)');

However, you'll run into issues like the SameSite attribute on cookies and CORS headers. Hope this helps a bit, but from what you are describing the chances of exploitation seem slim. Never hurts to try though, would be cool if you find a way. Also, I'd say it's still an issue, even though it's not a vulnerability. The developer should properly encode the output to prevent the vulnerable pattern creating vulnerabilities elsewhere.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .