面相小白的php反序列化漏洞原理剖析

embedded/2024/11/8 21:47:39/

前言

欢迎来到我的博客

个人主页:北岭敲键盘的荒漠猫-CSDN博客

本文整理反序列化漏洞的一些成因原理

建议学习反序列化之前

先对php基础语法与面向对象有个大体的了解

(我觉得我整理的比较细致,了解这俩是个啥就行)

漏洞实战情况

这个漏洞黑盒几乎不会被发现,除非极少数个别特别奇葩离谱少见,或者有内鬼作祟,明摆着告诉你这里有个漏洞,你来打我的情况。

大多数是白盒审计得出。

序列化与反序列化概念

需求分析

这里假设我们有一个类对象,我们想要引用可以直接用文件导入。

但是假设我们想要传输这个类对象给其他主机。

我们不可能把整个类的代码都给复制然后发送。

这个时候就需要把他们转化为一种更能方便传输的形式。

这个过程成为序列化。

反序列化则是把序列的产物重新变为类对象

序列化

函数:

serialize()

序列化后的产物模式:

代码演示

php"><?php
class student{public $name="joker";private $age=11;public function sayhello(){echo "hellohello";}
}$a=new student();
$b=serialize($a);
echo $b;
?>

结果如下:

反序列化

函数:

unserialize()

 他就是反过来,能够把序列化的字符串转化为类对象可供使用。

代码演示

php"><?php
class student{public $name="joker";private $age=11;public function sayhello(){echo "hellohello";}
}$a=new student();
$b=serialize($a);
$c=unserialize($b);
$c->sayhello();
?>

结果如下:

反序列化漏洞的成因与复现

原理分析

目标执行类中本不能执行的eval等危险函数。

反序列化可以覆盖原本的变量值,所以可以帮住我们运行本不应该被运行的区域。

自拟案例演示

以下为一串代码。

php"><?php
class student{public $name="joker";public $age=11;public function runeval(){echo $this->age; //输出为19if ($this->age >= 18){system("ipconfig");  //原本不能执行的区域被执行}}
}$b=$_GET["x"];
$c=unserialize($b);
$c->runeval();
?>

代码解析

get传递一个x参数,然后把他反序列化,之后运行runeval方法。

类中,有name,age属性,以及一个方法。

方法输出age的值,并且当age>=18的时候就会执行

system

而朋友,system是个高危函数,这里是固定的ipconfig,如果这个参数可控,那么就是一个大漏洞。

但是age明显固定是11啊,根本不会执行system。这里就轮到反序列化漏洞登场。

漏洞利用过程

我们新建一个php文件

把上面类的php代码全复制过来。

php"><?php
class student{public $name="joker";public $age=11;public function runeval(){echo $this->age; //输出为19if ($this->age >= 18){system("ipconfig");  //原本不能执行的区域被执行}}
}$b=new student;$c=serialize($b);echo $c;
?>

接下来删减代码,仅保留我们要更改的地方

要尽量的减少对原代码运行的影响,防止功能错乱。

这里我们只需要改一个age属性值,让他能过检查即可,那么把age留下其余的全部删除

php"><?php
class student{public $age=19;
}$b=new student;$c=serialize($b);echo $c;
?>

然后下面给他序列化输出一下。

把这串序列化字符串作为x传入原先的地方。

这里对比一下源代码

php"><?php
class student{public $name="joker";public $age=11;public function runeval(){echo $this->age; //输出为19if ($this->age >= 18){system("ipconfig");  //原本不能执行的区域被执行}}
}$b=$_GET["x"];
$c=unserialize($b);
$c->runeval();
?>

runeval函数中输出age的地方输出了19

也就是说我们覆盖了原先的11

并且过了检查执行了system。

现在我们试想一下真实场景。

假如这个age是判断你是不是vlp呢?

这样能不能绕过?

对吧,这个就是反序列化漏洞的一个基础的攻击形式。

反序列化进阶操作

在开发中几乎一定会用一些构造方法,类中实例化其他类对象的操作。

而这些操作让我们有更大的操作空间,让这个实例化跟打内网一样在类中各种横向移动建立隧道。

构造方法玩法

开发中几乎类都会执行一些构造方法。

构造方法的特点就是实例化的时候直接执行!!!!

没错直接执行!!!

具体的魔术方法以及作用参考我的这篇文章(太多了。。。)

(有php面向对象基础的可以直接看下面,没有的话先仔细看这个魔术方法,不然看不懂下面是啥)

php反序列化常见魔术方法整理-CSDN博客

看我们之前的代码 

php"><?php
class student{public $name="joker";public $age=11;public function runeval(){echo $this->age; //输出为19if ($this->age >= 18){system("ipconfig");  //原本不能执行的区域被执行}}
}$b=$_GET["x"];
$c=unserialize($b);
$c->runeval();
?>

看下面类对象的实例化。

我们是直接传入然后手动执行了runeval。

但是如果不执行的话,那不就是一点办法没有了嘛。

所以如果他有构造方法,构造方法就会在反序列化的时候自动执行。

大大提升了我们的可玩性!!

看这个代码

php"><?php
class student{public $name="joker";public $age=11;public function __destruct(){echo "aa";echo $this->age; //输出为19if ($this->age >= 18){system("ipconfig");  //原本不能执行的区域被执行}}}$b=$_GET["x"];
$c=unserialize($b);
?>

仅仅进行了反序列化,并没有执行方法,但是类中有一个构造方法。

这个方法会在类结束的时候自动执行,所以不好意思,上一个payload依旧秒掉。

(注意一下实例化加个(),我上面给忘了。。。)

php"><?php
class student{public $age=19;
}$b=new student();$c=serialize($b);echo $c;
?>

pop链类跳跃

看下面代码

php"><?php
class student1{public $name="joker";public $age=11;public function getip(){echo system("ipconfig");}
}class student2{public $name;public $age;public function __toString(){echo "runing";$this->name->{$this->age}();
}
}$b=$_GET["x"];
$c=unserialize($b);
echo $c;
?>

这里有两个类,仅仅靠源代码,他们毫无关联。

很明显system在student1中

然而getip方法显然是没有被执行的。

student2有toString的方法,如果类对象被当做字符串处理则会执行。

而下面那个echo明显作为了字符串,所以能够执行toString。

然后里面的

$this->name->{$this->age}();

两个属性值都能够被反序列化恶意更改让他实例化为student1并执行函数。

所以

php"><?php
class student1{
}class student2{public $name;public $age="getip";
}$c=new student2();$z=new student1();$c->name=$z;$d=serialize($c);echo $d;
?>

结语

看到这应该就会了解php反序列化漏洞的一个工作原理了。

但还是老规矩绕过策略与特殊玩法写在别的博客中。

别问我为毛老说写一个完整体系结果又写别的去了。。。

因为我写的过程中遇到一个点攻不破我就想摆烂了。


http://www.ppmy.cn/embedded/135996.html

相关文章

正则表达式 - 简介

正则表达式 - 简介 正则表达式&#xff08;Regular Expression&#xff0c;简称Regex&#xff09;是一种用于处理字符串的强大工具&#xff0c;它允许用户通过特定的模式&#xff08;pattern&#xff09;来搜索、匹配、查找和替换文本中的数据。正则表达式广泛应用于文本编辑器…

在PHP中使用UTF-8编码防止乱码需要注意以下几点‌:

在PHP中使用UTF-8编码防止乱码需要注意以下几点‌&#xff1a; ‌设置PHP文档编码为UTF-8‌&#xff1a;在PHP代码的最开始使用header()函数设置文档的编码为UTF-8。例如&#xff1a;header("Content-Type: text/html; charsetutf-8");‌12。 ‌确保文件编码为UTF-8…

Docker 基础命令简介

目录 Docker 基础命令 1. Docker 版本信息 2. 获取 Docker 帮助 3. 列出所有运行中的容器 4. 运行一个新的容器 5. 查看容器日志 6. 停止容器 7. 启动已停止的容器 8. 删除容器 9. 列出所有镜像 10. 拉取镜像 11. 构建镜像 12. 删除镜像 13. 执行命令 14. 查看容…

Dubbo负载均衡

负载均衡策略与配置细节 Dubbo 内置了 client-based 负载均衡机制&#xff0c;如下是当前支持的负载均衡算法&#xff0c;结合上文提到的自动服务发现机制&#xff0c;消费端会自动使用 Weighted Random LoadBalance 加权随机负载均衡策略 选址调用。 如果要调整负载均衡算法…

wx.openSetting未调起小程序设置界面的坑

一、遇到的问题 调用wx.openSetting未调起小程序设置界面 二、最终使用的方案 解决后有一个问题,小程序设置页面同意授权后,快速返回页面点击开始录制按钮,小程序设置未生效期间,按钮无法点击;这种延迟暂时忽略吧 <view class="cm2 f1s n" bind:tap=&quo…

Python与Excel交互:pandas库安装及基本用法

在之前的文章中&#xff0c;我们探讨了Python处理Excel文件的基本概念&#xff0c;如工作簿、工作表以及单元格等。现在我们将转向具体的工具介绍——pandas库&#xff0c;它是Python中最常用的数据分析库之一&#xff0c;能够非常便捷地读取、处理和写入Excel文件。 安装pand…

计算机视觉和深度学习有什么区别

计算机视觉和深度学习是两个紧密相连但又有所区别的领域。以下是对这两个领域的详细比较&#xff1a; 定义与范畴计算机视觉&#xff1a;是人工智能的一个分支&#xff0c;涉及使用计算机及相关设备对生物视觉进行模拟的一种技术。它主要关注对图像和视频数据的理解和分析&…

Vue 计算属性和监听器

文章目录 一、计算属性1. 计算属性定义2. computed 比较 methods3. 计算属性完整写法 二、监听器1. 普通监听2. 添加额外配置项 一、计算属性 1. 计算属性定义 概念&#xff1a;基于现有的数据&#xff0c;计算出来的新属性&#xff0c;依赖的数据变化&#xff0c;自动重新计…