我想使用JavaScript将一些用户生成的CSS插入到我的html的head
中。问题是当我转义某些字符时会破坏CSS。
例如:
let css = `
@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap');
body { font-family: "Roboto", sans-serif; }
`,
style = document.createElement('style');
style.type = 'text/css';
document.head.appendChild(style);
css = escape(css);
style.appendChild( document.createTextNode( css ) );
输出:
<style type="text/css" id="custom-theme-styles">
@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap');
body { font-family: "Roboto", sans-serif !important; }
</style>
如您所见,单引号和双引号分别产生'
和"
。查询字符串中的“&”号转换为&
。我也可以使用css子组合器(>)看到问题。
是否有一种逃避CSS的方法,以使其不会破裂并能够安全地渲染?感觉好像是个坏主意,但是如果我不逃避CSS的话,这甚至是出于安全考虑吗?我可能是错的,但我认为<script>
标记内的<style>
标记不会执行。我还有其他无法逃避CSS的漏洞吗?
[我认为使用decodeURI()
或escape()
之类的字眼几乎没有任何好处。
我建议先通过PostCSS之类的内容传递它,以便首先解析CSS。从安全性和功能性的角度来看,这具有多个好处。首先,它(应该)能够检测到任何语法错误,从而使您反抗代码注入。您依赖于PostCSS或所用解析器的安全性,但这总比没有好。将来也将使添加调试消息或CSS前缀等功能变得更加容易。
关于'更安全地注入未转义的CSS是否安全?'的具体问题:我将注意到,我的相对基础的调查似乎表明<style>
元素似乎确实对脚本注入具有一定的保护作用,与其他标签相比最少。通常使用注入的代码(通过innerHTML),您可以通过执行something like this
<img src="/" onerror = "alert(1);">
但是似乎对于样式标签来说,由于它的内容始终被认为是Text node,(实际上,在示例中,您明确地将其设置为文本节点)所以这似乎是不可能的。
无论如何,我仍然肯定会通过解析器传递它。 (如果找到通过样式标签执行JavaScript的任何方法,我将更新此答案)。