反序列化漏洞笔记

1 PHP 序列化基础概念

1.1 什么是序列化

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

为什么要序列化?

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

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

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

对象:对象是类的实例。

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

PHP 序列化函数

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

┌──(root㉿xuegod52)-[~]
└─#  cd /var/www/html/
└─#  vim serialize.php
<?php
//创建一个类 Testclass 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.phpprivate $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.rhkb.cn/news/305522.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git 删除本地分支 删除远程仓库中的分支

语法&#xff1a; 删除本地分支 git branch -D <分支名>删除远程分支 git push <remote名称> <分支名> --delete 示例&#xff1a; 删除本地分支 git branch -D feature/test_listview删除远程分支 git push origin feature/test_listview --delete 两个…

Day36|贪心算法part05:435. 无重叠区间、763.划分字母区间、56. 合并区间

435. 无重叠区间 有了上题射气球的因子&#xff0c;这题也就有思路了&#xff0c;反正无脑排序就行了&#xff1a; 首先将所有区间按照end的大小从小到大排序&#xff1b;选取最早end为起始x_end遍历所有区间&#xff0c;如果该区间的start比end大&#xff08;可重叠&#xf…

利用Python实现可视化交互界面:Dash

Dash是一个低代码数据框架&#xff0c;用Python实现可视化交互界面&#xff0c;不用写Javascript&#xff0c;开源&#xff0c;支持回调、HTML组件等功能。 安装 pip install dash使用 # Import packages from dash import Dash, html, dash_table, dcc, callback, Output, …

基于 WebRTC 实现的点对点文件传输和音视频聊天工具 | 开源日报 No.220

tl-open-source/tl-rtc-file Stars: 2.1k License: MIT tl-rtc-file 是一个基于 WebRTC 的文件传输工具&#xff0c;支持跨终端、不限平台的在线文件传输。它提供了丰富的功能和特性&#xff1a; 分片传输&#xff1a;支持大型文件的分片传输&#xff0c;确保高效稳定地完成上…

使用htmlentities()和nl2br()将文本数据正确显示到前台

问题&#xff1a; 在后台textarea里编辑了有一串字符串&#xff0c;虽然在textarea里编辑是有换行效果的&#xff0c;但是数据获取到就只是\n&#xff0c;前端是不认识这个的&#xff0c;正确输出到前台的换行只能是<br/>。 $str "ABCDEFGHIJKLMNOPQ"; echo…

【opencv】示例-fback.cpp 使用OpenCV库来实现密集光流算法

// 引入OpenCV库中有关视频跟踪的头文件 #include "opencv2/video/tracking.hpp" // 引入OpenCV库中有关图像处理的头文件 #include "opencv2/imgproc.hpp" // 引入OpenCV库中有关视频输入的头文件 #include "opencv2/videoio.hpp" // 引入OpenC…

DVWA -XSS(Reflected)-通关教程-完结

DVWA -XSS&#xff08;Reflected&#xff09;-通关教程-完结 XSS&#xff08;Reflected&#xff09; ​ XSS 攻击全称跨站脚本攻击。是指用户在 Web 页面中提交恶意脚本&#xff0c;从而使浏览包含恶意脚本的页面的用户在不知情的情况下执行该脚本&#xff0c;导致被攻击的行为…

Elasticsearch部署安装

环境准备 Anolis OS 8 Firewall关闭状态&#xff0c;端口自行处理 Elasticsearch&#xff1a;7.16.1&#xff08;该版本需要jdk11&#xff09; JDK&#xff1a;11.0.19 JDK # 解压 tar -zxvf jdk-11.0.19_linux-x64_bin.tar.gz# 编辑/etc/profile vim /etc/profile# 加入如下…

动态规划-入门三道题

1137. 第 N 个泰波那契数 题目描述&#xff1a; 状态表示: dp[i]表示第i个泰波那契数。 状态转移方程&#xff1a; dp[i]dp[i-3]dp[i-2]dp[i-1]。 初始化: 动态规划问题的初始化就是为了去避免初始情况下的越界问题。这里就对dp[0]0,dp[1]1,dp[2]1这样进行初始化即可&#xf…

基于Vue的宠物领养系统的设计与实现(论文+源码)_kaic

目 录 摘 要 ABSTRACT 1 引言 1.1 课题背景 1.2 设计原则 1.3 论文组织结构 2 系统关键技术 2.1 JSP技术 2.2 JAVA技术 2.3 B/S结构 2.4 MYSQL数据库 3 系统分析 3.1 可行性分析 3.1.1 操作可行性 3.1.2 经济可行性 3.1.3 技术可行性 3.1.4 法律可行性 3.2 系统功能分析 3.3…

搭建PyTorch神经网络进行气温预测(手写+调包两种方法)(保证学会!)+找到神经网络的最优情况

代码上有注释&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 本篇主要包括三大部分&#xff1a; 第一部分&#xff1a;导入数据集导入第三方库数据集简单介绍与可视化数据集简单预处理 第二部分&#xff1a;手写神经网络代码实现气温预测&#…

【高端电流检测IC储能产品应用方案】耐压28V侧轨的电流检测芯片FP130A 应用于电脑电源,开关电源以及多口快充充电器,户外移动电源,适配器,电池充电器等

电流检测技术常用于高压短路保护、电机控制、DC/DC换流器、系统功耗管理、二次电池的电流管理、蓄电池管理等电流侦测等场景。对于大多数应用而言&#xff0c;都是间接测量电阻两端的跨压差来获取待测电流。 如下面的高端电流检测芯片FP130A&#xff0c;丝印是FC915。电路原理图…

SOLIDOWRKS怎么将中间格式的模具装配体转化为装配体格式

模具是工业生产中用于制作成型物品的工具&#xff0c;它由各种零件构成&#xff0c;可以通过改变所成型材料的物理状态来实现物品外形的加工。如果工程师已经有其他格式的模具装配体&#xff0c;但是又想将其他格式的模具装配体导入solidworks里面&#xff0c;并且将一个个实体…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十 简单视频浮雕画效果

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十 简单视频浮雕画效果 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十 简单视频浮雕画效果 一、简单介绍 二、简单视频浮雕画效果实现原理 三、简单视频浮雕画效果…

情怀无价:重拾记忆的魅力——照片质量修复探究(上)

在当今数字时代&#xff0c;我们与照片的关系愈发密切。照片不仅是记录生活中珍贵瞬间的工具&#xff0c;更是承载情感和回忆的载体。然而&#xff0c;时间的流逝和技术的限制常常让我们的照片变得模糊、损坏&#xff0c;甚至失去了原本的色彩和细节。如何让这些珍贵的照片重现…

C++的并发世界(七)——互斥锁

0.死锁的由来 假设有两个线程T1和T2&#xff0c;它们需要对两个互斥量mtx1和mtx2进行访问。而且需要按照以下顺序获取互斥量的所有权&#xff1a; -T1先获取mte1的所有权,再获取mt2的所有权。 -T2先获取 mtx2的所有权。再铁取 mtx1的所有权。 如果两个线程同时执行&#xff0c…

在线预约小程序怎么做

在快节奏的现代生活中&#xff0c;无论是预约理发、还是预定餐厅&#xff0c;亦或是挂号就医&#xff0c;我们都希望有一个更加便捷、高效的方式来完成这些任务。而今&#xff0c;随着科技的发展&#xff0c;一款全新的在线预约小程序应运而生&#xff0c;为我们的生活带来了前…

程序猿之路

我接触计算机算对自己来说是比较晚的了&#xff0c;上初中的时候就有微机课&#xff0c;但是在那个小县城&#xff0c;上课也只是3个人共用一个电脑&#xff0c;我初中整个过程只会开关机&#xff0c;哈哈&#xff0c;虽然学过word&#xff0c;但是无奈&#xff0c;我插不上手呀…

机器学习 -- 端到端的机器学习项目

场景 我们将一个端到端的项目&#xff08;一个从开始到结束包含了所有必要步骤和组件的完整项目&#xff09;案例&#xff0c;步骤大概有&#xff1a; 1.观察大局。 2.获得数据。 3.从数据探索和可视化中获得洞见。 4.机器学习算法的数据准备。 5.选择和训练模型。 6.微调模型…

【简单讲解下Symfony框架】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…