PHP反序列化-(web_php_unserialize)

题目内容

PHP反序列化-(web_php_unserialize)_第1张图片

代码分析

可以很明显地看出这是一道PHP反序列化地题目

首先判断当前是否存在 GET 参数 ” var ” , 若存在则对其进行 Base64 解码后
存入 $var 变量 . 若不存在则输出当前页面源码

对 $var 进行一个正则过滤 , 若通过正则过滤 , 则对其进行反序列化操作,
否则响应提示信息

1. 题目中给出一个 Demo 类 , 需要注意一下其中三个魔术方法

  • __wakeup() 该方法是PHP反序列化时执行的第一个方法 , unserialize()会先检查是否存在 __wakeup()方法 , 若存在则会先调用该方法 , 来预先准备对象需要的资源( 比如重新建立数据库连接 , 执行其他初始化操作等等 )
  • __construct() 与其它 OOP( 面向对象 ) 语言类似 , PHP中也存在构造方法 ,具有构造方法的类会在每次创建新对象前调用此方法 ,该方法常用于完成一些初始化工作
  • __destruct() 析构方法 , 当某个对象的所有引用都被删除或者当对象被显式销毁时 , 析构函数会被执行 .

2. preg_match()函数
PHP反序列化-(web_php_unserialize)_第2张图片
3. highlight_file()函数
highlight_file()函数对文件进行语法高亮显示

解题思路

本题中__wakeup()函数的作用为 : 将 $file 变量强制赋值为 index.php,而题目又提示 flag 在 fl4g.php 中,因此这又牵扯到一个问题了 : 如何绕过__wakeup() ?

我们知道在执行 unserialize 之前会先调用 wakeup 函数,我们需要对其进行绕过,__wakeup()存在一个缺陷__wakeup 触发于 unserilize()调用之前,但是如果被反序列话的字符串其中对应的对象的属性个数发生变化时,会导致反序列化失败而同时使得__wakeup 失效

后面对$var进行了正则匹配,所以还需要绕过正则表达式。首先去掉正则匹配的这段代码并实例化一个Demo对象,看看序列化后的字符串长什么样子
PHP反序列化-(web_php_unserialize)_第3张图片
在这里插入图片描述
可以看出序列化结果中的O:4是无法通过正则匹配的,在PHP5中可以添加一个+号来绕过正则匹配

综上可得:

把O:4改为O:+4绕过正则,把:1:改为:2:绕过__wakeup函数(比1大就行)

构造Exp,拿到flag

PHP反序列化-(web_php_unserialize)_第4张图片
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结

基本函数

serialize():用于序列化对象或数组,并返回一个字符串返回带有变量类型和值的字符串

unserialize():将通过serialize()函数序列化后的对象或数组进行反序列化,并返回
			   原始的对象结构

在php中有一些函数不需要调用就可以执行,称这种为方法为魔术方法

__construct(),类的构造函数

__destruct(),类的析构函数

__call(),在对象中调用一个不可访问方法时调用

__callStatic(),用静态方式中调用一个不可访问方法时调用

__get(),获得一个类的成员变量时调用

__set(),设置一个类的成员变量时调用

__isset(),当对不可访问属性调用isset()empty()时调用

__unset(),当对不可访问属性调用unset()时被调用。

__sleep(),执行serialize()时,先会调用这个函数

__wakeup(),执行unserialize()时,先会调用这个函数

__toString(),类被当成字符串时的回应方法

__invoke(),调用函数的方式调用一个对象时的回应方法

__set_state(),调用var_export()导出类时,此静态方法会被调用。

__clone(),当对象复制完成时调用

__autoload(),尝试加载未定义的类

__debugInfo(),打印所需调试信息

你可能感兴趣的:(ctf-web)