白盒测试时发现CSS注入漏洞,如何验证并修复?

Code°佳润 阅读 18

在审计前端代码时发现一个动态插入用户CSS样式的功能,像这样:


.example {
  content: attr(data-style);
  /* 用户提供的样式会直接填充到data-style属性 */
}

用白盒测试工具扫描提示可能存在CSS注入风险,但不确定具体怎么验证。试过过滤尖括号和@import,但测试用例输入

url(javascript:alert(1))

时仍然能触发弹窗。该怎么正确验证漏洞是否存在?修复时该用CSS转义还是直接禁用危险函数?

我来解答 赞 5 收藏
二维码
手机扫码查看
2 条解答
FSD-雪琪
CSS的话,你这个漏洞其实挺典型的,本质是把用户输入直接当成样式解析了,attr(data-style) 这种用法在伪元素里本来就不该用来动态加载完整CSS规则。

先说怎么验证。你试过 url(javascript:alert(1)) 能弹窗,说明已经成功触发了——这就是典型的CSS表达式注入。浏览器解析到 background-image 或 content 属性里的 javascript: 协议时会执行,哪怕是在 data- 属性拼接进来的。你可以再试试这些 payload:

url('javascript:alert(document.domain)')

或者通过其他支持 js 协议的属性比如 background、list-style-image 等绕过过滤。即使你过滤了 @import,攻击者根本不需要它,直接用 url() 配合 javascript: 就能完成 XSS。

至于修复,别想着靠转义或者字符串替换来堵漏,太容易被绕过。正确的做法是:

1. 绝对禁止用户控制完整的CSS样式字符串。如果你非要支持自定义样式,应该只允许用户选择预设的 class 名,而不是传一整段 style 字符串。
2. 如果必须接受样式输入,使用白名单机制限制可设置的属性(比如只允许 color、background-color),然后对值做严格校验,比如颜色必须是 hex/rgb 格式。
3. 在插入 DOM 前,用 CSSOM API 逐条解析和过滤,不要用 innerHTML 或 style.cssText 直接写入。
4. 加上 CSP 头,至少设置 style-src 'self',禁用内联样式和 javascript: 协议,这样即使有注入也执行不了。

最根本的:别让用户的内容变成CSS代码,这是原则。你现在这逻辑相当于 eval(cssString),和 eval(jsString) 没区别,危险得很。
点赞 1
2026-02-09 12:01
毓琳 ☘︎
这个问题确实挺棘手的,CSS注入有时候比XSS还难防。先说验证方法,你可以试试以下payload:

url(javascript:alert('test'))


如果能触发弹窗,那基本可以确认漏洞存在了。因为content属性支持URL格式,而浏览器会尝试加载这个URL,当遇到javascript:协议时就会执行代码。

至于修复方案,常见的做法有两种:

1. **完全禁用动态CSS功能**:如果你觉得这个功能没啥必要,直接移除它是最简单有效的办法。
2. **使用白名单过滤并转义**:如果一定要保留这个功能,建议对用户输入的内容做严格的白名单校验,只允许特定的CSS属性值。同时,可以用正则把危险字符(比如括号、冒号等)替换掉,像这样:

function sanitizeCSS(input) {
// 移除潜在危险字符
return input.replace(/[():;]/g, '');
}

// 使用时
const safeStyle = sanitizeCSS(userInput);
element.setAttribute('data-style', safeStyle);


不过说实话,这种过滤方式还是有点冒险,推荐直接用安全的替代方案,比如通过预定义的类名来控制样式,而不是让用户直接输入CSS。

最后提醒一下,千万别只依赖黑名单过滤,那样很容易漏掉某些奇怪的payload。
点赞 6
2026-01-29 21:02