Exploiting XSS in hidden inputs and meta tags


In this post we are going to show how you can (ab)use the new HTML popup functionality in Chrome to exploit XSS in meta tags and hidden inputs.

It all started when I noticed the new popover behaviour with Chrome on Twitter. We all know about annoying modal dialogs that nag you to subscribe to a newsletter - now you can create these popups without JavaScript! Oh the joy. It's going to be a newsletter apocalypse.

Anyway, I noticed this functionality and wondered what JavaScript events these pop ups introduce. Sure enough, you can use the events ontoggle and onbeforetoggle and these apply to the popover target - this is an element that has an attribute of popover. This attribute makes the element invisible until you toggle the element by using the attribute popovertarget, with an element such as a button.

This is useful for bypassing a WAF, since you can use the onbeforetoggle event which is not likely to be blocked by an attribute-based blocklist:

A code sample with a button using the popovertarget attribute and a dialog with the onbeforetoggle event

In the example above you can see the button element targets the custom 'xss' element using the popovertarget. When the button is clicked, the onbeforetoggle event will be fired.

XSS in hidden inputs

I posted this on Twitter as I always do and Mario Heiderich pointed out that it even works with hidden inputs. This is significant because normally if you have XSS inside a hidden input, it may be hard to exploit because most events won't work. You can use access keys but this requires heavy user interaction. However, using popovers allows you to use new events in hidden inputs:

A code sample showing popovers being applied to hidden inputs

Mario mentioned that it would require two injection points; one sanitised harmless HTML injection, and one inside a hidden input. But that got me thinking - maybe you only need one. I fired up a HTML page and tested what would happen if two elements had the same id. Imagine a website contains code using the popovertarget attribute, and has an XSS vulnerability inside a hidden input:

A code sample showing duplicate id attributes to demonstrate that the first attribute is used

Our injected code would execute the onbeforetoggle event inside the hidden input because it occurs first. This means you only need one injection point, provided it occurs before any existing pop up. Popovers will then allow you to use the ontoggle and onbeforetoggle events to be fired in hidden inputs with a click. So it's very useful if you have XSS inside a hidden input, and you have an existing popover element on the page.

XSS in meta tags

Now it's already getting pretty interesting but wait, there's more! Mathias Karlsson chimed in with a great point; this technique enables you to use the onbeforetoggle event on a meta element, provided there's an existing popover element. This is significant because, like hidden inputs, meta elements are heavily restricted.

In the example below you have an injection inside a meta element that uses a popover attribute and a duplicate id (newsletter) which targets the existing popup on the page:

A code sample showing that the onbeforetoggle event will be fired in a meta element

When the user tries to subscribe to the newsletter they will instead fire the onbeforetoggle event on the hidden input.


As always, we've updated our XSS cheat sheet with these new vectors. If you like XSS filter bypasses you might enjoy our Web Security Academy labs for exploiting XSS in a link tag , and this one that filters most HTML tags .

Enjoy!

Back to all articles

Related Research