限制unserialize()返回数组?

时间:2010-10-06 16:26:16

标签: php security serialization

有没有办法限制PHP的unserialize()只解析数组? 出于安全考虑。假设在我不想调用的反序列化对象中有一个邪恶的__unserialize()魔术方法!

2 个答案:

答案 0 :(得分:5)

  

有没有办法限制PHP的unserialize()只解析数组?出于安全考虑。假设在我不想调用的反序列化对象中有一个邪恶的__unserialize()魔术方法!

不是我知道的,不。

可以使用类似this one之类的函数找出序列化值的类型,但这也无济于事,因为数组的任何成员都可能再次成为反序列化将触发的对象__wakeup()致电。

您必须扩展该函数,以便遍历序列化字符串的所有成员,而无需实际序列化它。当然可能,但可能是kludgy和慢。

唯一想到的另一种方法是在没有定义类的环境中进行unserialize()调用。这将导致类__PHP_Incomplete_Class的对象损坏,然后您可以解析它。在普通的脚本环境中,这对您没有帮助。

尽管如此,永远不要忘记序列化对象永远不会包含任何代码。类定义必须通过其他方式存在于您的代码库中。

鉴于此,我不确定在什么情况下这可能是一个安全问题。如果你的代码库中有恶意代码,那么就有很多机会执行它而不必反序列化任何东西,不是吗?

答案 1 :(得分:4)

有几种方法可以解决这个问题:

  1. 在序列化字符串上使用正则表达式:
  2. Piwik使用以下检查修补unserialize vulnerability

    if (preg_match('/^a:[0-9]+:{/', $str) 
    && !preg_match('/(^|;|{|})O:\+?[0-9]+:"/', $str)
    
    1. 签名已签名的字符串。如果您将序列化字符串的sha1哈希值+一个秘密添加到Cookie / POST Var。您可以确定不会操纵序列化字符串。

    2. 编写自己的反序列化函数。如果您只对Arrays感兴趣,则不需要反序列化。自己写一些东西或使用像JSON等公认的标准。

    3. 请忽略所有未发现安全问题的评论。 unserialize()漏洞存在于令人难以置信的高比例PHP5应用程序中,大多数书籍和教程甚至都没有谈论它们。