根据用户输入调用json_decode是否安全?

Is it safe to call json_decode on user input?

提问人:Fabrício Matté 提问时间:9/6/2012 最后编辑:DharmanFabrício Matté 更新时间:8/13/2022 访问量:14577

问:

我在 cookie 中存储了一个整数索引 => 个整数值的 JSON 编码数组。

显然,cookie 可以像任何其他用户输入一样轻松操作,所以这是我的 cookie getter 验证:

if ($_COOKIE['myCookie']) { //if cookie exists
    $myCookie = json_decode($_COOKIE['myCookie'], true);
    if (!is_array($myCookie)) { //in case decoding fails or bad cookie
        $myCookie = array(); //sets it as empty array
    }
} else { //if cookie doesn't exist, uses an empty array instead
    $myCookie = array();
}

然后在使用任何值之前,我检查它是否存在于数组中,并针对白名单值列表进行测试 - 这部分似乎很安全,但我发布它因为它是验证的一部分:

if (!empty($myCookie[$index])) { //checks if index exists and is truthy
    if ($myCookie[$index] !== 1 && $myCookie[$index] !== 2) { //values whitelist
        die('Hacking attempt through cookies exploit.');
    }
    //use the cookie data now
}

回到问题,直接在 cookie 上调用json_decode是否安全?用户可以操纵cookie来运行任意代码吗?

到目前为止,我一直在阅读有关 SO 的许多主题,我发现它是变暗的不安全的,因为它调用了构造函数,但在技术上是安全的。我已经通读了他们的 php.net 页面,但这些页面并没有直接解决安全性问题。unserialize()json_decode

我的插件即将进入实时测试版,所以我想知道直接调用 cookie 是否足够安全,或者我是否应该在调用之前运行某种类型的验证。我也可以运行一个,但是由于我在使用值之前正在对值的白名单进行测试,因此应该没有问题,除非以某种方式运行任意代码,但事实并非如此,对吧?json_decodejson_decodepreg_matchjson_decode

我知道如果它不是有效的 JSON,它会返回,但我想知道这是否是正确的方法,或者我应该在调用json_decode之前添加某种验证?json_encodeNULL

PHP 的JSON格式

评论

0赞 Itay Moav -Malimovka 9/6/2012
谁能利用这一点,可能会以你、我和世界其他地方从未想过的其他疯狂方式破解你的代码
0赞 Fabrício Matté 9/6/2012
@ItayMoav 感谢您的激励。 我以前从未使用过用户输入,显然除了它本身之外,没有办法验证这种数据,我认为,如果它失败,它就会返回。=]json_decodejson_decodeNULL
0赞 MauganRa 8/29/2016
如果您担心 Cookie 中数据的完整性,您应该使用 HMAC 对其进行签名,并在使用前验证 HMAC。使用库或让框架来做,自己很难把它做好!!

答:

9赞 Hamish 9/6/2012 #1

只要正确实现,在没有额外预处理的情况下使用应该是安全的(事实上,考虑到您的预处理器中可能存在错误,这可能会更糟)。json_decode

评论

0赞 Fabrício Matté 9/6/2012
你能定义“正确实施”吗?我假设PHP 5.4+的本机已正确实现。关于预处理,除了运行一个来检查可疑数据外,我不会做任何事情,但是当它解码失败时,它本身会返回,并且当我根据白名单检查值时,应该不需要它,对吧?json_decodepreg_matchjson_decodeNULL
0赞 Hamish 9/6/2012
“正确实施”,因此,它没有可能允许攻击者注入漏洞的错误。是的,它应该返回 NULL - 更重要的是 - 它在反序列化时不应该做任何危险的事情。
0赞 Hamish 9/6/2012
顺便说一句,刚刚意识到我的错别字。本来应该没有的。即,传递给 .json_decode
0赞 Fabrício Matté 9/6/2012
是的,我以为是错别字。+1'd 从那时起,希望我能有不止一个被接受的答案。接受了 xdazz 的回答,因为他稍微扩展了它的工作原理以及为什么不需要预处理。
5赞 Erik 9/6/2012 #2

如果数据不是 json 格式,json_decode将失败,否则将返回一个不错的数组供您使用。就像Itay说的那样,如果有人能利用这一点,他几乎应该进入。json_decode没有 sql 的风险,所以我会说你这样做很好。

只需确保在将其合并到查询中之前清理任何内容(或白名单,就像您已经清理的那样)。

评论

1赞 Fabrício Matté 9/6/2012
对我已经知道的东西没有增加太多,但听到我用另一种声音在想什么总是好的。=]
38赞 xdazz 9/6/2012 #3

用于直接解码用户输入没有安全问题。json_decode

它只是字符串解析,不会做任何字符串求值。

json_decode在 PHP 中就像在 JavaScript 中一样,它们都可以直接在用户输入上使用,它们在解码时是安全的。JSON.parse

但是在解码后,您必须验证数据是否符合您的要求。

评论

1赞 Fabrício Matté 9/6/2012
所以它基本上只是字符串解析,背后没有隐藏的巫术吗?谢谢你的信息。 我想我有点太偏执了。=]
0赞 Tyler V. 12/8/2017
要提供有关如何滥用它的更多见解,请参阅Magento中的此漏洞: karmainsecurity.com/KIS-2016-02 这是您在解码 JSON 并通过代码运行结果时需要查找的东西。