Json: PHP转JavaScript安全与否


Json: PHP to JavaScript safe or not?

我明白在客户端上使用eval(json_str)容易受到恶意代码的攻击。我的问题是,如果json_str是由PHP函数json_encode构造的数组,我安全吗?

例如,

json_str = json_encode(array(record1, 
                             record2, 
                             record3));
现在在客户端代码中使用eval(json_str)是完全安全的吗?

就纯JavaScript而言,是的,您是安全的:json_encode的输出永远不能包含静态值之外的任何内容,这些值在传递给eval时不会产生意外的副作用。(尽管在使用eval时通常必须用()包围JSON字符串,以避免它将对象文字表达式误解为语句块。)

旁白:这并不一定适用于所有JSON编码器,因为有一些字符在JSON字符串中包含raw是有效的,而在JavaScript中是无效的。最值得注意的是,U+2028和U+2029在JavaScript字符串字面量中不能不转义,因为它们构成换行符。然而,PHP的编码器编码所有非ascii字符(如"'u2028"),所以这里没有问题。

就JavaScript嵌入到另一种语言(通常是HTML)而言,您不一定是安全的。例如:

<script type="text/javascript">
    var v= <?php echo json_encode($value); ?>;
</script>

在这个例子中,如果value包含一个字符序列为</script的字符串怎么办?这将允许值过早地结束脚本块,从而转义为HTML标记,然后它可以在那里注入其他恶意脚本。

为了避免这个问题,当在HTML中包含JSON内容时,总是将字符串字面量中的<字符编码为'x3C,或者在JSON兼容的术语中编码为'u003C。为了与XHTML非cdata脚本块兼容,也可以使用&。为了与JS内部事件处理程序属性兼容,也使用引号。

PHP会为你做正确的选项json_encode():

var v= <?php echo json_encode($value, JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS); ?>;

(您可能需要定义一个快捷函数以使其编写更快)

如果您想使用内容安全策略(CSP),您将被阻止执行内联脚本标记。由于CSP要求所有的JavaScript都在单独的文件中,因此这将使bobince的惊人答案变得不可能。

如何在外部JavaScript中访问动态JSON:

一种方法是用PHP对JSON进行html编码(这应该防止XSS,因为json_encode/转换为'/),然后将其回发给数据块(非JavaScript MIME类型的script标签),然后使用JavaScript获取该标签的内容(改编自OWASP):

将其内联。注意,即使不使用CSP,由于type属性,它实际上也不会被浏览器执行:

<script id="jsonString" type="application/json">
<?php
echo json_encode($object, JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS); 
?>
</script>

…或者使用display: hidden HTML元素:

<div class="display-hidden">
<?php
echo json_encode($object, JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS); 
?>
</div>

然后在你的外部JavaScript文件中:

var dataElement = document.getElementById('jsonString');
var jsonString = dataElement.textContent || dataElement.innerText;
var jsonObj = JSON.parse(jsonString);

不要使用eval进行JSON解析

别这么做。

很可能您的服务器永远不会受到损害,并且您的应用程序将非常安全,等等等等,这不是重点。它可能的服务器被部分破坏(太多的攻击向量,如果php json_encode函数在您的服务器上被破坏了怎么办?)。

简单的解决方案是不要相信任何人发送的任何。现代浏览器都有原生JSON解析器,www.json.org提供了一长串针对不同语言的JSON解析器。为了提高速度,JS版本将回归到原生实现。

这一切意味着没有很好的理由使用eval进行JSON解析。

是和否:

是:PHP生成有效的JSON

不:PHP也可能像JSON一样返回恶意代码。

如果你可以信任源代码,或者你甚至可以完全控制它(因为它是你的),那就没有问题了。

它应该是安全的,但是在客户端,您不能保证json_str没有被其他来源注入。