我在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
取决于。例如,您会使用innerHTML
或textContent
插入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);
你绝对会遇到漏洞。