json_encode是否有足够的XSS保护?

Ala*_*orm 16 javascript php json

我有一个stdClassPHP 的对象,类似于

$o = new stdClass;
$o->foo = $bar
Run Code Online (Sandbox Code Playgroud)

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

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

<script type="text/javascript">
    var o = <?php echo json_encode($o); ?>;
</script>
Run Code Online (Sandbox Code Playgroud)

我的初始直觉反应是是安全的,因为编码对象作为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>    
Run Code Online (Sandbox Code Playgroud)

导致像这样的输出

<script type="text/javascript">
    var o = {"foo":"<script type=\"text\/javascript\">alert(document.cookie) <\/script>"};    
</script>    
Run Code Online (Sandbox Code Playgroud)

如果这是不安全的,那么有一种标准的,成熟的方法可以将一个简单的stdClass对象序列化为JSON字符串,以便在<script/>HTML文档的一部分中使用.

在预期第一个快速回答时,我意识到剥离任何HTML标记,或者以其他方式对JSON对象的每个元素进行XSS过滤都可以,但我正在寻找一种简洁的方法来实现这一点.与此类似

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

还有这个

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

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

Ala*_*orm 6

似乎通过这个问题的最佳答案在于另一个问题.

总而言之,PHP的JSON编码器会转义所有非ASCII字符,因此无法将换行符/回车符插入到JSON属性的Javascript字符串部分中.其他JSON编码器可能不是这样.

然而,传递一个原始字符串到JSON编码可导致的跨站脚本攻击的通常一连串,以下常量组合被建议.

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

确保传递给的变量json_encode确实是一个对象.

  • 为什么选择"随机"选项?`/`受`\ /`(`"<\/script>`"保护好 - 为什么HEX_TAG?),JSON字符串值用双引号括起来(`"'"`是好的 - 为什么HEX_APOS?),字符串值中的双引号是转义的(`"\""`是好的 - 为什么HEX_QUOT?)和HTML中的SCRIPT元素是CDATA(所以无人看守`&entity;`没关系 - 为什么HEX_AMP?).如果把JSON放在HTML中属性(例如,不在SCRIPT/CDATA上下文中)然后正确的解决方案是在应用json_encode之后为上下文*转义它. (6认同)
  • @ user2864740我同意,不需要所有这些标志.*除了'JSON_HEX_TAG`(参见:/sf/ask/1465971671/),因为`<! - -`可以破坏你的网站(这些字符都没有被转义,一切都会被注释掉,直到` - >`) (3认同)