【web漏洞】PHP反序列化

2023-11-10

知识点

  • 序列化(serialize): 对象的状态信息转换为可以存储或传输的形式的过程 在序列化期间,对象将当前的状态写入到临时或持久性的存储区【将状态信息保存为字符串】。
  • 反序列化(unserialize): 将字符串转换为状态信息 序列化 <—>反序列化。
  • 构造POP链:通过用户可控的反序列化操作,其中可触发的魔术方法为出发点,在魔术方法中的函数在其他类中存在同名函数,或通过传递,关联等可以调用的其他执行敏感操作的函数,然后传递参数执行敏感操作,即

用户可控反序列化→魔术方法→魔术方法中调用的其他函数→同名函数或通过传递可调用的函数→敏感操作

  • PHP反序列化只能修改成员变量的值和构造方法,其他的代码区不能修改
  • (1)属性声明是由关键字public,protected或者private开头,然后跟一个普通的变量声明来组成。 属性中的变量可以初始化,但是初始化的值必须是常量。所以修改属性值时,不能修改成属性=对象。

序列化的内容只有类名和成员变量,所以可控点是,类名和成员变量的值。
通过控制类名、可以指定反序列化的类,通过控制变量的值,就可以影响代码执行流程。然后按照我们的期望,将这些“影响”连接在一起,就可以控制代码的执行。

  • 序列化之后的字符串构成:
    序列化的内容只有类名和成员变量 成员方法不会被序列化

  • 在序列化时,会执行构造函数,所以就可以通过构造函数来控制各属性的值,得到我们想要属性值然后序列化这些属性值

在这里插入图片描述多加了几个方法,最后输出的还是一样的:
在这里插入图片描述但是添加构造方法之后,序列化的值就改变了,因为序列化的过程会新建对象,新建对象就会调用构造函数:
在这里插入图片描述

<?php
class key{
    public $a="abc";
    public $b=123;
    public function __construct(){
        $this->a="flag{123456}";
        $this->b=new key1();
    }
}
class key1{}
echo serialize(new key());
//O:3:"key":2:{s:1:"a";s:12:"flag{123456}";s:1:"b";O:4:"key1":0:{}}
类型 结构
String s:size:value;
Integer i:value;
Boolean b:value;(保存1或0)
Null N;
Array a:size:{key definition;value definition;(repeated per element)}
Object O:strlen(object name):object name:object size:{s:strlen(property name):property name:property definition;(repeated per property)}
  • 想象自己是一个特工,你的目标是监控一个重要的人,有一天你怀疑目标家里的窗子可能没有关,于是你上前推了推,结果推开了,这是一个POC。之后你回去了,开始准备第二天的渗透计划,第二天你通过同样的漏洞渗透进了它家,仔细查看了所有的重要文件,离开时还安装了一个隐蔽的窃听器,这一天你所做的就是一个EXP,你在他家所做的就是不同的Payload,就把窃听器当作Shellcode吧!

反序列化常用方法:

__wakeup() //执行unserialize()时,先会调用这个函数
__sleep() //执行serialize()时,先会调用这个函数
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据或者不存在这个键都会调用此方法
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把类当作字符串使用时触发
__invoke() //当尝试将对象调用为函数时触发

序列化的(构造payload)运行顺序

<?php
class A{
    public  $a=11;
    public function  __construct($b){  //2
        $this->a=$b;
        echo "A构造函数\n";
    }
    public function __wakeup(){
        echo "A苏醒函数\n";
    }
    public function  __destruct(){  
        echo "A析构函数first\n";        //3
        echo $this->a."aaa\n";
        echo "A析构函数second\n";       //5
    }
}
class B{
    public $x=1;
    public function  __construct($b){  //1
        $this->x=$b;
        echo "B构造函数\n";
    }
    public function  __toString(){     //4
        return "flag{a_b_c}";
    }
    public function  __destruct(){
        echo "B析构函数\n";    		   //6
    }
}
echo urlencode(serialize(new A(new B("Aa"))));
//O:1:"A":1:{s:1:"a";O:1:"B":1:{s:1:"x";s:2:"Aa";}}
//O%3A1%3A%22A%22%3A1%3A%7Bs%3A1%3A%22a%22%3BO%3A1%3A%22B%22%3A1%3A%7Bs%3A1%3A%22x%22%3Bs%3A2%3A%22Aa%22%3B%7D%7D
//先执行每个对象的构造函数,再执行析构函数
//结果:
//B构造函数
//A构造函数
//A析构函数first
//flag{a_b_c}aaa     (只要在构造payload的时候打印出了我们想要的东西,就是构造成功了)
//A析构函数second
//B析构函数
  • 运行顺序:

serialize()之后,依次执行:

__construct()
__toString()(如果被特定条件触发了)
__destruct()

析构方法在所有的代码被执行结束之后进行

反序列化的(实现payload)运行顺序

<?php
<?php
class A{
    public  $a=11;
    public function  __construct($b){
        $this->a=$b;
        echo "A构造函数\n";
    }
    public function __wakeup(){
        echo "A苏醒函数\n";             //1
    }
    public function  __destruct(){
        echo "A析构函数first\n";        //2
        echo $this->a."aaa\n";        
        echo "A析构函数second\n";       //4
    }
}
class B{
    public $x=1;
    public function  __construct($b){
        $this->x=$b;
        echo "B构造函数\n";
    }
    public function  __toString(){
        return "flag{a_b_c}";         //3
    }
    public function  __destruct(){
        echo "B析构函数\n";            //5
    }
}
unserialize($_GET[1]);
//echo urlencode(serialize(new A(new B("Aa"))));
//O:1:"A":1:{s:1:"a";O:1:"B":1:{s:1:"x";s:2:"Aa";}}
//1=O%3A1%3A%22A%22%3A1%3A%7Bs%3A1%3A%22a%22%3BO%3A1%3A%22B%22%3A1%3A%7Bs%3A1%3A%22x%22%3Bs%3A2%3A%22Aa%22%3B%7D%7D
//先执行wakeup函数,再执行触发了的toString函数,最后执行析构函数,就算用到了构造函数改变的值,也**不会主动去执行构造函数**
//结果:
//A苏醒函数
//A析构函数first
//flag{a_b_c}aaa
//A析构函数second
//B析构函数
  • 运行顺序:

unserialize()之后,依次执行:

__wakeup()
__toString()(如果被特定条件触发了)
__destruct()

析构方法在所有的代码被执行结束之后进行

绕过__wakeup()

  • 因为unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。__destruct()析构最后执行。所以有时执行wakeup的时候防止wakeup干坏事,我们就要绕过wakeup()函数:
PHP版本:
php5 < 5.6.25
php7 < 7.0.10

把类的属性值加1即可绕过wakeup:

O:5:"hello":1:{s:5:"test4";s:11:"hello,world";}

换成

O:5:"hello":2:{s:5:"test4";s:11:"hello,world";}

在这里插入图片描述

__tostring()

  • __toString 触发的条件比较多,也因为这个原因容易被忽略,常见的触发条件有下面几种
(1)echo ($obj) / print($obj) 打印时会触发

(2)反序列化对象与字符串连接时

(3)反序列化对象参与格式化字符串时

(4)反序列化对象与字符串进行==比较时(PHP进行==比较的时候会转换参数类型)

(5)反序列化对象参与格式化SQL语句,绑定参数时

(6)反序列化对象在经过php字符串函数,如 strlen()addslashes()(7)in_array()方法中,第一个参数是反序列化对象,第二个参数的数组中有toString返回的字符串的时候toString会被调用

(8)反序列化的对象作为 class_exists() 的参数的时候

由于是私有属性,他有自己特殊的格式会在前后加两个 %00 ,所以我们在传输过程中绝对不能忘掉. 反序列化字符串中存在 \x00字符,这个其实是类的私有属性反序列化后的格式,protected 属性也有自己的反序列化格式

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【web漏洞】PHP反序列化 的相关文章

  • PHP7构造函数类名

    我有一个 Laravel 4 2 应用程序 它可以与 PHP5 一起使用 没有任何问题 由于我安装了一个运行 PHP7 的新 vagrant box 一旦我运行一个模型 其中函数名称与类名称 关系函数 相同 就会出现错误 如下所示
  • Android GCM 服务器的 API 密钥

    我有点困惑我应该为 GCM 服务器使用哪个 API 密钥 在文档中它说使用 android api 密钥 这对我不起作用并且总是给出未经授权的 http developer android com google gcm gs html ht
  • 未捕获的异常“Google_IO_Exception”,消息为“HTTP 错误:无法连接”

    我有一个任务 查询 运行一些从 gmail 邮箱检索数据的 php 代码 直到上周五 2015 年 4 月 10 日 它一直工作正常 现在我收到以下错误日志 E 11 58 26 094 2015 04 15 200 3 38 KB 14
  • 通过JS Laravel访问存储目录

    有没有办法访问storage目录 该目录已经链接到publicJS 中的目录 我正在尝试制作一个上传图片的表单 验证脚本 if request gt hasFile photos marker gt photos request gt ph
  • 将数组拆分为特定数量的块

    我知道array chunk 允许将数组拆分为多个块 但块的数量根据元素的数量而变化 我需要的是始终将数组拆分为特定数量的数组 例如 4 个数组 以下代码将数组分为 3 个块 两个块各有 2 个元素 1 个块有 1 个元素 我想要的是将数组
  • 如何从字符串中删除所有数字?

    我想删除字符串 0 9 中的所有数字 我写了这段有效的代码 words preg replace 0 words remove numbers words preg replace 1 words remove numbers words
  • 检查文件权限

    我怎样才能检查file permissions 无需通过运行操作系统特定命令passthru or exec Use 文件权限 http php net fileperms功能 clearstatcache echo substr spri
  • 如何在 Zend Framework 中处理移动设备?

    我接手了一个噩梦般的项目 我正在迁移一个写得很差的站点 并慢慢地将其迁移到 Zend Framework 应用程序中 不幸的是 我没有时间做补救工作 使这变得可以忍受 也许是一个或两个模型 我现在被告知该网站很快就会有移动版本 建议是克隆旧
  • PHP - 扩展 __construct

    我想知道你是否可以帮助我 我有两个类 一个扩展了另一个 B 类将由各种不同的对象扩展 并用于常见的数据库交互 现在我希望 B 类能够处理其连接和断开连接 而无需来自 A 类或任何外部输入的指示 据我了解 问题是扩展类不会自动运行其 cons
  • PHPUnit\Framework\TestCase 和 Tests\TestCase 有什么区别?

    我注意到在示例测试中 这两个类是内置的 功能测试 gt use Tests TestCase 单元测试 gt PHPUnit Framework TestCase 两者有什么区别 在什么情况下您会使用其中一种 PHPUnit Framewo
  • 包含包含文件的 php 文件

    这是目录结构 global php includes class bootstrap php includes init php plugins myplugin php 这是这些文件中的代码 start php require inclu
  • 在一个后台为MYSQL的网站上集成搜索

    我有一个位置搜索website http www jammulinks com对于一个城市 我们首先收集该城市所有可能类别的数据 如学校 学院 百货商店等 并将其信息存储在单独的表中 因为每个条目除了名称 地址和电话号码外都有不同的详细信息
  • 如何让Gmail像加载进度条一样

    我想在页面的中心和顶部创建一个像 Gmail 一样的加载进度条 并适用于所有浏览器 这是基本代码
  • CSS 无法从带有 php“includes”的相对路径工作

    文件夹结构 index php includes header html css style css 我的主项目文件夹中有 2 个子文件夹 一个是名为 includes 的文件夹 另一个名为 css 我有我的 index php主文件夹中的
  • Windows iis 7.0 上的 APC 不稳定

    我的 IIS 非常不稳定 因为它总是由于某种与 APC 相关的原因而重新启动 服务器的规格如下 Intel R Xeon CPU 3GHZ 3GHZ 2GB RAM 64bit APC 和服务器规格 3 1 7 dev PHP Versio
  • phpinfo 说 php.ini 路径是 C:\Windows 但那里没有 php.ini

    我们正在尝试从 PHP5 切换到 PHP7 现在我们已经安装了 Apache 并且 PHP 可以运行了 然而 我们在php ini文件没有任何作用 Via phpinfo 我们意识到原因是Configuration File php ini
  • PHP 错误:“无法通过引用传递参数 2”

    我只是需要有关这个 PHP 错误的帮助 我不太明白 致命错误 无法在第 13 行 web stud openup inactivatesession php 中通过引用传递参数 2
  • 使用 fopen() 包装器创建 ZIP 文件

    如何使用以下命令创建 ZIP 文件fopen 包装器 http es php net manual en wrappers compression php 这显然是not道路
  • 使用“INSERT ... ON DUPLICATE KEY UPDATE”插入多条记录

    我的表结构 table marks 我的目标 我想用条件插入或更新多条记录 我目前正在通过此查询进行检查 第一步 SELECT FROM marks WHERE student 115 AND param 1 第二步 if records
  • 如何在 PHP 中从字符串类名实例化? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 如何创建返回方法名称的新实例 不幸的是我收到这个错误 错误 类名必须是有效的对象或字符串 这是我的代码 class Foo public f

随机推荐

  • Python爬虫逆向实战案例(五)——YRX竞赛题第五题

    题目 抓取全部5页直播间热度 计算前5名直播间热度的加和 地址 https match yuanrenxue cn match 5 cookie中m值分析 首先打开开发者工具进行抓包分析 从抓到的包来看 参数传递了查询参数m与f 同时页面中
  • 图常见算法-广度优先算法python实现

    广度优先算法 广度优先搜索 breadth first search BFS 该算法用于解决两类问题 1 节点A到节点B是否有路径 2 节点A到节点B的哪条路径最短 算法实现思想 图的建立使用了散列表 双端队列使用了deque 为了避免死循
  • 吴恩达深度学习编程作业 pytorch 版rnn时间序列

    import numpy as np import pandas as pd import matplotlib pyplot as plt import torch from torch import nn from torch auto
  • Pycharm无法导入第三方库终极解决方法!!!

    折磨了我两天 远程问人也无果 百度上的答案更是五花八门 却无一起作用 最终 在一次次尝试下得出解决方案 报错 重点看它的Proposed solution Make sure you use the correct version of p
  • Python分析《我们与恶的距离》豆瓣剧评

    Python分析 我们与恶的距离 豆瓣剧评 我们与恶的距离 是一部非常有深度的台剧 演员的演技无可挑剔 剧情编排也很新颖 而且逻辑严谨 剧情环环相扣 不拖泥带水 剧中出了很多火遍全网的台词 如 所以爱会消失 对不对 我们都是好人 不知道为什
  • 黑苹果升级到catalina 10.15.6问题

    配置 dell 9570 从catalina 10 15 4升级到 10 15 5 无任何问题 今天手贱 升级到10 15 6 问题来了 主要表现是 有时启动不成功 另外就是三指拖动窗口失效 发现xcode也升级了 可能需要重新编译 也许有
  • node.js操作mysql数据库和sql server数据库

    node js操作mysql数据库和sql server数据库 这一篇博客主要是数据库的 特别是sql server数据库 首先讲解mysql 因为mysql的操作并不复杂 所以讲解会很快 第一步 第一步肯定是导入模块 和配置配置项 con
  • 关于单舵轮AGV运动学模型整理笔记

    2 1 单舵机图画 2
  • Daily report和weekly report很重要

    7 Daily report和weekly report很重要很多程序员宁愿多写程序 也不愿意写report 觉得十分麻烦 而又无聊 但是Daily report weekly report真的非常的重要 首先report可以帮助你管理自己
  • 多个el-tab共用一个表单校验问题

    需求是这样的 有多项tab 切换不同的tab 显示的输入框是一样的 但有的tab需要必填 有的tab则不需要必填 效果图如下 带星号和不带星号
  • 西门子PN协议分布式IO模块

    BL200Pro版本支持OPC UA MQTT和Modbus TCP协议 分布式I O模块系统由于具有可靠度高 容易扩展 设置容易 网络布线方便等特性 适用于分散地区的应用 广泛应用于数据收集和各种控制 产品广泛应用于物联网 智慧工厂 智慧
  • 【进程间通信(三)】共享内存(system v)

    一 共享内存通信的实现原理 其实进程之间通信的本质就是让通信双方看见同一份内存 这样当这份内存的数据发生改变的时候 双方进程都能直接观察到结果 这份内存存放在共享数据区 由操作系统提供并维护 共享内存的特性是只会储存进程之间通信产生的临时变
  • 从Qt谈到C++(一):关键字explicit与构造函数

    原文 http blog csdn net guodongxiaren article details 24455653 主题 Qt 提出疑问 当我们新建了一个Qt的widgets应用工程时 会自动生成一个框架 包含了几个文件 其中有个ma
  • 关于sshd服务无法开启的问题集合

    SSHD服务开启问题集合 报错1 错误 systemctl restart sshd Failed to restart sshd service Interactive authentication required See system
  • 沈师 PTA 数据库题目及部分解析 第一章

    判断题 1 一个数据库只有一个模式和一个内模式 T 2 数据模型是由数据结构 数据操作和完整性约束三部分组成的 T 3 由于数据库中的数据是不断更新的 因此关系模式是相对变化的 F 解析 关系模式不会相对变化 变化的是实例 4 数据库中的数
  • linux中vim/gvim的安装与verilog,systemverilog语法高亮显示

    linux中vim gvim的安装参考如下链接 https blog csdn net Stone Age article details 47276995 utm source blogxgwz8 安装完后 在用户目录下vim和gvim都
  • SpringBoot集成redis

    一 下载安装redis 1 官网地址 https redis io 2 GitHub地址 https github com MicrosoftArchive redis tags 3 安装 自行安装 二 SpringBoot集成redis
  • 【odoo】创建带用户类型的odoo用户,基于xml

  • 3dmax卡顿、卡死 怎么解决?

    一般3dmax容易卡 主要有下面几个原因 1 Win10自带的微软输入法引起的 2 3dmax病毒引起的 3 3d场景太多垃圾引起的 4 模型太大 5 显卡驱动或显示模式不正确 如果是Win10自带的微软输入法引起的 只需要将Win10下面
  • 【web漏洞】PHP反序列化

    目录 知识点 反序列化常用方法 序列化的 构造payload 运行顺序 反序列化的 实现payload 运行顺序 绕过 wakeup tostring 知识点 序列化 serialize 对象的状态信息转换为可以存储或传输的形式的过程 在序