First of all, let me make it clear that this article is not about XSS in Bootstrap itself (the very popular libraries originally from Twitter to fancify your website), it’s about XSS as a result of using Bootstrap in an insecure fashion. It’s based on a real penetration test – the site in question wasn’t vulnerable but it was immediately clear how things could have gone wrong. I thought it would be an interesting XSS article, being both DOM-based and making use of a big-name library like Bootstrap.
To illustrate the point I’ve written a vulnerable page. What, it’s vulnerable to XSS? Yes. Do you know what you’re doing? I hope so. Here’s the brief:
- Try to create a DOM-based XSS condition that runs
<script>alert(1)</script>.
- Don’t bother trying to inject any other kind of script – it won’t work and the result may throw you. If it does work, I run a white-hat vulnerability programme – sorry, no bounty, just my thanks and a credit on the page
- Getting the alert box to pop up shouldn’t be hard at all – what’s more interesting is to spot the Bootstrap implementation error. When you view the source, note the comment on line 22 to ignore the indented lines (23-26 and 28) – that’s the code that should be protecting the page from arbitrary XSS.
- The page is here.
Discussion
I’m assuming you’ve had a look at the page above. The Bootstrap JavaScript plugin allows you to use “tooltips” (information shown on mouseover) that write into the DOM. Because of this, you can create more advanced tooltips by writing HTML code into the DOM. This is when the alarm bells should sound. In my page the email address, when invalid, is coloured red. But because the email address is under user control and can be pre-populated in the query string, there’s a DOM-based XSS condition, e.g. http://exploresecurity.com/wp-content/uploads/custom/bootstrap-dom-xss.html?email=<script>alert(1)</script>, which will fire when the victim hovers over the email address.
To get HTML inserted by a tooltip you need to set the attribute data-html="true"
. The default is false, which means the content is encoded before insertion into the page. But if you want to add some markup, such as changing the colour, you’ll need to set it to true. In this case if any part of the content is user-supplied, it needs to be handled safely.
The XSS risk is clearly stated in the documentation but that doesn’t mean mistakes won’t be made. In the test that prompted this article, the data-html
attribute was set to true everywhere, even when the content being displayed was straight text. Of course, no harm in that case – but in a few places the content was dynamic. Sadly (for me) this content was not under user control.
Conclusion
Developers and penetration testers may assume that popular and big-name libraries like Bootstrap (especially the latest version) are safe but this article shows that it depends on how they’re being used. As a penetration tester, watch out for client-side code that modifies the page and research the (potentially) dangerous options in popular third-party libraries (look out for that data-html
attribute!). As a developer, it’s all about (as ever) handling user-supplied content safely – and this article emphasises that you can’t always rely on third-party libraries to do everything for you. With great power comes great responsibility.
alert(“this vulnerable?”);