清理 <script> 元素内容
Posted
技术标签:
【中文标题】清理 <script> 元素内容【英文标题】:Sanitize <script> element contents 【发布时间】:2015-12-24 13:22:04 【问题描述】:假设我想通过动态<script>
元素向我的客户提供一些数据(在第一个响应中,没有延迟)。
<script><%= payload %></script>
假设payload
是字符串var data = '</script><script>alert("Muahahaha!")';</script>
。结束标记 (</script>
) 将允许用户将任意脚本注入我的页面。如何正确清理脚本元素的内容?
我想我可以将</script>
更改为<\/script>
并将<!--
更改为<\!--
。我还需要逃脱其他危险的字符串吗?有没有更好的方法来提供这种“冷启动”数据?
【问题讨论】:
服务器端是什么语言? 将数据编码为 JSON ...? 肯定有什么要解释的。也就是json是如何神奇地转义html的?它肯定不会。几乎每个框架都有使字符串 html 安全的方法,但只是说“json 会修复它”是完全错误的。 @ChristianVarga OP 并不担心字符串会被终止,他担心 ***.com/questions/1659749/… 这里有人遇到了由此产生的问题。那是 2009 年,也许从那时起浏览器变得更智能了,说实话我不知道。那里给出了一种解决方案。我首选的解决方案是不传递这样的数据,而是将其放置在data
属性或隐藏字段中,但我想它不能回答问题。
【参考方案1】:
假设您正在这样做:
有效载荷设置为
var data = '[this is user controlled data]';
其余代码(赋值、引号和分号)由您的应用程序生成,那么您想要的编码是十六进制实体编码。
请参阅OWASP XSS Prevention Cheat Sheet, Rule #3 了解更多信息。这将转换
</script><script>alert("Muahahaha!")
进入
var data = '\x3c\x2fscript\x3e\x3cscript\x3ealert\x28\x22Muahahaha\x21\x22\x29';
试试这个,你会发现它的优点是存储用户设置的字符串完全正确,不管它包含什么字符。此外,它还负责单引号和双引号编码。作为一个超级奖励,它也适合存储在 HTML 属性中:
<a onclick="alert('[user data]');" />
通常必须再次进行 HTML 编码才能正确显示(因为 HTML 属性中的 &amp;
被解释为 &
)。但是,十六进制实体编码不包含任何具有特殊含义的 HTML 字符,因此您可以花一个价格获得两个。
从 cmets 更新
OP 表示服务端代码会以表格形式生成
var data = <%= JSON.stringify(data) %>;
以上仍然适用。在将值插入 JSON 时,由 JSON 类正确地对实体进行十六进制编码。这不能在课堂之外轻松完成,因为您必须再次有效地解析 JSON 以确定当前语言上下文。我不建议选择在</script>
中转义正斜杠的简单选项,因为还有其他序列可以结束语法上下文,例如CDATA closing tags。正确转义,您的代码将面向未来且安全。
【讨论】:
原始帖子暗示违反规则#0,因为这似乎是直接注入脚本标签。否则,你的回答对我来说很有意义。 同意。我的回答是假设var data = '
位是由受信任的代码生成的,并且这里只有字符串文字是用户控制的。
抱歉,OP 中的示例旨在尽可能简单。我的数据实际上是字符串化的 JSON,例如var data = "foo": "</script>";
,其中模板为var data = <%= JSON.stringify(data) %>;
。【参考方案2】:
针对数据的非变异进行了编辑。
如果我解释正确的话。您希望防止用户在用户提交的字符串中过早结束 script
标记。正如您在结束标记<\/script>
中添加反斜杠所说的那样,这可以为html 完成。在这种情况下,这是您应该担心的唯一逃避。您不需要转义 html cmets,因为浏览器会将其解释为 javascript 的一部分。也许如果某些旧浏览器不能正确解释默认为 text/javascript
类型的脚本标签(language="javascript"
已弃用),则可能需要添加 type='text/javascript'
。
根据 Mike Samuel 的回答 here 我可能错了不需要转义 html cmets。但是我无法用铬或铬复制它。
【讨论】:
这将使字符串安全,但它也会改变我的数据。我不一定想那样做;如果我的payload中的一个JS对象有一个字符串属性,里面有一个&amp;amp;
,现在如果我重新保存数据,它变成&amp;amp;
,然后下次我检索它时,它变成&amp;amp;
,依此类推.编码过程不得影响数据的完整性。
我不希望数据发生变异。取消转义数据也是一种变异形式。以上是关于清理 <script> 元素内容的主要内容,如果未能解决你的问题,请参考以下文章