php反序列化(复习)(第一章)

因为最近在学java,学完基础知识想从Java的反序列化继续学习,借着这个机会来复习一下php的反序列化

一、序列化基础知识

1、序列化的定义

序列化(串行化):是将变量转换为可保存或传输的字符串的过程; 反序列化(反串行化):就是在适当的时候把这个字符串再转化成原来的变量使用; 这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性; 常见的php序列化和反序列化方式主要有:serialize,unserialize

2、表达方式

复制代码
<?php
  class Person
  {                                                                      
  public $name;        
public $age;        
public $sex;        

public function __construct($name="张三", $sex="男", $age=22)
  {      
    $this->name = $name;
    $this->sex = $sex;
    $this->age = $age;
  }
public function say()
  { 
    echo "我叫:" . $this->name . ",性别:" . $this->sex . ",年龄:" . $this->age;
  }                                                                                
}
$Person1 = new Person();
echo serialize(($Person1));

回显为

复制代码
O:6:"Person":3:{s:4:"name";s:6:"张三";s:3:"age";i:22;s:3:"sex";s:3:"男";}
O代表object
6代表对象名长度
Person代表对象名称
3代表对象中的变量个数
s和i等代表变量数据类型
s代表 string
i代表 int
变量是int型时,没有长度,不加引号
4代表变量名长度
name代表变量名

3.public、protected、private下序列化对象的区别

复制代码
php v7.x反序列化的时候对访问类别不敏感
public变量
直接变量名反序列化出来
protected变量
\x00 + * + \x00 + 变量名
可以用S:5:"\00*\00op"来代替s:5:"?*?op"
private变量
\x00 + 类名 + \x00 + 变量名

反序列化中s和S的区别

如果类型是s,会调用以下函数,简单来说就是将\解释成十六进制,来转成字符

复制代码
static zend_string *unserialize_str(const unsigned char **p, size_t len, size_t maxlen)
{
	size_t i, j;
	zend_string *str = zend_string_safe_alloc(1, len, 0, 0);
	unsigned char *end = *(unsigned char **)p+maxlen;

	if (end < *p) {
		zend_string_efree(str);
		return NULL;
	}

	for (i = 0; i < len; i++) {
		if (*p >= end) {
			zend_string_efree(str);
			return NULL;
		}
		if (**p != '\\') {
			ZSTR_VAL(str)[i] = (char)**p;
		} else {
			unsigned char ch = 0;

			for (j = 0; j < 2; j++) {
				(*p)++;
				if (**p >= '0' && **p <= '9') {
					ch = (ch << 4) + (**p -'0');
				} else if (**p >= 'a' && **p <= 'f') {
					ch = (ch << 4) + (**p -'a'+10);
				} else if (**p >= 'A' && **p <= 'F') {
					ch = (ch << 4) + (**p -'A'+10);
				} else {
					zend_string_efree(str);
					return NULL;
				}
			}
			ZSTR_VAL(str)[i] = (char)ch;
		}
		(*p)++;
	}
	ZSTR_VAL(str)[i] = 0;
	ZSTR_LEN(str) = i;
	return str;
}

二、反序列化特性

1、反序列化之后的内容为一个对象。

2、反序列化生成的对象里的值,由反序列化里的值提供,与原有类预定义的值无关。

3、反序列化不触发类的成员方法(成员函数)(魔术方法除外),需要调用方法后才能触发。

三、魔术方法的构造和解析

__construct() 类的构建函数

__destruct() 类的析构函数

__call() 在对象中调用一个不可以访问方法时调用

__callStatic() 用静态方式中调用一个不可以访问方法时调用

__get() 获得一个类的成员变量时调用

__isset() 当对不可访问属性调用isset()或empyt()时调用

__set() 设置一个类的成员变量时调用

__unset() 当对不可访问属性调用unset()时被调用

__sleep() 执行serialize()时,先会调用这个函数

__wakeup() 执行unserialize()时,会先调用这个函数

__toString() 类被当成字符串时的回应方法

__invoke() 调用函数的方式调用一个对象时的回应方法

__set_state() 调用var_export()导出类时,此静态方法被调用

__clone() 当对象复制完成时调用

__autoload() 尝试加载未定义的类

__debuginfo() 打印所需调式信息

1、什么是魔术方法

一个预定义好的,在特定情况下自动触发的行为方法。

2、魔术方法的作用

反序列化漏洞的成因:

反序列化的过程中,unserialize()接收的值(字符串)可控;

通过更改这个值(字符串),得到所需要的代码;

通过调用方法,触发代码执行。

魔术方法的作用就是在特定条件下自动调用相关方法,最终导致触发代码

3、魔术方法相关机制

1、触发机制(动作不同,触发的魔术方法也不同)

2、功能

3、参数(一些特殊魔术方法会传参)

4、返回值

四、常见的序列化格式

  1. 二进制格式
  2. 字节数组
  3. json字符串
  4. xml字符串
相关推荐
JJay.10 小时前
Android Kotlin 协程使用指南
android·开发语言·kotlin
BLUcoding11 小时前
Android 布局介绍
android
summerkissyou198711 小时前
android-蓝牙-状态和协议值总结及监听例子
android·蓝牙
徒 花11 小时前
数据库知识复习05
android·数据库
提子拌饭13313 小时前
番茄时间管理:鸿蒙Flutter 实现的高效时间管理工具
android·flutter·华为·架构·开源·harmonyos·鸿蒙
4311媒体网13 小时前
帝国CMS二次开发实战:精准实现“最新资讯”标识与高亮判断
android
BLUcoding14 小时前
Android 轻量级本地存储 SharedPreferences
android
冬奇Lab14 小时前
Camera HAL3 接口:Android 相机的真正底牌
android·音视频开发·源码阅读
sensen_kiss14 小时前
CAN302 Technologies for E-Commerce 电子商务技术 Pt.6 市场营销与SEO(搜索引擎优化)
android·学习·搜索引擎
菜鸟国国15 小时前
Compose + Koin ViewModel 实战完全手册
android