白盒测试时发现CSS注入漏洞,如何验证并修复? Code°佳润 提问于 2026-01-28 14:06:31 阅读 18 安全 在审计前端代码时发现一个动态插入用户CSS样式的功能,像这样: .example { content: attr(data-style); /* 用户提供的样式会直接填充到data-style属性 */ } 用白盒测试工具扫描提示可能存在CSS注入风险,但不确定具体怎么验证。试过过滤尖括号和@import,但测试用例输入 url(javascript:alert(1)) 时仍然能触发弹窗。该怎么正确验证漏洞是否存在?修复时该用CSS转义还是直接禁用危险函数? Web安全测试白盒测试 我来解答 赞 5 收藏 分享 生成中... 手机扫码查看 复制链接 生成海报 反馈 发表解答 您需要先 登录/注册 才能发表解答 2 条解答 FSD-雪琪 Lv1 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 毓琳 ☘︎ Lv1 这个问题确实挺棘手的,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 加载更多 相关推荐 1 回答 4 浏览 PostCSS插件开发中,如何在处理完所有节点后再执行某个操作? 我现在在写一个PostCSS插件,需要在遍历修改完所有CSS规则后统计处理过的节点数量。但发现执行console.log时数据还没完全更新: module.exports = postcss.plug... 西门小利 工具 2026-02-19 13:20:24 1 回答 43 浏览 如何根据网络状况动态调整CSS资源的预加载优先级? 我在移动端项目里用预加载公共CSS文件,但发现4G环境下首屏渲染反而更慢了。尝试用navigator.connection有效吗? 现在这样写的预加载代码: /* 公共样式预加载 */ <lin... 博主米娅 优化 2026-02-17 04:42:27 2 回答 19 浏览 CSS样式中的expression()如何绕过事件属性过滤导致XSS? 我在开发评论系统时发现,即使过滤了所有on开头的事件属性,用户提交的CSS代码还是能触发XSS。比如有人写了个这样的样式: div { width: expression(alert('XSS'));... 打工人尚勤 安全 2026-02-12 21:11:25 2 回答 17 浏览 PostCSS插件如何处理CSS-in-JS中的动态类名? 在用Styled Components写嵌套样式时,发现postcss-nested插件对动态生成的类名不起作用。比如这样写: const Component = styled.div .${dyna... Top丶含含 工具 2026-02-11 01:23:29 1 回答 34 浏览 Taro页面跳转后样式被重置,如何保持原页面CSS? 在Taro项目里用了navigator标签跳转页面,发现目标页面的CSS样式全被重置了。比如这个按钮样式: .button { background: linear-gradient(to right... 轩辕文茹 框架 2026-02-06 16:52:33 2 回答 26 浏览 如何在Nginx的Content-Security-Policy中正确允许data:的CSS背景图片? 我在Nginx配置里启用了Content-Security-Policy头,但发现页面的CSS数据URI背景图被阻止了。尝试过在style-src里加了'data:'和'self',但还是报错“Blo... 小雨欣 工具 2026-01-27 17:49:03 2 回答 27 浏览 如何减少首屏CSS阻塞导致的白屏时间? 在优化移动端首页时,发现首屏加载白屏时间超过3秒。明明已经压缩了CSS文件,但开发者工具里Network面板还是显示CSS文件解析阻塞了渲染,这是什么原因? 代码结构大概是这样:<pre cla... 东方爱慧 移动 2026-01-27 09:57:25 1 回答 25 浏览 移动端CSS动画导致滚动卡顿,如何优化性能? 我在手机端用CSS transform做了一个元素缩放动画,但发现页面滚动时会出现明显卡顿。之前试过给动画元素加will-change: transform,但没太大改善,反而感觉更卡了? 代码大概是... Designer°素红 移动 2026-01-26 09:07:23 1 回答 5 浏览 预加载图片时为什么会阻塞关键CSS加载? 我在电商详情页用预加载商品轮播图,但发现首屏渲染变慢了。用Lighthouse检查发现关键CSS的加载时间被图片占用了,这是为什么? 尝试过这样写: <link rel="preload" hr... 极客清梅 优化 2026-02-19 16:29:24 1 回答 28 浏览 合并CSS后部分页面样式错乱怎么办? 我在合并项目中的两个CSS文件时,发现登录页的按钮样式突然变成默认样式了。之前分别引入时没问题,合并后其他页面正常,就登录页出问题。试过调整合并顺序、检查选择器权重,都没解决。 合并前的HTML是这样... 琪帆酱~ 优化 2026-02-18 15:53:26
先说怎么验证。你试过 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) 没区别,危险得很。
如果能触发弹窗,那基本可以确认漏洞存在了。因为
content属性支持URL格式,而浏览器会尝试加载这个URL,当遇到javascript:协议时就会执行代码。至于修复方案,常见的做法有两种:
1. **完全禁用动态CSS功能**:如果你觉得这个功能没啥必要,直接移除它是最简单有效的办法。
2. **使用白名单过滤并转义**:如果一定要保留这个功能,建议对用户输入的内容做严格的白名单校验,只允许特定的CSS属性值。同时,可以用正则把危险字符(比如括号、冒号等)替换掉,像这样:
不过说实话,这种过滤方式还是有点冒险,推荐直接用安全的替代方案,比如通过预定义的类名来控制样式,而不是让用户直接输入CSS。
最后提醒一下,千万别只依赖黑名单过滤,那样很容易漏掉某些奇怪的payload。