json_encode是否具有足够的XSS保护


Is json_encode Sufficient XSS Protection?

我在PHP中有一个stdClass对象,类似

$o = new stdClass;
$o->foo = $bar

变量$bar包含不受信任的字符串。

以下PHP模板代码是否足够XSS保护

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

我最初的直觉是安全的,因为将对象编码为JSON将确保任何潜在的javascript漏洞都将作为JSON字符串属性对象被包含,从而变得惰性。像这样的

$o = new stdClass;
$o->foo = "<script type='"text/javascript'">alert(document.cookie)</script>";
?>
<script type="text/javascript">
    var o = <?php echo json_encode($o) ?>;    
</script>    

导致类似的输出

<script type="text/javascript">
    var o = {"foo":"<script type='"text'/javascript'">alert(document.cookie) <'/script>"};    
</script>    

如果已知这是不安全的,那么是否有一种标准、成熟的方法可以将简单的stdClass对象序列化为JSON字符串,用于HTML文档的<script/>部分。

在期待第一个快速答案时,我意识到去掉任何HTML标记,或者用XSS过滤JSON对象的每个元素都是可行的,但我正在寻找一种简洁的方法。类似于

//$eBar = addslashes($bar);
$sql = sprintf("SELECT * FROM table WHERE foo = '%s'",mysql_real_escape_string($bar));

和这个

$sql = $db->select('SELECT * from table where foo = ?', $bar);

(在大多数情况下)功能等效,但后者被认为是更好、更安全的代码,因为最终程序员用户不需要担心转义方案。

似乎这个问题的最佳答案在于另一个问题。

总之,PHP的JSON编码器转义所有非ASCII字符,因此不能插入换行符/回车符来填充JSON属性的Javascript字符串部分。其他JSON编码器可能不是这样。

然而,将原始字符串传递给JSON编码可能会导致常见的一连串XSS攻击,建议使用以下常量组合。

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

确保传递给json_encode的变量实际上是一个对象。

XSS非常广泛,实际上在任何时候都不可能知道您发出的不受信任的数据是否安全。

答案实际上是,这取决于情况。json_encode本身不进行任何转义——您只是将其用于序列化目的。您想要使用的转义函数应该是htmlspecialchars

但是,是否要使用htmlspecialchars取决于。例如,您会使用innerHTMLtextContent插入o.foo的值吗?后者会导致双重转义,但前者会插入一个脚本。如果你打算使用eval(在JS中)呢?

顺便说一句,addslashes在功能上与mysql转义不等价。

我不会以这种方式混合JavaScript和PHP,但那是另一回事。

这将起作用;)

...?payload=<img%20src=x%20onerror=alert(document.cookie);>

使用json_encode。。。

<?php echo json_encode($_GET['payload']); ?>

;)

我所做的是在假设json对象安全之前对其进行评估。我认为这个方法在原型中是evalJSON(true),jquery也有类似的实现。我对JSON的xss标准了解不多,但这对我的有帮助

正如其他答案所说;json_encode不是为反xss保护而构建的。除非您专门对不安全的字符串进行编码(或正确地进行消毒),否则您将面临潜在的问题。

此外,一旦从JSON对象中提取出该字符串,如果在任何时候将其注入到页面中,它仍然具有潜在的危险性。例如:

<?php $a->foo = "<script>alert(1)</script>"; ?>
var v = <?php echo json_encode($a); ?>

不太可能执行(尽管您不能确定)。但如果你要这样做:

$('#some-element').html(v.foo);

你绝对会遇到漏洞。