Web front-end security series: XSS attack and defense

Preface The Rise of Web Security

The development of Web attack technology can also be divided into several stages. In Web 1.0the era, people pay more attention to
the security issues of server-side dynamic scripts, such as uploading an executable script (commonly known as webshell) to the server to obtain permissions
. SQLInjection appeared later , and SQLthe emergence of injection is Weba milestone in the history of security. SQLInjection vulnerabilities are still Weban important part of the security field. Followed by another milestone security issue - XSS(Cross-site scripting attack). With Web 2.0the rise of , attacks such as XSS, CSRFand , have become more powerful. WebThe idea of ​​attack has also shifted from the server side to the client side, to the browser and the user.

WebWith the development of technology today, a rich and colorful Internet has been built. The vigorous development of Internet business has also spawned
many emerging scripting languages, such as Python, Ruby, , NodeJSetc. Agile development has become the main theme of the Internet. The rise of mobile phone technology and mobile Internet has also brought HTML 5new opportunities and challenges. At the same time, Websecurity technology will also keep pace with the development of the Internet and constantly evolve new changes.

Cross-site scripting attacks ( XSS) are the number one enemy in client-side scripting security. OWASP TOP 10Threats have repeatedly listed XSS
at the top of the list, and this article will focus on XSSthe offensive and defensive issues

Preliminary explorationXSS

Cross-site scripting attack , the full English name is Cross Site Script, the original abbreviation is , but in order to distinguish it CSSfrom cascading style sheets ( Cascading Style Sheet, ), it is called " " in the security field.CSSXSS

XSSAn attack usually refers to an attack behavior in which a hacker HTMLinjects tampered web pages and inserts malicious scripts to control the user's browser when the user browses the web. When this behavior first appeared, all demonstration cases were cross-domain behaviors, so it was called "cross-site scripting". Today, with Webthe complexity of terminal functions and application, it is not important whether it is cross-site, but XSSthe name has been retained.

With Webthe rapid development of development, Webdevelopment has been widely used, from the previous single PCend to the current mobile end ( APP, H5), even including desktop tools, large screens of equipment, etc., so the application scenarios generated are becoming more and more There are many, more and more complex situations, and at the same time, the iterative launch time of most Internet (especially traditional industries) product development versions is very short. In the case of one version a week and one big version in two weeks, the important attribute of security is ignored. Once attacked, the consequences will be disastrous.

XSSAttack Type Classification

XSSAttacks can be divided into three categories: reflective (non-persistent), storage (persistent), and based on DOM XSS;

reflective

The reflective type XSSsimply "reflects" the data entered by the user to the browser. In other words, hackers often need to induce users to "click" a malicious link in order to attack successfully. The reflective type XSSis also called "non-persistent **XSS**" ( **Non-persistent XSS**) .

Usually reflective XSSmalicious code exists URL, through URLthe function of passing parameters, such as website search, jump, etc. Since the user needs to actively open the malicious website URLto take effect, attackers often combine various methods to induce users to click.

One of the most basic reflection attacks is: we obtain web page data:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>XSS攻防演练</title>
</head>
<body>
    <div id="t"></div>
    <input id="s" type="button" value="这是一个按钮" onclick="test()">
</body>
<script>
    function test() {
      
      
        const arr = ['自定义的数据1', '自定义的数据2', '自定义的数据3', '<img src="11" οnerrοr="console.log(window.localStorage)" />']
        const t = document.querySelector('#t')
            arr.forEach(item => {
      
      
            const p = document.createElement('p')
            p.innerHTML = item
            t.append(p)
        })
    }
</script>
</html>

When a hacker clicks 这是一个按钮, local localStoragedata can be easily obtained, allowing them to obtain critical information.

storage type

The storage type XSSwill "store" the data entered by the user on the server side. This XSSis very stable.

A relatively common scenario is that a hacker writes a JavaScriptblog post that contains malicious code. After the article is published, all users who visit the blog post will execute this malicious JavaScriptcode in their browsers. Hackers save malicious scripts to the server, so this kind of XSSattack is called "storage type **XSS**" .

<!-- 例如我们分别在网站中的输入框中输入以下信息,并保存到远程数据库 -->
<img src="11" onerror="console.log(window.localStorage)" />
<img src="11" onerror="alert(111)" />

page input
insert image description here

insert image description here

alertWhen the user browses the page, the pop-up box is triggered and the local data is obtained successively localStorage:
insert image description here
insert image description here

The above is a typical storage attack.

based onDOM XSS

In fact, this type XSSis not divided according to "whether the data is stored on the server side", but DOM Based XSSalso reflective in effect XSS. It is divided separately because DOM Based XSSthe reason for its formation is quite special, and the security experts who discovered it specifically proposed this type XSS. DOM 型 XSSThe difference with the previous two XSSis that DOM 型 XSSduring the attack, the extraction and execution of malicious code is done by the browser, which is a JavaScriptsecurity vulnerability of the front-end itself, while the other two XSSare security vulnerabilities of the server.

Let's look at a simple example:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>XSS攻防演练</title>
</head>
<body>
    <h3>基于DOM的XSS</h3>
    <input type="text" id="input">
    <button id="btn">提交内容</button>
    <div id="div"></div>
</body>
<script>
    const input = document.getElementById('input');
    const btn = document.getElementById('btn');
    const div = document.getElementById('div');

    let inputValue;
     
    input.addEventListener('change', (e) => {
      
      
        inputValue = e.target.value;
    }, false);

    btn.addEventListener('click', () => {
      
      
        div.innerHTML = `<a href=${ 
        inputValue}>链接地址</a>`
    }, false);
</script>
</html>

We enter the following text in the input box on the page '' onclick=alert(/xss/). The quotation marks here ''are to close hrefthe attribute and give it a null value. Then click 提交内容the button, the label in the page <div id="div"></div>contains the following htmlcontent

<a href onlick="alert(/xss/)">链接地址</a>

insert image description here

XSSattack defense

The defense XSSis very complicated. Fortunately, modern browsers and front-end frameworks/libraries have already done a considerable part of the work for us.

HttpOnly

HttpOnlyIt was first proposed by Microsoft and IE 6implemented in China, and has gradually become a standard. Browsers will forbid JavaScriptaccess to pages with HttpOnlyattributes Cookie. So we need to set it in httpthe response header to let the browser know that the content cannot be obtained through other methods .set-cookiehttpOnlydocument.cookiecookie

Strictly speaking, HttpOnlyit is not for countering the post- XSS——HttpOnlyresolve hijacking attack. So using it helps mitigate the attack, but still needs other solutions that can solve the vulnerability;XSSCookieHttpOnlyXSSXSS

input check

We need to be skeptical about user input. The user may enter any string without doing any filtering checks on the input. For example, the content we expect to input is: hello word, maybe the content we received is onclick=alert(/xss/).

In XSSterms of defense, input checks generally check whether the data entered by the user contains some special characters, such as <、>、’、”etc. If special characters are found, these characters are filtered or encoded. This way of input checking can be called “XSS Filter”. There are many open source “XSS Filter”implementations on the Internet. For example a simple htmlencodeescape:

const htmlEncode = function (handleString){
    
    
    return handleString
    .replace(/&/g,"&amp;")
    .replace(/</g,"&lt;")
    .replace(/>/g,"&gt;")
    .replace(/ /g,"&nbsp;")
    .replace(/\'/g,"&#39;")
    .replace(/\"/g,"&quot;");
}

But input checking also has disadvantages, such as

  • The attacker bypasses the front-end page and directly uses the interface to submit malicious code to the remote library.
  • Input data may also be displayed in multiple places, and the context of each place may be different. If a single replacement operation is used, problems may arise. The input check also needs to be targeted. If we want to express that one number is smaller than another number ( 3 < 4), the character after the front-end escape will become 3 &lt; 4. When this value is stored in the remote end, it will be AJAXobtained and used It will cause unnecessary trouble, for example, I will perform numerical calculations and so on.

output check

Generally speaking, in addition to the output of rich text, when variables are output to HTMLthe page, encoding or escaping can be used to defend against XSSattacks.

The essence of XSS is still a kind of "HTML injection". User data is executed as part of the HTML code, thereby confusing the original semantics and generating new semantics.

As with input checks, we can encode-escape the output.

1. HTMLOutput in

For example, there is such a piece of code in our html code:

<div>$htmlVar</div>
<a href="">$htmlVar</a>

If the output variables are not processed safely, they can be directly used and rendered on the page, which can lead to direct generation XSS. The final result may generate the following code:

<div><script>alert('我是一个XSS攻击者')</script></div>
<a href="#"><img href="" onclick="alert('我是另外一个XSS攻击者')"></a>

The way to prevent this is to perform escape checks on html

2. HTMLOutput in properties

If our html attribute is a dynamic value, then the exploit attribute can also be attacked;

<div id="testXSS" data-name=""></div>

Now data-nameinsert an unescaped code into the attribute "><script>alert('我是一个XSS攻击者')</script><", the result is as follows:

<div id="testXSS" data-name=""><script>alert('我是一个XSS攻击者')</script><""></div>

3. <script>Output in label

When outputting in <script>tags, you should first ensure that the output variables are in quotes.

<script>
  // 假设userData是攻击者注入的数据
  let xssVar = userData;
</script>

The attacker needs to close the quotation marks first to implement the XSS attack:

<script>
  // 假设userData是攻击者注入的数据
  let xssVar = "";alert('我是一个script XSS攻击者');
</script>

4. CSSOutput in

The ways of forming in and CSS, styleare very diverse, so, in general, as much as possible, the output of user-controllable variables in " labels", " label attributes" and " files" is prohibited. If there must be such a requirement, it is recommended to use a CSS escaping library.style attributeXSS<style>HTMLstyleCSS

defenseDOM Based XSS

DOM Based XSSIt is a special kind of XSSvulnerability. The several defense methods mentioned above are not applicable and need special treatment. In essence, it is actually that the front-end JavaScript code of the website is not rigorous enough, and untrustworthy data is executed as code.

If you use Vue/Reactthe technology stack and don't use v-htmlthe / dangerouslySetInnerHTMLfunction, you should avoid the hidden dangers of 、 at the front-end renderstage . There will be a dedicated defense paragraph about that later.innerHTMLouterHTMLXSSVueXSS

There are many places that will be triggered DOM Based XSS, and the following places are the only way JavaScriptto output to HTMLthe page.

  • document.write();
  • document.writeln();
  • xxx.innerHTML();
  • xxx.outerHTML();
  • xxx.innerHTML.replace();
  • document.attachEvent();
  • window.attachEvent();
  • window.location();
  • window.name;

Therefore, developers need to focus on whether the parameters in these places can be controlled by users. If these are used in the project, be sure to avoid splicing untrusted data in the string.

VueXSSdefense in

VueIf you use it as a front-end development framework in your project , congratulations, Vueit will solve most of XSSthe attack problems for you, but Vueit is not a XSSframework for attack prevention, and there are still vulnerabilities to be attacked during development and use;

Vuedefensive measures in

Regardless of using a template or a rendering function, Vuethe interpolated content will be automatically escaped, just like the following template code:

<template>
    <p>{
   
   {userData}}</p>
</template>

<script>
    // 从远程获取的数据
    userData = "<script>alert('xss')</script>"
</script>

The source code content displayed on the page after the final compilation htmlis as follows:

<p>
    <script>alert('xss')</script>
</p>

The reason is Vueto help us escape the data, thus avoiding script injection. This escaping is done through browser-native APIs such as textContent, so unless there is a security hole in the browser itself, there is no security hole. The escaped content is as follows:

&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;

injectionHTML

If you want to dynamically inject remote HTMLcontent, you should first ensure that the content is safe and valid, otherwise you should take some defensive measures to filter or escape some dangerous tag symbols; for example, you can display the rendering like this HTML:

<!-- 当使用模版时 -->
<div v-html="userProvidedHtml"></div>

<!-- 当使用渲染函数时 -->
<script>
    h('div', {
      
      
    domProps: {
      
      
        innerHTML: this.userProvidedHtml
    }
    })
</script>
<!-- 当使用JSX 的渲染函数时 -->
<div domPropsInnerHTML={this.userProvidedHtml}></div>

For example, we can use a simple method (or refer to a more robust library/plug-in XSS to filter the remote userProvidedHtmldata content to ensure security;

// 一个简单的函数,通过转义<为&lt以及>为&gt来实现防御HTML节点内容
const escape = function(str){
    
    
    return str.replace(/</g, '&lt;').replace(/>/g, '&gt;')
}

style injection

Use Vuethe To avoid rendering tag inside the template style:

<style>{
      
      {
      
       userProvidedStyles }}</style>

This is because, once passed userProvidedStyles, a malicious user can still provide CSSthe to "click scam", such as styling the link as a transparent box overlaying the "login" button. Then https://user-XSS-website.com/make it look like the login page of your application, they may obtain a user's real login information, so Vue recommends using 对象语法and only allowing users to provide specific propertyvalues ​​that can be safely controlled:

<!-- sanitizedUrl应为受控的地址 -->
<a
  v-bind:href="sanitizedUrl"
  v-bind:style="{
    color: userProvidedColor,
    background: userProvidedBackground
  }"
>
  click me
</a>

There is "no silver bullet" for security issues

In the process of solving security problems, it is impossible to do it once and for all, that is to say, "there is no silver bullet".

Generally speaking, people hate troublesome things, and subconsciously hope that the trouble can be kept as far away as possible. And security is a troublesome thing, and it is an inescapable trouble. Anyone who wants to solve the security problem once and for all is wishful thinking. It is unrealistic to "deceive yourself".

Best Practices

The general rule is that as long as you allow unfiltered user-supplied content to execute (whether as HTML, JavaScriptor even CSS), you may be putting yourself in a position to be attacked. These suggestions are actually true whether you use Vue, Reactanother framework, or even no framework.

references

Guess you like

Origin blog.csdn.net/gaojinbo0531/article/details/129416340