On preventing XSS attack of vue project

1. For the data requested from the interface, try to use {}} loading instead of V-HTML
Curly braces in vue interpret the data as plain text. Usually, if you want to interpret it as HTML code, you need to use v-html. This instruction is equivalent to innerHTML. Like innerHTML, script tags will not be output directly, but img, iframe and other tags can also be output.

The description of v-html in vue document is as follows:

2. Escape the customer information loaded with V-HTML and INNERHTML
If there are HTML fragments in the display content, it must be loaded with v-html or innerHTML, for example:

<div v-html="`<span>${message}</span>`"></div>

The message inside is the information entered by the customer. If it is a malicious dom fragment at this time, it will certainly cause XSS attack. At this time, we can translate "<", ">" into "<", ">". Then enter it into the page.

You can use the escape method in lodash to translate customer information. As follows:

import _escape from 'lodash/escape'
Vue.prototype.$escape = _escape

Insert a global method into the vue and use this method for the data to be translated:

<div v-html="`<span>${$escape(message)}</span>`"></div>

3. Use CSP in META on the entry page
Add a meta tag to the head of the entry file

<meta http-equiv="Content-Security-Policy" content="script-src 'self';style-src 'self'">

The CSP settings above indicate that script resources and style resources can only load resources under the current domain name. In this way, external malicious script loading and execution can be avoided.

If the page has, for example, the following tags, these CDN resources cannot be loaded.

<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/1.0.0/css/font-awesome.css" rel="stylesheet">
<script src='https://cdn.bootcdn.net/ajax/libs/angular.js/0.10.0/angular-ie-compat.js'></script>

Digression: I don't recommend using a third-party CDN. First, it won't reduce the volume of page loading resources. Second, the stability of the third-party CDN can't be guaranteed. Sometimes the server of the third-party CDN will hang up, resulting in the failure to load the required resources.

The following CSP configurations are generally used:

<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline'">

Setting explanation:

Script SRC: only the resources under the face-to-face domain name server are loaded, and eval is allowed to execute scripts. Because webpack uses a lot of Eval for script injection in development mode, and the commonly used soap map in development is soap module Eval source map. If script SRC is set to 'self', it will prevent the use of eval.
Style SRC: only the resources under the face-to-face domain name server are loaded, and inline resources are allowed. Sometimes, in both development and production environments, CSS content may be packaged into JS files through webpack packaging. When loading a page, the JS script will insert style tags into the page to supplement the cascading style model. If style SRC is set to 'self', it will prevent the insertion and execution of style inline styles.
4. Selectively filter XSS tags for special scenarios
In the project, XSS security vulnerabilities are easy to appear, such as chat module and rich text module.

Sometimes you want to edit html content in a rich text editor. But I'm worried about XSS malicious script injection. At this point, you can use an XSS tool. website: https://github.com/leizongmin/js-xss . For more detailed usage, please see the attached website. Here is a brief description of the usage.

First download xss

npm i xss -S

(1) Introduce resources into the page and generate XSS filters to filter the content

var xss = require("xss") 
const option={} //Custom settings
const myxss = new xss.FilterXSS(option);
const line='<script type="text/javascript">alert(1);</script>'
var html = myxss.process(line);
console.log(html); //Output: & lt; script type="text/javascript"> alert(1);& lt;/ script>

(2) If I want to not filter the oneror attribute of the img tag, or not filter the style tag. By setting whiteList, you can selectively retain specific tags and their properties, such as:

const option={
    whiteList:{
        img:['src','onerror'] //img tags retain SRC and oneror attributes
        style:['type'] //The style tag is not in the while list attribute by default. Now add it
    }
}
const myxss = new xss.FilterXSS(option);
letline='<img src="./123.png" onerror="alert(1);" alt="123">'
let html = myxss.process(line);
console.log(html); //Output: < img SRC = ". / 123. PNG" onerror = "alert (1);" >
line='<style type="text/css">color:white;</style>'
html = myxss.process(line);
console.log(html); //Output: < style type = "text / CSS" > Color: white</ style>

xss default whiteList can be displayed through console.log(xss.whiteList).

(3) If you want to completely filter out similar script and noscript tags, the option can be set as follows:

const option={
    stripIgnoreTagBody: ["script","noscript"],
}
const myxss = new xss.FilterXSS(option)
let line='<script type="text/javascript">alert(1);</script>'
let html = myxss.process(line)
console.log(html.length) //Output 0, that is, html is converted to an empty string
line='<noscript>123</noscript>'
html = myxss.process(line)
console.log(html.length) //Output 0, that is, html is converted to an empty string

stripIgnoreTagBody is used to set the filtering method of tags that are not in the whiteList. For example, if script is not in whiteList, the escape HTML method inside xss will be executed. For example, the beginning example will escape "<", ">". But if script is added to stripIgnoreTagBody. The entire script tag will be filtered out directly.

(4) The default filter generated by xss is to filter out the class attribute of any tag. If we don't want to filter the class attribute of any tag in whiteList, we can set it as follows:

const option={
    onIgnoreTagAttr: function(tag, name, value, isWhiteAttr) {
        if (['style','class'].includes(name)) {
            return `${name}="${xss.escapeAttrValue(value)}"`
        }
    },
}
const myxss = new xss.FilterXSS(option);
let line='<div class="box"></div>'
let html = myxss.process(line);
console.log(html); //Output: < div class = "box" > < / div >

The onignorettr method is used to set the filtering method for specific attributes in the whitelist.

For more detailed tutorials, please see the website attached at the beginning.

Tags: Javascript Vue Vue.js xss

Posted on Wed, 03 Nov 2021 04:39:04 -0400 by Collin