清理 <script> 元素内容

Posted

技术标签:

【中文标题】清理 <script> 元素内容【英文标题】:Sanitize <script> element contents 【发布时间】:2015-12-24 13:22:04 【问题描述】:

假设我想通过动态&lt;script&gt; 元素向我的客户提供一些数据(在第一个响应中,没有延迟)。

<script><%= payload %></script>

假设payload 是字符串var data = '&lt;/script&gt;&lt;script&gt;alert("Muahahaha!")';&lt;/script&gt;。结束标记 (&lt;/script&gt;) 将允许用户将任意脚本注入我的页面。如何正确清理脚本元素的内容?

我想我可以将&lt;/script&gt; 更改为&lt;\/script&gt; 并将&lt;!-- 更改为&lt;\!--。我还需要逃脱其他危险的字符串吗?有没有更好的方法来提供这种“冷启动”数据?

【问题讨论】:

服务器端是什么语言? 将数据编码为 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;amp; 被解释为 &amp;)。但是,十六进制实体编码不包含任何具有特殊含义的 HTML 字符,因此您可以花一个价格获得两个。

从 cmets 更新

OP 表示服务端代码会以表格形式生成

var data = <%= JSON.stringify(data) %>;

以上仍然适用。在将值插入 JSON 时,由 JSON 类正确地对实体进行十六进制编码。这不能在课堂之外轻松完成,因为您必须再次有效地解析 JSON 以确定当前语言上下文。我不建议选择在&lt;/script&gt; 中转义正斜杠的简单选项,因为还有其他序列可以结束语法上下文,例如CDATA closing tags。正确转义,您的代码将面向未来且安全。

【讨论】:

原始帖子暗示违反规则#0,因为这似乎是直接注入脚本标签。否则,你的回答对我来说很有意义。 同意。我的回答是假设var data = ' 位是由受信任的代码生成的,并且这里只有字符串文字是用户控制的。 抱歉,OP 中的示例旨在尽可能简单。我的数据实际上是字符串化的 JSON,例如var data = "foo": "&lt;/script&gt;";,其中模板为var data = &lt;%= JSON.stringify(data) %&gt;;【参考方案2】:

针对数据的非变异进行了编辑。

如果我解释正确的话。您希望防止用户在用户提交的字符串中过早结束 script 标记。正如您在结束标记&lt;\/script&gt; 中添加反斜杠所说的那样,这可以为html 完成。在这种情况下,这是您应该担心的唯一逃避。您不需要转义 html cmets,因为浏览器会将其解释为 javascript 的一部分。也许如果某些旧浏览器不能正确解释默认为 text/javascript 类型的脚本标签(language="javascript" 已弃用),则可能需要添加 type='text/javascript'


根据 Mike Samuel 的回答 here 我可能错了不需要转义 html cmets。但是我无法用铬或铬复制它。

【讨论】:

这将使字符串安全,但它也会改变我的数据。我不一定想那样做;如果我的payload中的一个JS对象有一个字符串属性,里面有一个&amp;amp;amp;,现在如果我重新保存数据,它变成&amp;amp;amp;,然后下次我检索它时,它变成&amp;amp;amp;,依此类推.编码过程不得影响数据的完整性。 我不希望数据发生变异。取消转义数据也是一种变异形式。

以上是关于清理 <script> 元素内容的主要内容,如果未能解决你的问题,请参考以下文章

清理用户输入

怎样让前端界面自动清理js,css文件的缓存

没有包装“行”容器的清理

使用 Trix 清理 HTML 输入

CVS清理缓存

清理浮动的三种常用方法以及如何居中一个浮动元素