欧美极品在线观看不卡|国产精品Va免费视频|国产国产人无码在线免费|亚洲精品无码九九九九九|亚洲国产综合精品久久久久|成人国产在线观看高清不卡|制服诱惑一区二区三区六区|国产一区二区精品高清在线观看

新聞中心

輕量級博客系統(tǒng)Typecho install.php 反序列化導(dǎo)致任意代碼執(zhí)行

作者 / 無憂主機(jī) 時間 2017-12-07 21:32:35

Typecho是一個輕量級的開源博客系統(tǒng),近日有網(wǎng)友爆出該系統(tǒng)的安裝文件install.php存在反序列化可控點(diǎn),能導(dǎo)致任意代碼執(zhí)行。 快速修補(bǔ)方法: 刪除install.php及install目錄 漏洞細(xì)節(jié): 在 install.php 文件的 288-235行

    $config = unserialize(base64_decode(Typecho_Cookie::get('__typecho_config')));
    Typecho_Cookie::delete('__typecho_config');
    $db = new Typecho_Db($config['adapter'], $config['prefix']);
    $db->addServer($config, Typecho_Db::READ | Typecho_Db::WRITE);
    Typecho_Db::set($db);
第230行獲取cookie中的__typecho_config值base64解碼,然后反序列化。想要執(zhí)行,只需isset($_GET['finish'])并且__typecho_config存在值。 反序列化后232行把$config['adapter']和$config['prefix']傳入Typecho_Db進(jìn)行實(shí)例化。然后調(diào)用Typecho_Db的addServer方法,調(diào)用Typecho_Config實(shí)例化工廠函數(shù)對Typecho_Config類進(jìn)行實(shí)例化。 跟蹤 Typecho_Db 類,構(gòu)造方法,Db.php 114-135行
public function __construct($adapterName, $prefix = 'typecho_')
{
    /** 獲取適配器名稱 */
    $this->_adapterName = $adapterName;

    /** 數(shù)據(jù)庫適配器 */
    $adapterName = 'Typecho_Db_Adapter_' . $adapterName;

    if (!call_user_func(array($adapterName, 'isAvailable'))) {
        throw new Typecho_Db_Exception("Adapter {$adapterName} is not available");
    }

    $this->_prefix = $prefix;

    /** 初始化內(nèi)部變量 */
    $this->_pool = array();
    $this->_connectedPool = array();
    $this->_config = array();

    //實(shí)例化適配器對象
    $this->_adapter = new $adapterName();
}
發(fā)現(xiàn)第120行對傳入的$adapterName進(jìn)行了字符串的拼接操作。那么如果$adapterName傳入的是個實(shí)例化對象,就會觸發(fā)該對象的__toString()魔術(shù)方法。 全局搜索__toString():發(fā)現(xiàn)三處,跟進(jìn)發(fā)現(xiàn) Typecho_Query類的__toString()魔術(shù)方法,Query.php 488-519行:
public function __toString()
{
    switch ($this->_sqlPreBuild['action']) {
        case Typecho_Db::SELECT:
            return $this->_adapter->parseSelect($this->_sqlPreBuild);
        case Typecho_Db::INSERT:
            return 'INSERT INTO '
            . $this->_sqlPreBuild['table']
            . '(' . implode(' , ', array_keys($this->_sqlPreBuild['rows'])) . ')'
            . ' VALUES '
            . '(' . implode(' , ', array_values($this->_sqlPreBuild['rows'])) . ')'
            . $this->_sqlPreBuild['limit'];
        case Typecho_Db::DELETE:
            return 'DELETE FROM '
            . $this->_sqlPreBuild['table']
            . $this->_sqlPreBuild['where'];
        case Typecho_Db::UPDATE:
            $columns = array();
            if (isset($this->_sqlPreBuild['rows'])) {
                foreach ($this->_sqlPreBuild['rows'] as $key => $val) {
                    $columns[] = "$key = $val";
                }
            }

            return 'UPDATE '
            . $this->_sqlPreBuild['table']
            . ' SET ' . implode(' , ', $columns)
            . $this->_sqlPreBuild['where'];
        default:
            return NULL;
    }
}
第492行$this->_adapter調(diào)用parseSelect()方法,如果該實(shí)例化對象在對象上下文中調(diào)用不可訪問的方法時觸發(fā),便會觸發(fā)__call()魔術(shù)方法。 繼續(xù)跟進(jìn)發(fā)現(xiàn)Typecho_Plugin類的__call()魔術(shù)方法存在回調(diào)函數(shù),Plugin.php 479-494行:
public function __call($component, $args)
{
    $component = $this->_handle . ':' . $component;
    $last = count($args);
    $args[$last] = $last > 0 ? $args[0] : false;

    if (isset(self::$_plugins['handles'][$component])) {
        $args[$last] = NULL;
        $this->_signal = true;
        foreach (self::$_plugins['handles'][$component] as $callback) {
            $args[$last] = call_user_func_array($callback, $args);
        }
    }

    return $args[$last];
}
$component是調(diào)用失敗的方法名,$args是調(diào)用時的參數(shù)。均可控,但是根據(jù)上文,$args必須存在array('action'=>'SELECT'),然后加上我們構(gòu)造的payload,最少是個長度為2的數(shù)組,但是483行又給數(shù)組加了一個長度,導(dǎo)致$args長度至少為3,那么call_user_func_array()便無法正常執(zhí)行。所以此路就不通了。 繼續(xù)跟進(jìn)Typecho_Feed類的__toString()魔術(shù)方法,F(xiàn)eed.php 340-360行
} else if (self::ATOM1 == $this->_type) {
            $result .= '_baseUrl . '"
>' . self::EOL;

            $content = '';
            $lastUpdate = 0;

            foreach ($this->_items as $item) {
                $content .= '' . self::EOL;
                $content .= '<![CDATA[' . $item['title'] . ']]>' . self::EOL;
                $content .= '' . self::EOL;
                $content .= '' . $item['link'] . '' . self::EOL;
                $content .= '' . $this-&gt;dateFormat($item['date']) . '' . self::EOL;
                $content .= '' . $this-&gt;dateFormat($item['date']) . '' . self::EOL;
                $content .= '
    ' . $item['author']-&gt;screenName . '
    ' . $item['author']-&gt;url . '
' . self::EOL;
第358行$item['author']調(diào)用screenName屬性,如果該實(shí)例化對象用于從不可訪問的屬性讀取數(shù)據(jù),便會觸發(fā)__get()魔術(shù)方法。 全局搜索__get(): 發(fā)現(xiàn)了幾處,最終確定Typecho_Request類存在可利用的地方 __get()魔術(shù)方法調(diào)用get()方法,Request.php 293-309行:
public function get($key, $default = NULL)
{
    switch (true) {
        case isset($this->_params[$key]):
            $value = $this->_params[$key];
            break;
        case isset(self::$_httpParams[$key]):
            $value = self::$_httpParams[$key];
            break;
        default:
            $value = $default;
            break;
    }

    $value = !is_array($value) && strlen($value) > 0 ? $value : $default;
    return $this->_applyFilter($value);
}
308行調(diào)用_applyFilter()方法,傳入的$value是$this->_params[$key]的值,$key就是screenName。 跟進(jìn)_applyFilter(),Request.php 159-171行:
private function _applyFilter($value)
{
    if ($this->_filter) {
        foreach ($this->_filter as $filter) {
            $value = is_array($value) ? array_map($filter, $value) :
            call_user_func($filter, $value);
        }

        $this->_filter = array();
    }

    return $value;
}
第163行array_map和164行call_user_func均可造成任意代碼執(zhí)行。

本文地址:http://www.gle-technology.com/safety/25764.html

1
1
1
1
1
1
1

客戶服務(wù)熱線

0791-8623-3537

在線客服