假设我想通过动态< script>
元素向我的客户端提供一些数据(在第一个响应中,没有延迟)。
< script><%= payload%>< / script>



 说出来 payload
是字符串 var data ='< / script>< script> alert(“Muahahaha!”)';< / script>
。结束标记(< / script>
)将允许用户将任意脚本注入我的页面。如何正确清理脚本元素的内容?
我想我可以将< / script>
更改为< \ / script>
和<! -
到< \! -
。还有其他危险的字符串我需要逃脱吗?有没有更好的方法来提供这种“冷启动”数据?
答案 0 :(得分:1)
编辑非数据突变。
如果我正确地解释了这一点。您希望阻止用户在用户提交的字符串中过早地结束script
标记。正如您所说的那样,可以使用结尾标记<\/script>
添加反斜杠来完成html。在这种情况下,这是你应该担心的唯一逃避。您不应该转义html注释,因为浏览器会将其解释为javascript的一部分。也许如果某些较旧的浏览器不能正确解释脚本标记,则默认为text/javascript
类型(language="javascript"
已弃用),可能需要添加type='text/javascript'
。
根据Mike Samuel的回答here我可能错误地认为不需要逃避HTML评论。但是我无法用铬或铬来复制它。
答案 1 :(得分:1)
假设您正在执行此操作:
Payload设置为
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属性中的&
被解释为&
)。但是,十六进制实体编码不包含任何具有特殊含义的HTML字符,因此您可以以一个价格获得两个。
OP指出服务器端代码将以
的形式生成var data = <%= JSON.stringify(data) %>;
以上仍然适用。 JSON类可以正确地对实体编码值进行十六进制,因为它们会插入到JSON中。这不容易在课外进行,因为您必须再次有效地解析JSON以确定当前语言上下文。我不建议选择在</script>
中转义正斜杠的简单选项,因为还有其他序列可以结束语法上下文,例如CDATA closing tags。正确逃离,您的代码将来会证明并且安全。