一、反序列化基础
1、序列化和反序列化
2、PHP序列化和反序列化基本类型表达
3、PHP序列化和反序列化
4、代码中的关键函数
5、魔术方法
6、示例1
7、示例2
二、常见的反序列化
1、反序列化利用
1、存在反序列化漏洞的必要条件:
(1)存在魔术方法
(2)存在命令执行漏洞
(3)存在反序列化函数
(4)传参可控
2、反序列化漏洞利用的方法:
(1)定义类
(2)实例化类
(3)序列化类
(4)将序列化结果传入
三、Phar反序列化
1、Phar概念
2、Phar文件格式
3、Phar归档文件类型
4、生成phar文件
5、Phar反序列化作用
触发点很多
6、测试demo
phar.xxx
test.txt写入内容
7、将Phar文件伪造成其他格式文件
8、Phar://伪协议利用
四、反序列化实验基础01
1、实验目的
掌握PHP反序列化基础利用方式
2、实验地址
http://分配IP:4001
3、实验环境
一台ubuntu18.04 已经安装实验环境
一台windows 10客户端,已安装firefox浏览器、hackbar插件、burpsuit、PHP环境
4、实验内容
利用反序列化漏洞配合file_get_contents()函数读取任意文件
5、实验步骤
(1)实验主页
(2)代码分析
1、首先定义类Ser
2、第二行定义公有变量 $name
3、存在魔术方法 __toString
当实例化的类被当作字符串处理时会自动触发__toString魔术方法
4、在__toString函数中存在file_get_contents()函数,并且参数为$name,可控
5、最后存在unserialize()函数,并且参数可控
(3)利用方法
1、实例化类Ser
2、$name赋值所需读取文件名称
3、将实例化类Ser序列化并输出
4、将输出结果通过GET方式输入
<?php
class Ser{
public $name = "/etc/passwd";
}
$a = new Ser();
echo serialize($a);
?>
5、序列化输出结果为:
O:3:"Ser":1:{s:4:"name";s:11:"/etc/passwd";}
(4)最终结果
五、反序列化实验基础02
1、实验目的
掌握PHP反序列化__wakeup()魔术方法基础方式
2、实验地址
http://分配IP:4002
3、实验环境
一台ubuntu18.04 已经安装实验环境
一台windows 10客户端,已安装firefox浏览器、hackbar插件、burpsuit、PHP环境
4、实验内容
利用反序列化魔术方法__wakeup()函数配合file_get_contents()函数读取任意文件
5、实验步骤
(1)实验主页
(2)代码分析
1、首先定义Ser类
2、第二行定义私有变量 $name
3、在Ser类中,存在魔术方法 __wakeup()函数
该魔术方法在反序列化的时候自动调用,为反序列化生成的对象做一些初始化操作
4、在__wakeup()函数中存在file_get_contents()函数,并且参数为$name,可以控制
5、最后存在unserialize()函数,同时参数也可控
(3)利用方法
1、实例化类Ser
2、$name赋值所需读取文件名称
注意:$name是私有属性,在类中私有属性private和protected属性的变量,在序列化时,存在%00*%00保护它,而%00是不可见字符。
因此需要使用urlencode()函数将%00进行url编码,避免%00的缺失,下图为经过url编码后的序列化字符串。
3、将实例化类Ser序列化并输出
4、将输出结果通过GET方式输入
<?php
class Ser{
private $name = "/etc/passwd";
}
$a = new Ser();
echo urlencode(serialize($a));
?>
5、输出序列化内容为:
O%3A3%3A%22Ser%22%3A1%3A%7Bs%3A9%3A%22%00Ser%00name%22%3Bs%3A11%3A%22%2Fetc%2Fpasswd%22%3B%7D
(4)最终结果
六、反序列化实验基础03
1、实验目的
掌握PHP反序列化POP链的基本利用方式
2、实验地址
http://分配IP:4003
3、实验环境
一台ubuntu18.04 已经安装实验环境
一台windows 10客户端,已安装firefox浏览器、hackbar插件、burpsuit、PHP环境
4、实验内容
通过类A中的__destruct()魔术方法调用类B中的read_file()函数,达到读取任意文件的目标
5、实验步骤
(1)实验主页
(2)代码分析
1、首先定义类A,类B
2、在类A中存在公有变量$classname和__destruct()魔术方法,在魔术方法中调用了类B中的read_file()函数
类执行完毕以后调用,其最主要的作用是拿来做垃圾回收机制
3、在类B中,定义了私有变量$filename,同时,read_file()函数中存在file_get_contents()函数,并且参数为$filename。
4、最后存在unserialize()函数,同时参数也可控
(3)利用方法
1、实例化类A
2、并且将类A中的公有变量$classname赋值为类B的实例化对象。那么,当实例化类A的同时也实例化了类B
3、然后将类B中的私有变量$filename赋值所需读取文件名称
4、将实例化类A序列化并输出
5、最后将输出结果通过GET方式输入
<?php
class A{
public $classname;
}
class B{
private $filename="/etc/passwd";
}
//对象A的属性是对象B,那么在序列化A的时候也会序列化B
$a = new A();
$a -> classname = new B();
echo urlencode(serialize($a));
?>
6、输出序列化内容为:
O%3A1%3A%22A%22%3A1%3A%7Bs%3A9%3A%22classname%22%3BO%3A1%3A%22B%22%3A1%3A%7Bs%3A11%3A%22%00B%00filename%22%3Bs%3A11%3A%22%2Fetc%2Fpasswd%22%3B%7D%7D
(4)最终结果