XSS 是什么?

Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。为了和 CSS 区分,这里把攻击的第一个字母改成了 X,于是叫做 XSS。

XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。

危害

对于普通的web应用来说,因为是在浏览器的沙盒保护中,所以XSS注入产生的危害只在当前站点中,能做的包括:显示虚假信息,泄漏cookie,泄漏网站内信息…..

通过引入外部的脚本,并由浏览器执行,来完成比较复杂的攻击策略

为什么会有 XSS

因为v-html和innerHTML这类方法(如 document.writeeval 等)可以将字符串解析成html代码,并将其渲染到页面上,或者 php 前后端没分离的情况下,可以将代码直接输出到 html 里面,如果没将用户输入的内容进行过滤,直接输出到 html,就会造成注入。

innerHTML 和类似的函数提供了极大的灵活性,允许开发者快速构建和更新页面内容。对于许多简单的应用程序和内部工具,开发者可能会选择使用这些方法,因为它们易于使用。

不仅仅是业务上的“用户的 UGC 内容”可以进行注入,包括 URL 上的参数等都可以是攻击的来源。在处理输入时,以下内容都不可信:

  • 来自用户的 UGC 信息
  • 来自第三方的链接
  • URL 参数
  • POST 参数
  • Referer (可能来自不可信的来源)
  • Cookie (可能来自其他子域注入)

XSS 的原因以及如何避免

后台模板问题

$content 的内容,没有经过任何过滤,原样输出

<p>评论内容:<?php echo $content; ?></p>

要解决这个问题,只需要后台输出的时候,将可疑的符号变成 &lt; (HTML实体)就行。

前端代码问题

$p.html(content)
$p = $('<p>'+ content +'</p>')

content 内容被原样输出了,解决办法就是不要自己拼 HTML,尽量使用 text 方法。如果一定要使用 HTML,就把可疑符号变成 HTML 实体。

治理方案

  • 封装处理方法,在所有输出到 html 都用这个方法过滤
  • 预防:使用 git commit 提交检查,识别出所有没有加过滤方法的代码并且拉群通知
  • 使用第三方工具进行扫描
  • 对陌生的链接不要随意打开,比如可以通用生成短链接的方式进行攻击

举例

一、存储型 XSS

假设我们有一个评论系统,用户 A 提交评论「小谷你好」到服务器,然后用户 B 来访问网站,看到了 A 的评论「小谷你好」,这里没有 XSS。

恶意用户 H 提交评论「<script>console.log(document.cookie)</script>」,然后用户 B 来访问网站,这段脚本在 B 的浏览器直接执行,恶意用户 H 的脚本就可以任意操作 B 的 cookie,而 B 对此毫无察觉。有了 cookie,恶意用户 H 就可以伪造 B 的登录信息,随意访问 B 的隐私了。而 B 始终被蒙在鼓里。

二、 反射性 XSS,注入到 js 代码中

如果输出是在 js 中,则可以通过 </script><script>你要执行的 js 代码</script>

三、反射性 XSS,注入到 html

可以通过html 属性执行 js 代码,比如

<input type="hidden" id="redirect_url" value='<?php echo $redirect_url;?>'/>

则 $redirect_url 可以构造为链接后面增加如下代码来执行 js,[document.domain].find(alert) 这段代码的含义是将 document.domain 包装成一个数组,然后调用数组的 find 方法,传入 alert 函数作为回调(或者也可以使用top[‘alert’](123))

' test=[document.domain].find(alert)  '

XSS 攻击小游戏

以下是几个 XSS 攻击小游戏,开发者在网站上故意留下了一些常见的 XSS 漏洞。玩家在网页上提交相应的输入,完成 XSS 攻击即可通关。

alert(1) to win prompt(1) to win XSS game

常见的 XSS 代码混淆方式

1. 编码转换

  • HTML 实体编码:攻击者将 XSS 代码中的特殊字符转换为 HTML 实体,如将 < 转换为 &lt;> 转换为 &gt;" 转换为 &quot; 等。当页面解析这些实体时,会将其还原为原始字符并执行恶意代码。
    • 示例:原本的 XSS 代码 <script>alert('XSS')</script> 可以被编码为 &lt;script&gt;alert('XSS')&lt;/script&gt;
  • URL 编码:对 XSS 代码进行 URL 编码,将特殊字符转换为 % 后跟两位十六进制数的形式。服务器在接收并解析时,会将其还原。
    • 示例<script>alert('XSS')</script> 编码后为 %3Cscript%3Ealert('XSS')%3C/script%3E
  • JavaScript 转义:在 JavaScript 中使用转义字符 \ 对特殊字符进行转义,绕过过滤机制。
    • 示例\x3cscript\x3ealert('XSS')\x3c/script\x3e,其中 \x3c 是 < 的十六进制转义,\x3e 是 > 的十六进制转义。

2. 拆分与拼接

  • 字符串拆分:将 XSS 代码拆分成多个部分,然后在页面上通过 JavaScript 代码动态拼接成完整的恶意代码。

3. 利用 HTML 标签特性

  • 事件属性:利用 HTML 标签的事件属性(如 onloadonclick 等)来触发恶意代码。
    • 示例<img src="nonexistent.jpg" onerror="alert('XSS')">,当图片加载失败时,会触发 onerror 事件执行恶意代码。
  • 标签嵌套:通过嵌套 HTML 标签来混淆代码结构,增加检测难度。
    • 示例<a href="javascript:alert('XSS')"><span>Click me</span></a>

4. 大小写混淆

  • 改变 XSS 代码中标签名、属性名的大小写,绕过对特定大小写的过滤规则。
    • 示例<SCRIPT>alert('XSS')</SCRIPT>

参考文献:https://tech.meituan.com/2018/09/27/fe-security.html