0、前言
逛烏雲知識庫的時候看到一篇有趣的譯文:www.Bkjia.com
說的是一種注入方式,叫對象注入。對象也能注入?
是的,只要是存在污染數據,沒有什麼是不可能注入的,但是這個漏洞有點太古怪了,所以我覺得有趣。
1、原理
在程序編寫的時候,往往需要序列化一些運行時數據,所謂序列化就是按照一定的格式將運行時數據寫入本地文件。這樣做可以對數據進行本地保存,用的時候直接讀文件就可以把運行時產生的數據讀出。在PHP中就是serialize和unserialize函數了。
能夠注入的原理就是在反序列化的時候,引入了污染數據造成的,比如:
$obj = unserialize($_GET[‘injection’]) ;
通過這個語句,我們可以自己按照序列化數據的格式進行構造,得到我們想要的對象$obj。
有人就要問了,你僅僅得到這個對象$obj有啥用?先看看下面的實例。
2、情景
該情景也是來源於譯文中的demo,這裡還原一下:
. $this->filename ; return file_get_contents($this->filename) ; } } // Main User class class User { // Class data public $age = 0; public $name = ''; // 允許對象作為一個字符串輸出上面的data public function __toString() { return 'User ' . $this->name . ' is ' . $this->age . ' years old. '; } } // 用戶可控 $obj = unserialize($_GET['usr_serialized']); // 輸出 __toString var_dump($obj) ; echo $obj; ?>
上面的代碼是從用戶可控的數據獲取一個序列化數據,然後調用unserialize方法對$_GET['usr_serialized']進行反序列化,那麼這個$obj就可以被我們控制了。
正常的方式是提交:
http://127.0.0.1/code/objin.php?usr_serialized=O:4:User:2:{s:3:age;i:20;s:4:name;s:4:John;}
上面的序列化數據是一個User類的對象,其中$age=20, $name=John。
這時,echo $obj ;直接echo對象,就能調用魔術方法__toString,在User類中已經對這個魔術方法進行了重載,即輸出一段字符串,運行效果如下:
上面的代碼是從用戶可控的數據獲取一個序列化數據,然後調用unserialize方法對$_GET['usr_serialized']進行反序列化,那麼這個$obj就可以被我們控制了。
正常的方式是提交:
http://127.0.0.1/code/objin.php?usr_serialized=O:4:User:2:{s:3:age;i:20;s:4:name;s:4:John;}
上面的序列化數據是一個User類的對象,其中$age=20, $name=John。
這時,echo $obj ;直接echo對象,就能調用魔術方法__toString,在User類中已經對這個魔術方法進行了重載,即輸出一段字符串,運行效果如下:
3、漏洞挖掘
這類漏洞相當隱蔽,但是一旦出現效果很到位。挖掘主要是找找unserialize函數中的參數是否是污染數據。找到相應的控制位置,再看看哪個類可以利用起來完成我們的攻擊,比如本情景中的FileClass類。