小曹同学的百草园
首页
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

小曹同学

一个普通的前端开发
首页
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • XSS基本概念与防范方法
    • 计算机基础
    小曹同学
    2022-03-15
    目录

    XSS基本概念与防范方法

    # XSS基本概念与防范方法

    # 何为XSS:

    跨站脚本攻击(Cross-site scripting, XSS)是一种常见的Web安全漏洞,攻击者可以利用这种漏洞在网站上注入恶意的客户端代码。当被攻击者登录网站时,就会自动运行这些恶意代码,从而使攻击者可以突破网站的访问权限,冒充受害者进行一系列的操作。

    如果web网站没有部署足够的安全验证,XSS攻击就很容易成功。浏览器没办法判断哪些脚本是恶意脚本,所以这些恶意脚本就可以随意的读取cookie,session,tokens或者其他的敏感的网站信息,或者重写HTML内容。例如[^1]:

    • 使用document.cookie拿到用户Cookie信息;
    • 使用addEventListener监听用户的行为;
    • 伪造get和post请求
    • 修改页面DOM伪造假的登录窗口窃取账号密码或者生成弹窗广告;

    XSS攻击可以分为三类:存储型(stored XSS,持久型),反射型( non-persistent XSS attack,非持久型),DOM型。

    # 1.存储型XSS攻击

    注入型脚本永久的存储在目标服务器上。当浏览器请求数据时,脚本从服务器上传回并且执行 —— MDN Cross-site scripting(跨站脚本攻击) (opens new window)

    例如在留言板中,用户浏览时输入一段脚本代码,服务器存储在数据库中。此时再查看留言时,脚本就会被执行。实现XSS攻击。

    stored-xss-attack

    # 存储型XSS攻击步骤:
    1. 攻击者通过网站漏洞将恶意的javascript脚本代码提交到服务器上存储。
    2. 当用户浏览网站时打开含有恶意代码的网页 ,恶意代码注入。
    3. 在用户浏览含有恶意脚本的页面时,恶意脚本将用户的隐私数据上传到黑客自己的服务器上。完成XSS攻击。
    # 典型的存储型XSS攻击:Samy蠕虫

    Samy Kamkar 的蠕虫在短短几小时内就感染了100 万用户一一他使用恶意的 JavaScript 代码更新他的个人资料,然后当已登录的用户访问了 Samy 的主页后,都会运行恶意代码通过浏览器发送 XHR 请求,增加 Samy 为好友、添加到自己的关注列表中并且在每个用户的自我简介后边加了一句话"but most of all, Samy is my hero." (Samy 是我的偶像〉。这是Web 安全史上第一个重量级的XSS Worm ,具有里程碑意义。

    # 实现一个存储型XSS攻击[^2]

    ex-1

    <!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>Document</title>
    </head>
    <body>
    <input type="text" id="input" />
    <button id="btn">Submit</button>   
    
    <script>
        const input = document.getElementById('input');
        const btn = document.getElementById('btn');
    
        let val;
         
        input.addEventListener('change', (e) => {
            val = e.target.value;
        }, false);
    
        btn.addEventListener('click', (e) => {
            fetch('http://localhost:8001/save', {
                method: 'POST',
                body: val
            });
        }, false);
    </script>     
    </body>
    </html>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31

    服务端代码

    const http = require('http');
    
    let userInput = '';
    
    function handleReequest(req, res) {
        const method = req.method;
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
        
        if (method === 'POST' && req.url === '/save') {
            let body = '';
            req.on('data', chunk => {
                body += chunk;
            });
    
            req.on('end', () => {
                if (body) {
                    userInput = body;
                }
                res.end();
            });
        } else {
            res.writeHead(200, {'Content-Type': 'text/html; charset=UTF-8'});
            // 直接将用户输入的内容显示在页面上
            res.write(userInput);
            res.end();
        }
    }
    
    const server = new http.Server();
    server.listen(8001, '127.0.0.1');
    
    server.on('request', handleReequest);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    # 2.反射型XSS攻击

    当用户点击一个恶意链接,或者提交一个表单,或者进入一个恶意网站时,注入脚本进入被攻击者的网站。Web服务器将注入脚本,比如一个错误信息,搜索结果等 返回到用户的浏览器上。由于浏览器认为这个响应来自"可信任"的服务器,所以会执行这段脚本。 —— MDN Cross-site scripting(跨站脚本攻击) (opens new window)

    通俗的说就是当恶意连接中含有恶意脚本代码,当用户点击链接时。恶意脚本通过网络传输到服务器中,服务器解析之后作为响应传输到浏览器中,浏览器执行代码,攻击完成。

    特点:非持久性的,需要用户点击链接或提交表单才能实现攻击。

    reflexted-xss

    相较于存储型XSS攻击,反射型XSS只需要将恶意脚本添加到链接并且诱导用户点击就能够完成攻击。

    反射型XSS案例 (opens new window)

    # 实现一个反射型XSS攻击[^2]

    ex-2

    const http = require('http');
    function handleReequest(req, res) {
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.writeHead(200, {'Content-Type': 'text/html; charset=UTF-8'});
        res.write('<script>alert("反射型 XSS 攻击")</script>');
        res.end();
    }
    
    const server = new http.Server();
    server.listen(8001, '127.0.0.1');
    server.on('request', handleReequest);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 3.反射型XSS和存储型XSS的区别[^1]

    82168049-3f4ff880-98f0-11ea-9825-dedd58333650

    # 4. 基于DOM的XSS攻击

    DOM-XSS利用原理主要是通过客户端JavaScript可以访问浏览器DOM文本对象模型,例如通过网络劫持在页面传输数据的过程中,利用JavaScript修改HTML页面的内容,添加一个恶意链接或者假的登录网站以此来盗取用户信息。

    与反射型XSS和存储型XSS不同的是,DOM-XSS攻击是运行在客户端的,并不经过服务端。因此可以绕过WAF、躲避服务器的检测效果。

    # DOM-XSS的一些案例[^3]
    • 利用innerHTML插入DOM
    • 利用hash.substring(1)将参数卸载 # 后面避免WAF检测。
    • 利用eval将用户输入的数据拼接到代码中。
    • 通过document.cookie来获取cookie等等....

    # 如何防御XSS攻击

    从前面的介绍我们可以知道,无论是存储型XSS、反射型XSS或者DOM型XSS,都是通过注入恶意的脚本,执行恶意脚本,或者修改页面结构来进行攻击的。

    所以要阻止和防御XSS攻击,可以通过阻止恶意脚本的注入(输入过滤)和恶意脚本的执行(输出过滤等)来实现。

    # 防范方法
    1. 输入过滤、检查:不要相信用户的任何输入。对用户的输入进行检查,过滤,转义等。建立可以信任的白名单。

    2. 输出过滤、检查:对输出进行编码和转义,例如nodejs可以使用js-xss库进行html代码转化。

    3. 设置http-only,JavaScript脚本就无法读取Cookie。以此来防止截取Cookie。

    # 总结

    总结下来,XSS攻击主要分为存储型XSS攻击,反射型XSS攻击,DOM型XSS攻击。其攻击方式都是通过各种方法注入恶意脚本,执行恶意脚本来进行攻击。

    所以防范方法主要是围绕输入输出检查、过滤、转义来实现。比如对输入输出进行检查、过滤、转义等,建立可信任白名单,不可信任黑名单等。其次是防止盗取Cookie通过HttpOnly来实现Cookie的防范。

    # 参考链接

    [^1]: moeacg 从前端的角度去理解 XSS 攻击 (opens new window) ↩ [^2]:会飞的Pikachu 浅说 XSS 和 CSRF (opens new window) [^3]:DOM-XSS攻击原理与防御 (opens new window)

    编辑 (opens new window)
    上次更新: 2022/03/16, 08:42:45
    最近更新
    01
    优雅代码书写之道
    06-07
    02
    图片懒加载
    05-05
    03
    项目部署
    04-16
    更多文章>
    Theme by Vdoing
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式