前端安全——XSS攻击与防御原理详解

前言

这周末应该有很多人被叫去加班改bug了吧,因为出现了一个log4j的bug,可以让黑客进行攻击,所以都在紧急修复这个问题。
现在互联网的开发者最关心的问题是是什么?肯定是安全。不止是开发者会关心安全问题,就是普通用户也会关心这个问题,如果一个网站或者一个APP不安全,用户是不会选择使用的,谁愿意让自己的信息公布于众,而随着技术的发展各种各样的攻击手段层出不穷。这里有一个网站,隔一段时间就会统计各种web攻击的排名前十:owasp,感兴趣的可以点进去看看,下面我先列出2017年和2021年攻击手段排名top10:
在这里插入图片描述
从图上可以看到作为一名前端开发者经常听到的一些攻击:XSS、Injection等等,为啥这里面没有CSRF呢,目前为止我们对CSRF的防范已经很成熟了,现在使用的token就是为了防止CSRF的攻击而产生,而且它的攻击手段简单,不像XSS难以防范,所以已经跌出前十了,在前几年还能排进前十。

XSS

下面就开始讲我们本篇文章的重点了,那就是XSS(跨站脚本攻击)。先来看一下XSS的定义:XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。
我们想个问题:如果你能够在别人的网站里植入JS,你会干嘛?如果我们可以在一个网站里植入自己的js代码,我们就拥有了无限的可能,比如:无限弹窗、篡改网站页面、获取用户信息等等。甚至你可以在网站里植入广告,以此来获取大量利润,这都是完全可以实现的。所以XSS的危害是巨大的,作为一个前端开发人员不得不小心。

XSS分类

根据攻击的来源可以分为三种类型:存储型、反射型、DOM型三种。

存储型XSS

存储型 XSS 的攻击步骤:

  1. 攻击者将恶意代码提交到目标网站的数据库中。
  2. 用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器。
  3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
  5. 这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。
反射型XSS

反射型 XSS 的攻击步骤:

  1. 攻击者构造出特殊的 URL,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
  3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

反射型 XSS 跟存储型 XSS 的区别是:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。
反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。
由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击。
POST 的内容也可以触发反射型 XSS,只不过其触发条件比较苛刻(需要构造表单提交页面,并引导用户点击),所以非常少见。

DOM型XSS
  1. 攻击者构造出特殊的 URL,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL。
  3. 用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。

攻击举例

在这里插入图片描述
随便在一个html文件里写一个input和button,假设现在是一个文章的评论区,那么我们在这个input框里输入的文字就是我们要评论的内容,点击按钮发表评论,发表的内容会在下面展示出来,我们先测试一下:
在这里插入图片描述
很完美,可以打印出来了,那么普通文本可以展示出来,换成标签呢,我们在试试:
在这里插入图片描述
可以看到我们输入s标签就是加横线的,下面打印出来的和我们输入的不一样,这里我是使用的innerHTML展示的输入框内容。如果我们在一个网站里输入东西之后展示的是这样的结果,那么我们就可以做很多事情了,因为这代表着这个网站没有对XSS进行防御,我们可以为所欲为,下面就进行一个弹窗的测试,更直观的展示使用document.write()来实现,innerHTML需要一些特殊操作:
在这里插入图片描述
如上图所示,在输入框中输入一行js代码,点击打印文字就会执行。不要仅仅以为只能执行这几行js代码感觉做不了什么事情,script标签的src属性可以链接外部文件。加入一个黑客写了一堆代码,然后使用src加载这个文件并执行,这是一件非常可怕的事情。上面的演示只是本地模拟,真正的场景是会把评论内容存进数据库,这样会造成每个看到这个评论的用户都会执行这句恶意注入的代码,这就会造成很严重的影响,下面我们再来看一个改变DOM结构的XSS攻击:

<!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="inp">
    <button id="btn">打印文字</button>
    <div id="box"></div>
    <script>
        let inp = document.getElementById('inp');
        let btn = document.getElementById('btn');
        let box = document.getElementById('box');
        btn.onclick = function() {
            let value = inp.value;
            box.innerHTML = "<img src='"+value+"'></img>";
        }
    </script>
</body>
</html>

这是我们要测试的代码,可以看到这行代码里引入了一个img标签,输入的内容会作为这个img的src,这个场景也很常见,比如头像上传,图片上传等等。
在这里插入图片描述

我们在input框中输入1'onerror='alert("xss")也会执行这些代码,1’是为了闭合img标签的src,否则后面的js代码无法生效。我们甚至可以在输入框中执行一个函数添加一个诱导链接,然后获取用户信息。

XSS防御

通过上面的举例和分类可以看出xss攻击有两大要素:

  1. 攻击者提交恶意代码
  2. 浏览器执行恶意代码

解决方法:从输入到输出都要进行过滤、转义。永远不要相信用户的输入!!!

输入
  1. 用户输入
  2. url参数
  3. post参数
    我们需要对一些特殊的字符、标签进行编码展示:

图片来自网上

输出

永远不要相信innerHTML、document.write()、eval这三兄弟,只要网站中使用了这三种输出方式,那么恭喜你,喜提XSS攻击,这三种输出方式可以做太多的事情。

CSP(Content Security Policy)

严格的 CSP 在 XSS 的防范中可以起到以下的作用:

  1. 禁止加载外域代码,防止复杂的攻击逻辑。
  2. 禁止外域提交,网站被攻击后,用户的数据不会泄露到外域。
  3. 禁止内联脚本执行(规则较严格,目前发现 GitHub 使用)。
  4. 禁止未授权的脚本执行(新特性,Google Map 移动版在使用)。
  5. 合理使用上报可以及时发现 XSS,利于尽快修复问题。

后记

大家在进行网站开发时一定不要盲目自信,尽量使用完善的防御工具或者防御库,在开发完成后请测试人员或者安全人员进行测试,确保没有问题后在进行上线,否则可能会带来一系列的灾难。
最后给大家提供一个XSS小游戏,一共有6关,都是实现XSS攻击的,每完成一个攻击就会进入下一关,要是通关了,我想你开发的网站在XSS防御方面应该是比较可靠的:xss小游戏

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值