XSS in Vue.js

While working at Sqreen, I put some time to look into Front-end Security issues. Of course, as you can guess, it has been widely documented on the web. As a VueJS enthusiast, I was happy to look into Cross-site scripting (XSS) possibilities with Vue and concerns that developers should have. This article’s main goal is to help you know a bit more about XSS in general and Vue.JS in particular. We will try to create some XSS attacks, and see what tools we have to prevent them.

What is an XSS?

An XSS attack injects malicious code into someone else’s web page.

Here is a quick example of an XSS performed with JQuery.

In the example above, you have a normal use case of displaying a username. What if you display a malicious username? Uncomment the second username and see what happens!

As you can see, we can inject into the username malicious code that allows us to retrieve cookies from anyone seeing the concerned page.

Is Injecting HTML possible in newer frameworks?

Injecting HTML is a feature available to any front end framework and used is by websites when part of the website HTML is generated by the server.

Here is the documentation for how some current frameworks perform HTML injection:

Let’s focus on Vue.js

Can we perform an XSS attack?

Let’s try to  perform a basic XSS attack on the v-html directive:

<div id="app" >
Welcome :
 <span v-html="attack">
 </span>
</div >
new Vue({
 el: '#app',
 data: {
 attack: 'john doe',
 }
});

Following along in this playground, we will try to inject different strings in the v-html directive and see if we can retrieve cookies.

new Vue({
 el: '#app',
 data: {
  attack: '<script > alert(document.cookie)</script >',
 }
});

Nothing happens. The browser prevent executing injected script tags after initial page load.

Let’s try to inject in events from HTML tags.

new Vue({
 el: '#app',
 data: {
 attack: '<a onmouseover=alert(document.cookie)>click me!</a>',
 }
});

As you can see we are now using the <span style="font-weight: 400;">onmouseover event to retrieve the cookies. This is the result.

Interesting, we just found our first possible XSS with Vue. Let’s dig a bit more:

new Vue({
 el: '#app',
 data: {
 attack: '<img src="validUrl" onload=alert(document.cookie)>',
 }
});
new Vue({
 el: '#app',
 data: {
 attack: '<img src="notValidUrl" onerror=alert(document.cookie)>',
 }
});

They work too!

Then I simply need to avoid v-html

It’s not that simple. Chances are you use a UI library to help you handle UI interaction/display. Can a UI library use v-html inside a component without you knowing it? Let’s see if we can find some interesting UI libraries using v-html.

Let’s check Vux.

XSS in Github Vue.js23 hits, now we can try to search for possible XSS attacks in Vue.js. In fact, we can perform some injections while not directly using v-html. Now let’s try to attack it. Basically, we want to be able to perform malicious XSS when using the UI components.

Here is an example repository and demo of possible injections with UI libraries. This demo shows how to perform a simple XSS using commonly used UI components such as cards and modal. Other libraries such as vuetify offer great UI components while totally avoiding v-html.

In Vux, have you noticed that the prop header of the Card Component is XSS-able ? Using external UI library without checking the rendering methods used is risking yourself to a XSS.

How can I avoid XSS attacks?

Try to use as much as possible interpolated expressions {{}}, they are stringified and cannot be executed by the browser.

Do you need to inject HTML?

Be absolutely sure the data coming from your server is sanitized (node example).

Do you use an external UI library?

Be sure of how the data passed through props is rendered. Is it using v-html? document.write ?

How to protect your app against XSS without pain?

At Sqreen, we believe developers should be able to focus on developing their applications without having to constantly fear for security. We also believe developers deserve security tools that look like the other tools they use every day.

Sqreen will block attacks in your application (including NoSQL injections, SQL injections or XSS) without you having to take any action or to change your code. The best thing is that Sqreen takes literally 30 seconds to install in any app.

Conclusion

Don’t worry, injecting HTML is not inherently bad and is very useful in other ways. However, it’s the developer responsibility to be aware of this possibility and make sure XSS cannot happen. Whenever you are using a library responsible for displaying data, be aware of how it is displayed.