PHP反序列化漏洞
阿新 • • 發佈:2017-11-03
發生 arc arr 再看 記錄 php7 數據化 tostring 又能 聊一聊PHP反序列化漏洞
2016年11月4日
反序列化漏洞在各種語言中都較為常見,下面就簡單聊一聊PHP的反序列化漏洞(PHP對象註入)。第一次了解這個洞還是在某次ctf上,就簡單記錄下個人理解以及對CVE-2016-7124的簡單分析。
序列化與反序列化
php允許保存一個對象方便以後重用,這個過程被稱為序列化,序列化一個對象將會保存對象的所有變量,但是不會保存對象的方法,只會保存類的名字。先看一眼具體什麽樣子
name . ‘\‘s phone is ‘ . $this->phone;
}
}
$usr = new info();
$usr->printdata();
echo serialize($usr);
?>
此時輸出
church‘s phone is 111111
O:4:"info":2:{s:4:"name";s:6:"church";s:5:"phone";s:6:"111111";}
可以看到其中沒有任何跟類有關的東西,只有其中的數據被數據化。
O:4:"info":2:{s:4:"name";s:6:"church";s:5:"phone";s:6:"111111";}
O:4:"info":2: 參數類型為對象(object),數組(array)為a。類名為info,有兩個變量(參數
s:4:"name";s:6:"church"; s:變量類型為字符串(數字為i),長度為4,名為name,值是長度為6的字符串church
s:5:"phone";s:6:"111111"; 長度為5的字符串phone,值是長度為6的字符串111111
反序列化是將序列化後的字符串轉換回一個數組對象。由於對象實例化和自動加載,反序列化可能會導致代碼被加載並被執行。再看一下反序列化
printdata();
這時輸出
church‘s phone is 111111
反序列化漏洞
現在我們了解了序列化是如何工作的,那我們該如何利用它?因為反序列化對象的值是可控的,如果反序列化對象中存在魔術方法,而且魔術方法中的代碼又能夠被我們控制,漏洞就產生了,根據不同的代碼可以導致各種攻擊,如代碼註入、SQL註入、目錄遍歷等等。
影響:Joomla反序列化漏洞、SugarCRM v6.5.23 PHP對象註入漏洞、WordPress 3.6.1反序列化漏洞等。
魔術方法
php類可能會包含一些特殊的函數叫magic函數,magic函數命名是以符號”__“開頭的,比如 __construct, __destruct, __toString, __sleep, __wakeup等。
而這些函數在某些情況下是自動調用的,比如:
__construct當一個對象創建時調用,相反__destruct當一個對象被銷毀時調用
__sleep方法在一個對象被序列化時調用,__wakeup方法在一個對象被反序列化時調用
__toString當一個對象被當作一個字符串使用時調用
name;
}
public function __construct() {
echo ‘__construct‘;
}
public function __destruct() {
echo ‘__destruct‘;
}
public function __toString() {
return ‘__toString‘;
}
public function __sleep() {
echo ‘__sleep‘;
return array(‘name‘);
}
public function __wakeup() {
echo ‘__wakeup‘;
}
}
$usr = new info();
$usr->printdata();
echo $usr;
$serialized = serialize($usr);
echo $serialized;
$unserialized = unserialize($serialized);
$unserialized->printdata();
?>
這時會輸出
__construct
church
__toString
__sleep
O:4:"info":1:{s:4:"name";s:6:"church";}
__wakeup
church
__destruct
__destruct
可以很清楚的看到這些魔術函數的自動調用,類似的魔術方法還有很多,這裏不再一一列舉。
漏洞利用
先看一個簡單的demo:
file)) {
include($this->file);
}
}
}
$file = $_GET["file"];
if(isset($file)) {
echo unserialize($file);
}
?>
這個代碼調用了Read類,並且有一個file值是我們可以控制的,所以構造類似這樣的payload:
test.php?file=O:4:"Read":1:{s:4:"file";s:11:"/etc/passwd";}
這時僅需一個GET請求便能讀取文件。
CVE-2016-7124
php前一段時間爆了一個漏洞(php bugs 72663 ),當反序列化一個對象時,假如屬性發生了變化,就會導致__wakeup()中的return 0不會執行。簡單來說就是當序列化字符串中表示對象屬性個數的值大於真實的屬性個數時就會跳過__wakeup()方法。
影響版本PHP5 < 5.6.25 、PHP7 < 7.0.10
寫了個簡單的demo:
正常情況下序列化後$serialized是這樣的
O:4:"info":1:{s:4:"name";s:6:"church";}
執行之後,結果是這樣的
__wakeup
__destruct
可以看到__wakeup()方法被調用了。
那把$serialized改成下面這個樣子
O:4:"info":2:{s:4:"name";s:6:"church";}
再次執行之後,看結果
__destruct
由於表示對象屬性個數的值大於真實的屬性個數,很明顯__wakeup()方法這次被跳過了。
漏洞實例分析:SugarCRM v6.5.23 PHP反序列化對象註入漏洞分析
PHP反序列化漏洞