之所以單獨的把他拿出來呢,是因為之前接觸到的還原序列化的洞和題目已經挺多了的,包括p總出的三個白帽啊,某ctf的一些題目都涉及到這個方面的東西。
但是呢,在這道題目裡找到了一些新的東西,值得自己思考一下
參考了資料 http://drops.wooyun.org/tips/3909
和p總的提示:
session的序列化是指,儲存到session檔案中的是經過序列化的字串,而我們能訪問到的$_SESSION是已經被解析的變數
首先我們要瞭解,php在session儲存和讀取資料時,都會有一個序列化和還原序列化的過程。
而還原序列化中會調用對象的magic方法,比如__destruct(),__wakeup()等,都是很常見的東西,不予贅述了。
那麼這裡有一個配置選項 session.serialize_handler
可以用ini_set或者在php.ini中加以設定
有下面幾種用於處理序列化的處理器類型
處理器 對應的儲存格式
php 鍵名 + 豎線 + 經過 serialize() 函數反序列處理的值
php_binary 鍵名的長度對應的 ASCII 字元 + 鍵名 + 經過 serialize() 函數反序列處理的值
php_serialize
(php>=5.5.4) 經過 serialize() 函數反序列處理的數組
對於php處理器,如果我們先用php_serialize加以序列化,那麼對於這樣的一個字串
a:1:{s:4:"test";s:20:"|O:8:"stdClass":0:{}";}
最後會被解釋為:鍵名為 a:1:{s:4:"test";s:20:"的一個對象
而php處理器序列化,則是把$_SESSION的每個索引值都 單獨拿出來,比如$_SESSION['test']
就是test|序列化的值
而php_serialize則會直接將整個session數組序列化。最後儲存的是一整個數組的序列化數值
那麼這樣就好理解了,如果在處理器session.serialize_handler=php_serialize的情況下
我們構造帶有豎線的字串,在其他處理器為php的地方,就可以還原序列化出偽造的對象。
而我們這裡明顯是需要去操作session的,文章中為了測試使用的是
$_SESSION['ryat'] = $_GET['ryat'];
然而很多時候沒有這個條件的,怎麼辦呢
http://php.net/manual/zh/session.upload-progress.php
php為了提供一個上傳進度的資料
$n=ini_get("session.upload_progress.name");
會把它儲存在$_SESSION["$n"] 當中。
這樣我們構造一個檔案上傳頁,就可以成功寫入session了