手把手教你防御 XSS 攻击

简介: 继上一篇文章介绍了如何实现 XSS 攻击之后,后面留下了伏笔,我们应该如何去防御文章介绍的 XSS 各种攻击呢?废话少说,直接上车!

继上一篇文章介绍了如何实现 XSS 攻击之后,后面留下了伏笔,我们应该如何去防御文章介绍的 XSS 各种攻击呢?废话少说,直接上车!

202212071826163.png

您可以在线查看完整的示例源代码

攻击分类

XSS 攻击主要可以分为三类

  1. 存储型(持久型)(server端缺陷)
  2. 反射型(server 端缺陷)
  3. DOM 型(浏览器端缺陷)

接下来将从上面的攻击类型分别给出防御方案

反射型

IMG

为什么叫 ta 反射型,大概是因为

由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击。

而像上面这个是一个搜索的例子,用户需要点击下面这个链接

http://localhost:3000/search?search=<script>alert("反射型 XSS 攻击")</script>

这个反射型 XSS 攻击之所以能够成功的原因是后端未对用户提交的内容做校验,具体逻辑如下

/**
 * 基于用户搜索内容返回 /search 页面内容
 * @param {string} search 
 */
exports.generateSearchHTML = (search = "") => {
  return `
    <body>
      <form
        action="http://localhost:3000/search"
        method="GET"
        enctype="application/json"
      >
        搜索:<input class="search-input" name="search" type="text" />
        <br />
        搜索内容:${search}
        <br />
        <button class="confirm-button" type="submit">确认</button>
      </form>
    </body>
  `;
};

此类后端渲染直接拼接返回 HTML 字符串是主要原因,所以防御的主要手段就是对可能的恶意代码片段进行转义

啥是转义呢?为什么不直接把可能是恶意代码删掉就行了呢?

比如 <script>alert("反射型 XSS 攻击")</script> 里的 < > / 这几个字符,我删掉就行了

这样操作其实不太严谨,毕竟不是所有和 < > / 相关的内容都是恶意的,就比如我数学不好,我去搜索 5 < 7 的答案是多少,很合理吧?

202212142112936.png

所以过滤和删除是不行的,所以就要采用转义

转义(Escape)

有一些特别的字符被保留用于 HTML 中,这意味着浏览器会将这些字符解析为 HTML 代码。例如,如果你使用小于号( <),浏览器会将其后的文本解析为一个  tag

HTML 有一些特殊字符,就比如 < > / 这种字符,如果你想要在浏览器展示,想要 HTML 能够正常渲染,可以采用浏览器提供的实体(Entity

比如说

<span>123&amp;</span>

实际效果就是 123&

这个转义的意思和正则表达式的转义应该是差不多的

下面这个是文章使用到的转义字符的对照表

字符 十进制 转义字符
" &#34; &quot;
& &#38; &amp;
< &#60; &lt;
> &#62; &gt;
不断开空格(non-breaking space) &#160; &nbsp;

更详细的对照表请参考下面的两个表

  1. HTML转义字符常用对照表 - OSCHINA
  2. 字符实体的官方列表 - 这个格式乱乱的,建议看上面这个

防御实操

回到反射型 XSS 攻击的防御,可以在 Server 端采用转义的方式解决,代码如下

// ...
exports.generateSearchHTML = (search = "") => {
  /**
   * 转义字符串
   * @param {string} originStr
   * @returns
   */
  const escape = (originStr) => {
    let str = originStr;
    str = str.replace(/</g, "&lt;");
    str = str.replace(/>/g, "&gt;");
    str = str.replace(/"/g, "&quot;");
    str = str.replace(/'/g, "&#x27;");
    str = str.replace(/\//g, "&#x2F;");
    return str;
  };

  return `
    ...
        搜索内容:${search}
    ...
  `;
};

我的正则应该还是非常 66666

202212142148032.png

效果如下

202212142156184.gif

直接将攻击者的恶意代码渲染,并且不会执行,看看这次生成的 HTML

<body>
  <form
    action="http://localhost:3000/v2/search"
    method="GET"
    enctype="application/json"
  >
    搜索:<input class="search-input" name="search" type="text" />
    <br />
    搜索内容:&lt;script&gt;alert(&quot;反射型 XSS
    攻击&quot;)&lt;&#x2F;script&gt;
    <br />
    <button class="confirm-button" type="submit">确认</button>
  </form>
</body>

特殊字符都被转义了,恶意代码不会被执行

存储型和 DOM 型

如果你看过这篇我的前篇文章就知道,其实所谓的 XSS 攻击的三种分类都是一样的,对前端来说就是,获取变量然后渲染,XSS 在其中就是

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

XSS 攻击的处理和场景辨别是一个需要经验的知识,文章不可能介绍的了全部,尽可能的防御是对需要转义的场景可以采用受业界广泛采用的库,比如 leizongmin/js-xss

npm install xss

这样库出问题的时候就大家都出问题了,法不责众,哈哈哈哈哈哈哈哈哈

但是对于 XSS 攻击的防御还有最后一个需要介绍的

转义时机

XSS 攻击步骤

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

前端

首先前端转义再提交后端不靠谱,攻击者只要模拟发起请求,绕过前端,后端请求处理比较靠谱

后端

对于反射型来说,不需要存入数据库,而且需要拼接字符串,但对于存储型 XSS 攻击的入库内容就不太一样,比如下面这个场景

用户提交了一个评论内容,但是如果这个获取评论的 GET 请求 iOS/Andorid/Web 都需要展示呢?

比如内容在 5 < 7

如果在存入数据库时转义,那么数据库实际存储内容就是 5 &lt; 7

那么 iOS/Andorid 端请求时并展示时就是 5 &lt; 7

而对于 Web 来说,如果有用到这个请求的某个页面有 SEO 需求做了 SSR 处理,则拼接 HTML 字符串可以正常展示,而对于有用到这个请求的某个页面是使用 Ajax 来展示,则也会显示 5 &lt; 7

具体如下图

IMG

实际操作中可以

  1. 恶意代码存储进库,保证浏览器不执行就行了,拼接 HTML 处理即可
  2. 先过滤存储,在实际多端 GET 请求时再反转义一次,比如

iOS/Android 由 5 &lt; 7 转义至 5 < 7

参考资料

  1. 前端安全系列(一):如何防止XSS攻击?
  2. 原始 HTML - Vue2 Doc
  3. html中常见符号的代码表示
  4. web安全之XSS实例解析
  5. leizongmin/js-xss
  6. XSS攻击,这次一定会! - 前端私教年年 - 掘金
相关文章
|
22小时前
|
JavaScript 安全 前端开发
js开发:请解释什么是XSS攻击和CSRF攻击,并说明如何防范这些攻击。
XSS和CSRF是两种常见的Web安全威胁。XSS攻击通过注入恶意脚本盗取用户信息或控制账户,防范措施包括输入验证、内容编码、HTTPOnly Cookie和CSP。CSRF攻击则诱使用户执行未经授权操作,防范手段有CSRF Tokens、双重验证、Referer检查和SameSite Cookie属性。开发者应采取这些防御措施并定期进行安全审计以增强应用安全性。
25 0
|
22小时前
|
存储 JSON 前端开发
【面试题】XSS攻击是什么?
【面试题】XSS攻击是什么?
|
22小时前
|
缓存 安全 JavaScript
前端安全:Vue应用中防范XSS和CSRF攻击
【4月更文挑战第23天】本文探讨了在Vue应用中防范XSS和CSRF攻击的重要性。XSS攻击通过注入恶意脚本威胁用户数据,而CSRF则利用用户身份发起非授权请求。防范措施包括:对输入内容转义、使用CSP、选择安全的库;采用Anti-CSRF令牌、同源策略和POST请求对抗CSRF;并实施代码审查、更新依赖及教育团队成员。通过这些实践,可提升Vue应用的安全性,抵御潜在攻击。
|
22小时前
|
存储 安全 JavaScript
【PHP开发专栏】PHP跨站脚本攻击(XSS)防范
【4月更文挑战第30天】本文探讨了Web开发中的XSS攻击,解释了其原理和分类,包括存储型、反射型和DOM型XSS。XSS攻击可能导致数据泄露、会话劫持、网站破坏、钓鱼攻击和DDoS攻击。防范措施包括输入验证、输出编码、使用HTTP头部、定期更新及使用安全框架。PHP开发者应重视XSS防护,确保应用安全。
|
22小时前
|
安全 JavaScript Go
跨站脚本攻击(XSS)防护在Django中的应用
【4月更文挑战第15天】本文介绍了Django如何防范XSS攻击。Django模板引擎自动转义HTML以防止恶意脚本,提供`mark_safe`函数和CSRF防护。此外,建议开发者验证清理用户输入、使用内容安全策略、更新库以及遵循安全编码实践来增强防护。通过这些措施,开发者能构建更安全的Web应用。
|
22小时前
|
安全 JavaScript 前端开发
Low 级别反射型 XSS 演示(附链接)
Low 级别反射型 XSS 演示(附链接)
|
22小时前
|
存储 JavaScript 前端开发
DOM 型 XSS 演示(附链接)
DOM 型 XSS 演示(附链接)
|
22小时前
|
存储 前端开发 JavaScript
存储型 XSS 攻击演示(附链接)
存储型 XSS 攻击演示(附链接)
|
22小时前
|
存储 前端开发 JavaScript
反射型 XSS 攻击演示(附链接)
反射型 XSS 攻击演示(附链接)
|
22小时前
|
存储 安全 JavaScript
HW常见攻击方式 --XSS跨站脚本攻击
HW常见攻击方式 --XSS跨站脚本攻击
47 0