Jump to content
xenonxsc

XSS Polyglots - The Context Contest

Recommended Posts

That title is in fact a tongue twister, but it helps to describe this post, which will take a look at XSS polyglot payloads. For the newcomers: dafuq is a polyglot? Now since you’re done with reading the first paragraph of that article, let's dive into XSS vectors with the motto "One payload to rule them all."

This post will assume the reader knows the basics of what XSS is, and how to find & exploit it. If you don’t, OWASP’s XSS article is a great resource to brush up on. Knowledge about HTML contexts is also required to be able to follow the article.

 

 

Contexts, Contexts, Contexts!

When testing for XSS, the injected payload can land into many different places or HTML contexts. Depending on the landing space, different escape characters are required to make an XSS successful. There are XSS attack vectors that try to reach as many contexts as possible in order to be most effective. Those types of attack vectors are called XSS polyglots.

There are quite a few contexts with different scenarios that each require a special payload:

 

 

HTML element:     

 

 <p> injection </p>

 

HTML attribute value:

 

<p class="injection"></p>

 

HTML attribute name:

 

<p injection="myid123"></p>

 

HTML comment:       

 

<!-- injection -->

 

 

Style element or attribute:

 

<style>injection</style>

 

<p style="injection"></p>

 

 

Javascript:       

 

<script> var a = "injection"; </script>

 

<script> var b = ‘injection’; </script>

 

URL:

 

<a href="injection">click</a>

 

 

This list is not complete as there are more configurations possible such as:

 

  • injection landing in html attributes with single quotes or no quotes
  • injection landing in Javascript context without quotes
  • nested contexts (URL in Javascript, URL in CSS) etc.

 

However, for most real world scenarios, covering the first list will be enough to find most XSS while staying within the character limits that are often present. 

 

XSS Polyglot Anatomy

 

Let's start with the simplest example where the XSS payload lands in the normal HTML Element context:   

 

 <p>            

 Attack_String_Here

</p>

 

Most XSS payloads will work in this example and succeed (for example <img src=x onerror=alert(1)>)… nothing special.

 

Looking at another example, this time the XSS payloads land on a different context, namely the HTML Attributecontext:

 

<img src="Attack_String_Here">

For this context, a simple payload like the following would result in XSS: x" onerror="alert(1)

Both above payloads are specific to the context they’re attacking, and will not work in the other. This is due to the context nature, which requires specific characters to escape it.

In order to be time effective and test both contexts at once, a polyglot XSS payload is required:

"><script>alert(1)</script><p id="

 The payload hits both contexts due to its clever configuration. For the HTML Element context, the <script>alert(1)</script> will result in Javascript execution while the characters in the beginning and end are ignored (Browser rendering engines have lenient HTML parsers and try to parse as best as they can. Read more here.) When the payload lands in the HTML Attribute context, the characters to the beginning (">) will close the first tag, and allow the <script>alert(1)</script> to continue with Javascript execution. An additional <p id=" is used to well-form the remaining html, however that is not needed due to lax browser parsing as mentioned before. 

Another polyglot payload that would work for the contexts above is the following:

<iframe onload=alert(1)>" onerror="alert(1);

This payload still works fine in the HTML Element context (provided angle brackets aren’t encoded), but also works in the HTML Attribute context with a scenario where angle brackets are correctly encoded (but quotes aren’t!). The output would look like this:

<img src="&lt;iframe onload=alert(1)&gt;" onerror="alert(2);">

 As you can see, the angle brackets were properly encoded but the quotes weren’t. This allowed the polyglot payload to escape from the image source attribute, and add another (onerror) attribute to allow for javascript execution. This is a good example of how useful XSS polyglot payloads are, as they allow testers to catch all of these edge cases at once.

We will now build a more complex XSS polyglot payload that will hit all of the contexts mentioned earlier. As a reminder, those contexts were: URL, HTML Element, HTML Attribute name, HTML Attribute value, HTML Comment, Style and Javascript contexts.

Because of the unique requirement of the URL context to have the payload start with "javascript:" we will meet that requirement first. So we have the following as payload:

 javascript:alert(1);

Next we will make the payload work in the HTML Attribute context, by adding the following: 

javascript:alert(1);" onclick=alert(1);//

 We added a quote, which is needed to escape the HTML Attribute context, added a space and javascript execution. You would think that this would work well (and it does), however the same payload works for the HTML Attribute context when injecting in the attribute name. As crazy as it may seem, the browser will actually parse the following and execute javascript:

<p alert(1);" onclick=alert(1);//="myid123">click_me</p>

 While the payload above breaks a multitude of HTML rules, the browser will look past all of that and try to render what it assumes the developer wanted to achieve.

It’s even more curious making the existing payload work for the Javascript context. All you need to do is to add a semicolon after the first quote: 

javascript:alert(1);"; onclick=alert(1);//

 With the added semicolon, this payload will now work in the Javascript context with an injection such as:

var abc="Injection_here";

While the javascript rendering engine is stricter than the HTML one, it will execute the payload above if injected into a quoted javascript variable simply because it will result in valid javascript code.

Back to our payload and the remaining contexts... We will add the same structure used in HTML Attribute and Javascript context for single quotes. After that’s added, the payload looks like this:

javascript:alert(1);"; onclick=alert(1);// '; onclick=alert(1);//

 This takes care of instances when HTML Attributes or Javascript strings use single quotes. With that, we already have 5 contexts that our polyglot XSS Payload can trigger.

Additional quick wins for HTML Comment, Style, and the normal HTML Element contexts can be achieved by simply closing the initial part of the context and executing javascript: 

javascript:alert(1);"; onclick=alert(1);// '; onclick=alert(1);//--></style><button onclick=alert(1);>

As you can see, a --> was added to close the HTML Comment context, and a </style> was added to close the style tag. Then a simple XSS payload for triggering javascript gives us another three for a total of eight contexts triggered.

A final addition would be a </script> tag before the button tag for cases when the XSS payloads land within a javascript string and single/double quotes are properly encoded. This works because the HTML parser will see the closing </script> tag and end the script part of the html, regardless of whether or not that closing script tag was within a javascript string (HTML doesn’t even speak javascript!). So our final payload looks like the following:

javascript:alert(1);"; onclick=alert(1);// '; onclick=alert(1);//--></style></script><button onclick=alert(1);>

You can test the payload by pasting it into any of the contexts and clicking on the "click_me"s in the following jsfiddle: https://jsfiddle.net/w5ev7bzn/. (Replace "injection" with the payload.) 

 

XSS Polyglots in the wild

There are many good examples of XSS Polyglot payloads by known bug hunters. Take Mathias Karlsson’s example from his excellent talk at Hackpra that can hit 7 contexts and stays very well under most length limits imposed on xss-able fields.

" onclick=alert(1)//<button ' onclick=alert(1)//> */ alert(1)//

 

Jason Haddix presented XSS Polyglot payloads as part of his How to Shot Web talk at Defcon in 2015, and later the Bug Hunter’s Methodology. He also maintains the SecLists project, which has a decent list of XSS Polyglots.

 Of course XSS Polyglots wouldn’t be cool if there wasn’t a challenge around who’s got the best one. At http://polyglot.innerht.ml/ you can find a challenge for payloads that can hit up to 16 different contexts. The scoreboard shows the winning payloads based on number of contexts hit and length of the payload.

 I hope you found this useful. To comment on this post or offer your own polyglot tips and resources, continue the conversation on our forum.

Happy Hunting!

 

 

Source : Bugcrowd

  • Upvote 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...