◈ 渗透任务
data: URI 安全评估
任务中
你的身份
「暗影安全公司」渗透测试工程师
目标网站
EmbedView 内嵌预览服务 (embed.embedview.example.com)
委托方
EmbedView 允许用户提交 data: URI 并在 iframe 中预览
任务目标
利用 data: URI 在 iframe 中嵌入恶意脚本
- 构造包含 JS 的 data: URI
- 在 iframe 中触发 alert(1)
◈ 教程:data: URI XSS
什么是 data: URI?
data: URI scheme(RFC 2397)允许在 URL 中直接嵌入小型数据资源,无需从外部服务器加载。其基本格式为:
data:[<mediatype>][;base64],<data>
核心概念:
data: URI 可以指定任意 MIME 类型。当类型为 text/html 时,浏览器会将其作为完整的 HTML 文档解析和渲染,其中的 JavaScript 代码会正常执行。
基本语法
// 纯文本
data:text/plain,Hello World
// HTML 文档
data:text/html,<h1>Hello</h1>
// 带脚本的 HTML
data:text/html,<script>alert(1)</script>
// Base64 编码
data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==
在 XSS 中的利用场景
data: URI XSS 通常出现在以下场景:
- iframe src — 页面将用户输入作为 iframe 的 src
- object/embed data — object 标签的 data 属性
- window.open() — JavaScript 打开新窗口的 URL
- location.href — 重定向到 data: URI
- href 属性 — 链接目标为 data: URI
编码方式
方式 1:原始文本
data:text/html,<script>alert(1)</script>
直接嵌入 HTML,特殊字符需要保持原样(在 URL 中会被自动解码)。
方式 2:URL 编码
data:text/html,%3Cscript%3Ealert(1)%3C/script%3E
对 HTML 中的特殊字符进行 URL 编码。
方式 3:Base64 编码
data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==
将整个 HTML 内容进行 Base64 编码,适合绕过简单的关键字过滤。
安全过滤的不足
许多开发者认为 htmlspecialchars() 就能阻止 XSS,但 data: URI 的特殊性在于:
- 它是一个合法的 URL scheme,不会被 HTML 实体编码影响
- 作为 iframe src 时,内容在独立的浏览上下文中渲染
- 虽然同源策略限制了对父页面的直接访问,但仍可窃取 URL 参数、执行钓鱼等
浏览器差异
| 场景 | Chrome | Firefox | Safari |
|---|---|---|---|
| iframe src="data:..." | 允许 | 允许 | 允许 |
| navigation to data: | 允许 | 允许 | 限制 |
| window.open("data:...") | 允许 | 允许 | 限制 |
| a href="data:..." | 允许 | 允许 | 限制 |
◈ 练习:data: URI XSS
目标:页面允许你输入一个 URL,该 URL 会被设置为 iframe 的
src 属性。
服务端没有对 URL 的协议(scheme)做任何限制。利用 data: URI 在 iframe 中注入并执行脚本。
iframe 渲染区:
上方输入一个 URL 后点击"加载",iframe 将在此处显示内容。
示例用法:
- 正常 URL:
https://example.com - data: URI(HTML):
data:text/html,<h1>Hello</h1> - data: URI(Base64):
data:text/html;base64,PGgxPkhlbGxvPC9oMT4=
◈ 查看漏洞源码 (PHP)
<?php
$url = $_GET['url'] ?? '';
// 危险:直接将用户输入作为 iframe src,未做任何过滤
echo '<iframe src="' . $url . '" width="100%" height="200"></iframe>';
?>
◈ 过滤状态:
- URL 协议(scheme)检查 — 未过滤
data:URI 检测 — 未过滤- HTML 实体编码 — 仅用于输入框回显
- iframe src 赋值 — 直接拼接用户输入