XSS 是什么?
Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。为了和 CSS 区分,这里把攻击的第一个字母改成了 X,于是叫做 XSS。
XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。
危害
对于普通的web应用来说,因为是在浏览器的沙盒保护中,所以XSS注入产生的危害只在当前站点中,能做的包括:显示虚假信息,泄漏cookie,泄漏网站内信息…..
通过引入外部的脚本,并由浏览器执行,来完成比较复杂的攻击策略
为什么会有 XSS
因为v-html和innerHTML这类方法(如 document.write
、eval
等)可以将字符串解析成html代码,并将其渲染到页面上,或者 php 前后端没分离的情况下,可以将代码直接输出到 html 里面,如果没将用户输入的内容进行过滤,直接输出到 html,就会造成注入。
innerHTML
和类似的函数提供了极大的灵活性,允许开发者快速构建和更新页面内容。对于许多简单的应用程序和内部工具,开发者可能会选择使用这些方法,因为它们易于使用。
不仅仅是业务上的“用户的 UGC 内容”可以进行注入,包括 URL 上的参数等都可以是攻击的来源。在处理输入时,以下内容都不可信:
- 来自用户的 UGC 信息
- 来自第三方的链接
- URL 参数
- POST 参数
- Referer (可能来自不可信的来源)
- Cookie (可能来自其他子域注入)

XSS 的原因以及如何避免
后台模板问题
$content 的内容,没有经过任何过滤,原样输出
<p>评论内容:<?php echo $content; ?></p>
要解决这个问题,只需要后台输出的时候,将可疑的符号变成 < (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 实体,如将
<
转换为<
,>
转换为>
,"
转换为"
等。当页面解析这些实体时,会将其还原为原始字符并执行恶意代码。- 示例:原本的 XSS 代码
<script>alert('XSS')</script>
可以被编码为<script>alert('XSS')</script>
。
- 示例:原本的 XSS 代码
- 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 标签的事件属性(如
onload
、onclick
等)来触发恶意代码。- 示例:
<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>
- 示例: