2010-10-06 106 views
2

有什麼辦法來限制PHP的unserialize()只能解析數組嗎? 出於安全原因。假設在我不想調用的非序列化對象中存在一個邪惡的__unserialize()魔術方法!限制unserialize()返回數組?

回答

4

有幾個方法,你可以解決這個問題:

  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://stackoverflow.com/questions/22433167 – NoBugs 2014-03-17 20:57:42

5

有什麼辦法來限制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