限制unserialize()返回数组?

限制unserialize()返回数组?

问题描述:

有什么办法来限制PHP的unserialize()只能解析数组吗? 出于安全原因。假设在我不想调用的非序列化对象中存在一个邪恶的__unserialize()魔术方法!限制unserialize()返回数组?

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

  1. 使用的序列化的字符串正则表达式:

Piwik修补的unserialize vulnerability具有下列检查:

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

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

并请忽略所有没有看到安全问题的评论。 unserialize()漏洞存在于令人难以置信的高比例PHP5应用程序中,大多数书籍和教程甚至不提及它们。

+0

哇,谢谢你!我开始认为我正在变成一个偏执的程序员!那么我不能使用JSON或其他任何因为我需要反序列化()的速度。有趣的是,序列化的值永远不会在客户端/服务器之间传递。它存储在我们的安全数据库中,它是加密的,并且还有散列和盐以及所有内容。但我不需要相信数据库。我的意思是,如果我们的一个db节点被搞砸了,我不希望看到我的整个应用程序与它一起下去。所有的图层和组件必须拥有自己的安全措施! – 2010-10-06 21:46:49

+0

这个答案给出了为什么它是必要的细节:http://*.com/questions/22433167 – NoBugs 2014-03-17 20:57:42

有什么办法来限制PHP的unserialize()只能解析数组吗?出于安全原因。假设在我不想调用的非序列化对象中存在一个邪恶的__unserialize()魔术方法!

不是我知道的,没有。

使用像this one这样的函数可以找出序列化值的类型,但这对您也无济于事,因为数组中的任何成员都可能是非序列化对象将触发__wakeup()调用的对象。

您将不得不扩展该函数,以便遍历序列化字符串的所有成员而不实际序列化它。当然可能,但潜在的可笑和缓慢。

想到的唯一方法是在没有定义类的环境中调用unserialize()。这会导致类__PHP_Incomplete_Class的对象被破坏,然后您可以解析出来。在正常的脚本环境中,这不会对您有所帮助。

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

鉴于此,我不确定在什么情况下这首先会成为安全问题。如果您的代码库中存在恶意代码,那么将有很多机会执行它,而不必反序列化任何内容,对吗?

+0

好的答案,完全忘了'serialize()'是如何工作的。 – 2010-10-06 17:40:12

+0

危险的类将有一个__wakeup()方法,用于消除对象的某个属性并... – 2010-10-06 18:29:04

+0

而且我们有一个庞大的类库和一个自动加载器,因此,很难确定应用程序启动时不会发生任何恶意行为!虽然系统只接受一个完全加密的字符串,但只有应用程序本身才能看到该字符串,但仍然不满意我放置我的确认图层的位置! – 2010-10-06 18:38:10