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 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 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 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 at 8:02
  • @Scaum If you don't have a working PoC, then it's not a vulnerability.
    – MechMK1
    Aug 6 at 12:02

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 at 8:02
  • ah, sorry, I misunderstood him. Thanks for clarification.
    – airween
    Jul 7 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 at 8:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.