从零开始的PHP原生反序列化漏洞
1、写在前面
OK 兄弟们,这几天一直在面试,发现很多 HR 喜欢问反序列化相关的内容,今天咱们就从最简单的 PHP 原生反序列化入手,带大家入门反序列化
2、PHP 序列化
在 PHP 中,有反序列化,就有序列化,我们先来解释一下序列化。
所谓序列化,就是将 PHP 的一个对象,序列化为一串字符串的过程,其所用的函数就是serialize()
对象:一个对多种信息描述的整体
类:一个储存信息的共享的模板,以class开头
我们先试着创建一个新的类
<?php
class seren //定义一个类
{
//变量
public $a = 'hello';
private $b = 'world';
//方法
public function print_var()
{
echo $this->a;
}
}
?>
上面就是一个很简单的类,我们来看一下,首先使用class声明了一个类seren,在这个seren类里,我们有两个变量a和b,还有一个方法print_var
现在我们要去使用这个类,就需要把这个类实例化为一个对象
//创建一个对象
$object = new seren();
//调用一个方法
$object->print_var();
我们可以使用new,将seren类实例化为一个object对象,如果我们想要使用这个类的方法,可以直接使用 $object->print_var(); 的方法来调用这个方法。
接下来,我们试着使用serialize函数,将这个对象给序列化
<?php
class seren //定义一个类
{
//变量
public $a = 'hello';
private $b = 'world';
//方法
public function print_var()
{
echo $this->a;
}
}
$object = new seren();
$c = serialize($object);
echo $c;
?>
此处我们使用 serialize 将object这个对象,序列化为c,并打印出c

此处可以看到打印出的字符串
O:5:"seren":2:{s:1:"a";s:5:"hello";s:8:" seren b";s:5:"world";}
接下来我们就把这串字符串逐个解释一下。
首先是前面的 O,代表这是一个Object,也就是一个对象,然后是 O 后面的5,代表这个对象的名称为 5 个长度,再后面的seren就是我们对象的名称,后面的 2 就是我们对象里变量的个数。
然后就是大括号里面的内容,里面都是对我们对象里的变量的描述。
第一个s:1:"a";,表示为string类型,这个变量的名称长度为 1,变量名称为 a
后面的s:5:"hello";,表示为string类型,这个值的长度为 5,值为 hello
其实从这里我们就可以发现出规律,这个字符串对对象的描述都是类型+长度+名称的格式
比较特殊的就是后面的s:8:" seren b";,此处我们可以看到似乎有点不一样,这里的长度变成了 8,并且名称变成了serenb
我们回到上面,看我们创建这个类的时候,b 的类型为private,所以就可以知道,根据规定,private类型的变量在序列化后,名称会变为类名+变量名的格式,但是serenb也只有 6 个长度,但是他提示我们有 8 个长度
其实是因为在seren的前后有两个我们不可见的%00,他真正的内容应该是%00seren%00b,%00 算是一个长度,所以一共是 8 个长度。
3、PHP 反序列化
讲完了序列化,接下来就是反序列化,反序列化的函数是unserialize(),他可以将我们的序列化后的字符串,反序列化为对象
<?php
class seren //定义一个类
{
//变量
public $a = 'hello';
private $b = 'world';
//方法
public function print_var()
{
echo $this->a;
}
}
$object = new seren();
$c = serialize($object);
$object2 = unserialize($c);
var_dump($object2);
?>
此处我们使用unserialize函数将字符串 c 反序列化为了对象object2

4、魔术方法
魔术方法是 php 反序列化漏洞利用中很重要的一环,一般以两个下划线开头,如果这个类里面存在魔术方法,他就会优先调用魔术方法
_construct() //当一个对象创建时被调用
_destruct() //对象被销毁时触发
_wakeup() //反序列化前触发
_sleep() //序列化前触发
_toString() //把类当作字符串使用时触发
_get() //用于从不可访问的属性读取数据
_set() //用于将数据写入不可访问的属性
_isset() //在不可访问的属性上调用isset()或empty()触发
_unset() //在不可访问的属性上使用unset时触发
_invoke() //当脚本尝试将对象调用为函数时触发
我们试着在类里创建一个魔术方法wakeup
<?php
class seren //定义一个类
{
//变量
public $a = 'hello';
private $b = 'world';
//方法
public function print_var()
{
echo $this->a;
}
public function __wakeup()
{
// TODO: Implement __wakeup() method.
echo 'Follow SerenSec!';
}
}
$object = new seren();
$c = serialize($object);
$object2 = unserialize($c);
?>
运行后发现输出了Follow SerenSec!

5、PHP 反序列化漏洞
我们可以试着在反序列化的时候,寻找一些比较危险的魔术方法,从而达成 RCE 的目的,这就是反序列化漏洞
下面是一个很简单的例子
<?php
class seren //定义一个类
{
//变量
public $a = 'hello';
private $b = 'world';
public $hack;
//方法
public function print_var()
{
echo $this->a;
}
public function __construct($hack) {
$this->hack = $hack;
}
public function __wakeup()
{
// TODO: Implement __wakeup() method.
echo shell_exec($this->hack);
}
}
$object2 = unserialize($_GET['hack']);
?>
此时我们发现有 __wakeup 魔术方法,其中存在 shell_exec 函数,可以执行命令,并且其中的 hack 变量是可控的
我们先构造出序列化后的字符串
O:5:"seren":3:{s:1:"a";s:5:"hello";s:8:"%00seren%00b";s:5:"world";s:4:"hack";s:6:"whoami"}
然后构造 payload
http://localhost/test.php?hack=O:5:%22seren%22:3:{s:1:%22a%22;s:5:%22hello%22;s:8:%22%00seren%00b%22;s:5:%22world%22;s:4:%22hack%22;s:6:%22whoami%22}
成功执行命令

6、结语
PHP 原生反序列化比较简单,后面会有一些拓展内容,像是POP 链和Phar 协议,这些是比较绕的地方,各位可以自行探索。
从零开始的PHP原生反序列化漏洞的更多相关文章
- Weblogic反序列化漏洞补丁更新解决方案
Weblogic反序列化漏洞的解决方案基于网上给的方案有两种: 第一种方案如下 使用SerialKiller替换进行序列化操作的ObjectInputStream类; 在不影响业务的情况下,临时删除掉 ...
- Java反序列化漏洞总结
本文首发自https://www.secpulse.com/archives/95012.html,转载请注明出处. 前言 什么是序列化和反序列化 Java 提供了一种对象序列化的机制,该机制中,一个 ...
- 原来不只是fastjson,这个你每天都在用的类库也被爆过反序列化漏洞!
GitHub 15.8k Star 的Java工程师成神之路,不来了解一下吗! GitHub 15.8k Star 的Java工程师成神之路,真的不来了解一下吗! GitHub 15.8k Star ...
- 通过WebGoat学习java反序列化漏洞
首发于freebuff. WebGoat-Insecure Deserialization Insecure Deserialization 01 概念 本课程描述了什么是序列化,以及如何操纵它来执行 ...
- 【CVE-2020-1948】Apache Dubbo Provider反序列化漏洞复现
一.实验简介 实验所属系列: 系统安全 实验对象:本科/专科信息安全专业 相关课程及专业: 计算机网络 实验时数(学分):2 学时 实验类别: 实践实验类 二.实验目的 Apache Dubbo是一款 ...
- 反序列化漏洞问题研究之php篇
php的反序列化反序列化漏洞又称php对象注入(php Object Injection)产生的问题主要分以下两类: 将传来的序列化数据直接unserilize,造成魔幻函数的执行.这种情况在一般的应 ...
- Java反序列化漏洞执行命令回显实现及Exploit下载
原文地址:http://www.freebuf.com/tools/88908.html 本文原创作者:rebeyond 文中提及的部分技术.工具可能带有一定攻击性,仅供安全学习和教学用途,禁止非法使 ...
- Java反序列化漏洞通用利用分析
原文:http://blog.chaitin.com/2015-11-11_java_unserialize_rce/ 博主也是JAVA的,也研究安全,所以认为这个漏洞非常严重.长亭科技分析的非常细致 ...
- Java反序列化漏洞分析
相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...
- 小白审计JACKSON反序列化漏洞
1. JACKSON漏洞解析 poc代码:main.java import com.fasterxml.jackson.databind.ObjectMapper; import com.sun.or ...
随机推荐
- 流程控制之switch选择结构
实现方式:switch case语句 switch case语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支 switch语句中的变量类型可以是: byte.short.int或者cha ...
- 【忍者算法】从生活场景到回文链表:探索对称性检测|LeetCode 234 回文链表
从生活场景到回文链表:探索对称性检测 生活中的回文现象 在日常生活中,回文无处不在.比如"上海自来水来自海上"."12321"这样正着读和倒着读都一样的字符串或 ...
- Azure Data Factory - [01] 触发器
题记部分 一.概述 Azure Data Factory(后面简称ADF)的触发器是一种机制,用于在特定事件发生时自动执行数据管道.触发器可以基于事件间隔.数据变化或其他外部事件来启动数据管道的执 ...
- Scala样例类及底层实现伴生对象
package com.wyh.day01 /** * 样例类的使用 * 1.使用case修饰类 * 2.不需要写构造方法,getter,setter方法,toString方法 * 3.直接通过对象名 ...
- 【由技及道】CI/CD的量子纠缠术:Jenkins与Gitea的自动化交响曲【人工智障AI2077的开发日志】
摘要:当代码提交触发量子涟漪,当构建流水线穿越时空维度--欢迎来到自动化构建的十一维世界.本文记录一个未来AI如何用Jenkins和Gitea搭建量子纠缠式CI/CD管道,让每次代码提交都成为时空交响 ...
- pandas 删除指定条件的行
inplace=True:不创建新的对象,直接对原始对象进行修改: inplace=False:对数据进行修改,创建并返回新的对象承载其修改结果. 删除工作日餐补为0的记录 row_index=df[ ...
- go errors转string
前言 在 Go 中如果声明了两个字符相同的错误,但命名是新的变量,此时两个错误不相等 package main import ( "errors" "fmt" ...
- 如何在 Github 上获得 1000 star?
作为程序员,Github 是第一个绕不开的网站.我们每天都在上面享受着开源带来的便利,我相信很多同学也想自己做一个开源项目,从而获得大家的关注.然而,理想很丰满,现实却是开发了很久的项目仍然无人问津. ...
- delphi获取DOS命令行输出函数 运行CMD命令并获取结果
procedure TForm1.Button4Click(Sender: TObject); var hReadPipe,hWritePipe:THandle; si:STARTUPINFO; ls ...
- 利用AI增强VS Code TypeScript插件:AnyToTS带来编程新体验
Any to TS: VSCode 扩展插件 概述 "Any to TS" 是一个强大的 VSCode 扩展插件,旨在将任何对象转换为 TypeScript 类型或接口.该工具基于 ...