最近一直在学习php反序列化模块,越来越认识到自己是多么菜,在系统化学习之后找了一些大佬的博客看了一些php反序列化的总结,其中便引用了这道题,于是便去buuctf尝试了一下,顺便检验一下自己的学习成果。
tips:
serialize():string serialize( mixed $value)
返回一个字符串,有利于存储或传递 PHP 的值,同时不丢失其类型和结构。这里需要注意其中的参数除了不可以为资源`(resouce),其他的类型都可以序列化。(相当于把一张床为了方便放进房间先将其拆分成一些部件)
unserialize():mixed unserialize( string $str)
对单一的已序列化的变量进行操作,将其转换回 PHP 的值。既然资源不会被序列化那么自然也没有资源反序列化这一说。(相当于把床的各种部件组装重新变为床)
了解本题中涉及到的魔术方法
__construct
:相当于java当中的构造方法,简单来说就是在new一个对象的同时使其初始化
__invoke
:将对象作为函数使用时触发
__get
:当访问类中的不可访问或者不存在的属性时触发
__toString
:当对象被当成字符串使用时触发
__wakeup
:在调用unseralize()之前自动触发
修改类中属性的方法
1.直接写:优点是方便,缺点是只能赋值字符串。
class dome{
public $a = 'phpinfo()';
}
2.外部赋值:优点是可以赋值任意类型的值,缺点是只能操作public属性。
class dome{
public $a;
}
$o = new dome();
$o -> a = 'evil';
引用:
对于php7.1+的版本,反序列化对属性类型不敏感。尽管题目的类下的属性可能不是public,但是我们可以本地改成public,然后生成public的序列化字符串。由于7.1+版本的容错机制,尽管属性类型错误,php也认识,也可以反序列化成功。
基于此,可以绕过诸如\0字符的过滤。
3.构造方法赋值(万能方法):优点是解决了上述的全部缺点,缺点是有点麻烦
<?php
class DEMO1{
public $a;
function __construct(){
$this->a = 'evil';
}
}
不说废话,我们看这道题的源码:
<?php
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append(