作者:Eason_LYC
悲观者预言失败,十言九中。 乐观者创造奇迹,一次即可。
一个人的价值,在于他所拥有的。可以不学无术,但不能一无所有!
技术领域:WEB安全、网络攻防
关注WEB安全、网络攻防。我的专栏文章知识点全面细致,逻辑清晰、结合实战,让你在学习路上事半功倍,少走弯路!
个人社区:极乐世界-技术至上
追求技术至上,这是我们理想中的极乐世界~(关注我即可加入社区)

本专栏CTF基础入门系列打破以往CTF速成或就题论题模式。采用系统讲解基础知识+入门题目练习+真题讲解方式。让刚接触CTF的读者真正掌握CTF中各类型知识点,为后续自学或快速刷题备赛,打下坚实的基础~

目前ctf比赛,一般选择php作为首选语言,如读者不了解php的基本语法,请登录相关网站自学下基本语法即可,一般5-7天即可掌握基础。

目录

  • 1. 什么是PHP序列化和反序列化
    • 1.1 基础概念
    • 1.2 基础知识
    • 1.3 PHP反序列化漏洞的危害
    • 1.4 PHP反序列化漏洞的防御措施
  • 2. 知识点讲解
    • 2.1 类的访问修饰符
      • 2.1.1 public 公开的
      • 2.1.2 protected 受保护的
      • 2.1.3 private 私有的
    • 2.2. 相关函数和重要知识点
      • 2.2.1 基础定义
      • 2.2.2 相关函数及技巧知识点
        • `serialize(mixed $value)`
        • `unserialize(string $str): mixed`
      • 2.2.3 【技巧】urlencode 序列化结果
      • 2.2.4 【技巧】序列化引用R类型绕过比对
      • 2.2.5 PHP反序列化特点
  • 3. PHP常用魔术方法
    • 3.1 魔法函数汇总
    • 3.2 魔法函数使用示例

1. 什么是PHP序列化和反序列化

1.1 基础概念

  • PHP序列化是将一个PHP对象转换成一个字符串,以便在不同的应用程序之间传递和存储。
  • 反序列化是将序列化的字符串转换回PHP对象。攻击者可以通过构造恶意的序列化字符串来触发代码执行,这就是PHP反序列化漏洞的本质。
  • PHP序列化函数官方文档:https://www.php.net/manual/en/function.serialize.php
  • PHP反序列化函数官方文档:https://www.php.net/manual/en/function.unserialize.php

1.2 基础知识

序列化是将 PHP 对象转换为可存储或传输的字符串的过程。序列化后的字符串可以保存到文件或通过网络传输到其他计算机,在需要时可以反序列化为原始对象。

序列化的基本原理是将 PHP 对象转换为一组字符串,其中包含对象的属性和变量。序列化后的字符串可以被反序列化为原始对象,从而重新创建对象。

PHP 序列化可以使用 PHP 内置的 serialize() 函数进行。例如,以下代码将一个 PHP 对象序列化为字符串:

$object = new MyClass();
$string = serialize($object);

在上面的代码中,$object 是一个 MyClass 类的实例,serialize() 函数将其序列化为一个字符串,存储在 $string 变量中。

反序列化可以使用 PHP 内置的 unserialize() 函数进行。例如,以下代码将一个序列化的字符串反序列化为 PHP 对象:

$string = 'O:7:"MyClass":2:{s:3:"foo";s:3:"bar";s:3:"baz";i:123;}';
$object = unserialize($string);

在上面的代码中,$string 是一个序列化的字符串,unserialize() 函数将其反序列化为一个 MyClass 类的实例,存储在 $object 变量中。

需要注意的是,PHP 序列化只能序列化 PHP 对象,不能序列化资源、闭包等其他类型的数据。另外,由于序列化后的字符串包含对象的私有属性和方法,因此在反序列化时需要确保对象的类定义已经加载到内存中。

简单来说,就是将一个php对象转化为字符串保存(序列化),方便传输到远端后,在远端再还原成对象的一个过程(反序列化)。

1.3 PHP反序列化漏洞的危害

PHP反序列化漏洞可以导致远程代码执行,攻击者可以通过构造恶意的序列化字符串,将任意代码注入到应用程序中,从而实现控制服务器的目的。

简单说就是构造恶意的字符串(序列化),这样远端还原对象时(反序列化),就把恶意的对象还原并执行了。

1.4 PHP反序列化漏洞的防御措施

防御PHP反序列化漏洞的方法有多种,其中最重要的是对用户输入进行过滤和验证。此外,还可以使用PHP内置的序列化函数进行序列化和反序列化,而不是使用第三方库。

2. 知识点讲解

首先我们先看一个完整的PHP序列化和反序列化的代码

CTF中往往会直接给出代码,需要分析代码编制恶意字符串

2.1 类的访问修饰符

上图中定义了一个类Tree,类中前三行分别出现了public、private、protected,分别是什么意思呢?下面我们就来详细介绍下~·

  • 类内部:是指类定义的内部,即类名后大括号{ }内部。
  • 类外部:是指类定义的外部内容,即类名后大括号{}之外的所有地方。
  • 类成员的访问权限控制分为:内部访问(私有的private)。内部访问(受保护protected)和全部访问(公有public)。

2.1.1 public 公开的

公开的属性或函数,可在类内部、外部访问
public $name='BMW'
public function XXX{}

2.1.2 protected 受保护的

受保护的属性或函数,只能在类及其子类、父类间内部访问。若想在外部访问,需要设置引用方法。
protected $color='blue'

2.1.3 private 私有的

私有的属性或函数,只能在当前类的内部访问,若想在外部访问,需要设置引用方法。

比如上图中最后三个echo的调用,如下图可以看到,public可以正常调用,其余两个产生报错

2.2. 相关函数和重要知识点

2.2.1 基础定义

序列化的目的是方便对象的传输和存储。

  • 序列化

指将一个实例化的对象从一个实例转换为一个简短的序列化字符串,这样便于保存对象,可以将序列化字节存储到数据库或者文本当中。

  • 反序列化

是当需要的时候再通过反序列化将序列化字符串解析,获取保存的对象,直接调用,而不需要重新实例化一个类

在PHP应用中,序列化和反序列化一般用做缓存,比如session缓存,cookie等

2.2.2 相关函数及技巧知识点

serialize(mixed $value)

参数为需要序列化的对象、数组、字符串等。返回值类型为字符串,即序列化字符串。

unserialize(string $str): mixed

参数类型为字符串,也就是序列化字符串。返回值为反序列化得到的对象、数组、字符串等。

<?php
class Car{public $name='BMW';protected $color='blue';private $size='large';private $price;function __construct(){echo '序列化时调用构造方法<br>';}function __destruct(){echo '反序列化时调用析构函数<br>';}function show(){echo $this->name.'<br>';echo $this->color.'<br>';echo $this->size.'<br>';echo 'price:"'.$this->price.'"<br>';}
}$myCar = new Car();
$o = serialize($myCar);
print_r($o);
print_r("\n");
print_r(urlencode($o));
print_r("\n");$un_o = unserialize(urlencode($o));
print_r($un_o);?>// 序列化时调用构造方法
// O:3:"Car":4:{s:4:"name";s:3:"BMW";s:8:"*color";s:4:"blue";s:9:"Carsize";s:5:"large";s:10:"Carprice";N;}
// O%3A3%3A%22Car%22%3A4%3A%7Bs%3A4%3A%22name%22%3Bs%3A3%3A%22BMW%22%3Bs%3A8%3A%22%00%2A%00color%22%3Bs%3A4%3A%22blue%22%3Bs%3A9%3A%22%00Car%00size%22%3Bs%3A5%3A%22large%22%3Bs%3A10%3A%22%00Car%00price%22%3BN%3B%7D// 反序列化时调用析构函数

这段代码定义了一个名为Car的类,包含公共属性$name、受保护属性$color、私有属性$size和未定义初始值的私有属性$price,以及构造函数__construct()析构函数__destruct()和一个公共方法show(),用于输出属性的值。

在代码中,首先创建了一个Car类的实例$myCar,并将其序列化为字符串$o,然后打印输出$o和$o的URL编码形式。

$o=O:3:"Car":4:{s:4:"name";s:3:"BMW";s:8:"*color";s:4:"blue";s:9:"Carsize";s:5:"large";s:10:"Carprice";N;}
urlencode($o) = O%3A3%3A%22Car%22%3A4%3A%7Bs%3A4%3A%22name%22%3Bs%3A3%3A%22BMW%22%3Bs%3A8%3A%22%00%2A%00color%22%3Bs%3A4%3A%22blue%22%3Bs%3A9%3A%22%00Car%00size%22%3Bs%3A5%3A%22large%22%3Bs%3A10%3A%22%00Car%00price%22%3BN%3B%7D

接着,将URL编码后的字符串$o反序列化为一个新的对象$un_o,并打印输出$un_o。

在输出的过程中,构造函数__construct()被调用,输出序列化时调用构造方法,而析构函数__destruct()在反序列化时被调用,输出反序列化时调用析构函数。在调用show()方法时,只有公共属性$name和受保护属性$color被输出,而私有属性$size的值无法输出。

PHP序列化字符串的格式如下:
对象类型:长度:“类名”:类中变量的个数:{类型:长度:“值”;类型:长度:“值”;......}

这里的长度是指字符串长度 o表示对象,a表示数组,s表示字符,i表示数字

2.2.3 【技巧】urlencode 序列化结果

  • %00为空字符,占位1位。正常浏览器不会显示,但是在urlencode下会显示
  • private在序列化后会出现%00*%00(%00*%00color)
  • protected在序列化后出现 %00类名%00变量名(%00Car%00size)

为避免浏览器不显示空字段,导致反序列化不成功,使用序列化时采用url编码
$o = urlencode(serialize($myCar))

2.2.4 【技巧】序列化引用R类型绕过比对

序列化的时候可以通R类型值来保存变量的引⽤(指针)状态。

上述含义为:input值引用correct值的结果。保持key[correct] = key[input]

2.2.5 PHP反序列化特点

PHP在序列化保存类对象状态时,只保存其中的变量和类名等,并不会保存序列化时类的结构(不保存方法)。在反序列化时其实就是将序列化字符串中存储的变量,带入到当前上下文环境中寻找到的类,去重新实例化对象。

3. PHP常用魔术方法

3.1 魔法函数汇总

在面向对象编程中,PHP 提供了一系列的魔术方法,这些魔术方法为编程提供了很多便利,在 PHP 中的作用是非常重要的。PHP 中的魔术方法通常以__(两个下划线)开始,并且不需要显式的调用而是在某种特定条件下自动调用的。上文中介绍的构造函数 __construct() 在实例化对象时调用,析构函数__destruct()在销毁对象时自动调用。常用魔术方法如下:

__construct()  // 构造函数,在实例化对象时调用
__destruct()   // 析构函数,在销毁对象时调用
__call(string $function_name, array $arguments)  // 在对象中调用一个不可访问或不存在的方法时被调用
__callStatic() // 用静态方式中调用一个不可访问方法时调用
__get($name)   // 获取对象不存在的属性或无法访问的属性时调用.$name表示要获取的属性名
__set($name, $value) // 设置对象不存在的属性或无法访问的属性时调用.$name表示要设置的属性名,$value表示要设置的值
__isset()     // 当对不可访问属性调用isset()或empty()时调用
__unset()     // 当对不可访问属性调用unset()时被调用
__sleep()     // 执行serialize()时,先会调用这个函数
__wakeup()    // 执行unserialize()时,先会调用这个函数
__toString()  // 类被当成字符串时的回应方法  echo $obj;
__invoke()    // 以调用函数的方式调用一个对象时的回应方法  $person();
__set_state() // 调用var_export()导出类时,此静态方法会被调用
__clone()     // 当对象复制完成时调用
__autoload()  // 尝试加载未定义的类
__debugInfo() // 打印所需调试信息

反序列化时会默认调用的方法有:

  • __destruct()
  • __wakeup()

魔法函数介绍推荐文章:
PHP之十六个魔术方法详细介绍
PHP魔法方法/函数详解

3.2 魔法函数使用示例

下面这段代码,初学时也许看不明白,但其实含金量非常高,后续做题中,这个表要反复查看的~

<?php
# 设置⼀个类A
class A{private $name = "AS1def";function __construct(){echo "__construct() call\n";}function __destruct(){echo "\n__destruct() call\n";}function __toString(){return "__toString() call\n";}function __sleep(){echo "__sleep() call\n";return array("name");}function __wakeup(){echo "__wakeup() call\n";}function __get($a){echo "__get() call\n";return $this->name;}function __set($property, $value){ echo "\n__set() call\n";$this->$property = $value;}function __invoke(){echo "__invoke() call\n";}
}
//调⽤ __construct()
$a = new A();
//调⽤ __toSting()
echo $a;
//调⽤ __sleep()
$b = serialize($a);
echo $b;
//调⽤ __wakeup()
$c = unserialize($b);
echo $c;
//不存在这个abcd属性,调⽤ __get()
echo $a->abcd;
//name是私有变量,不允许修改,调⽤ __set()
$a->name = "pro";
echo $a->name;
//将对象作为函数,调⽤ __invoke()
$a();
//程序结束,调⽤ __destruct() (会调⽤两次__destruct,因为中间有⼀次反序列化)

输出结果如下:

__construct() call
__toString() call
__sleep() call
O:1:"A":1:{s:7:"Aname";s:6:"AS1def";}__wakeup() call
__toString() call
__get() call
AS1def
__set() call
__get() call
pro__invoke() call__destruct() call__destruct() call

以上就是PHP反序列化的基础知识,下一篇文章就在这些基础知识上,开始题目的练习~

CTF-PHP反序列化漏洞1-基础知识相关推荐

  1. 个php反序列化漏洞,PHP反序列化漏洞学习(一)

    前言:PHP反序列化也是web安全中常见的一种漏洞,这次就先来大致了解一下PHP反序列化漏洞的基础知识. 一.PHP序列化和反序列化 在学习PHP反序列化漏洞时,先来了解一下基础的知识. (一)PHP ...

  2. Python Pickle反序列化漏洞

    前言: 刷题的时候做了一道[CISCN2019]ikun的题目,提示考察的知识点是Python Pickle,之前接触的都是有关PHP反序列化,这次就来好好学习一下Python Pickle反序列化漏 ...

  3. 山东大学软件学院项目实训-创新实训-山大软院网络攻防靶场实验平台(十)-Java反序列化漏洞(2)

    目录 前言: 2.项目配置 3.编写"java 反序列化漏洞"后端代码 4.编写"java 反序列化漏洞"前端代码 5.运行测试 前言: 本篇文章在上一篇文章基 ...

  4. PHP反序列化漏洞-CTF实例

    PHP反序列化漏洞-CTF PHP反序列化漏洞-FIRST PHP反序列化漏洞-SECOND 1.CTF实例 CTF实例源码: strchr() 函数: 搜索字符串在另一字符串中的第一次出现,返回字符 ...

  5. 网络空间安全---漏洞基础知识

    目录 文章目录 前言 一.漏洞是什么: 二.漏洞产生的原因: 三.漏洞产生的原理.适用场景是什么.危害是什么.利用方法是什么.怎么防护: 四.哪些工具: 总结 前言 计算机网络安全问题是随着网络.特别 ...

  6. 风炫安全Web安全学习第三十九节课 反序列化漏洞基础知识

    风炫安全Web安全学习第三十九节课 反序列化漏洞基础知识 反序列化漏洞 0x01 序列化相关基础知识 0x01 01 序列化演示 序列化就是把本来不能直接存储的数据转换成可存储的数据,并且不会丢掉数据 ...

  7. ctf php沙箱,详谈CTF中常出现的PHP反序列化漏洞

    0x01什么是PHP序列化与反序列化 PHP序列化是一种把变量或对象以字符串形式转化以方便储存和传输的方法 在PHP中,序列化用于存储或传递 PHP 的值的过程中,同时不丢失其类型和结构. 比方来说, ...

  8. CTF基础知识及web

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 CTF基础知识 一.CTF简介 二.CTF赛事介绍 三.CTF竞赛模式 1.解题模式(Jeopardy) 2.攻防模式(At ...

  9. CTF基础知识与web信息泄露下的目录遍历、PHPINFO、备份文件下载

    文章目录 CTF基础知识 一.CTF简介 二.竞赛模式 三.比赛形式 四.题目类型 web信息泄露 一.目录遍历 二.PHPINFO 三.备份文件下载 (一)网站源码 (二)bak文件 (三)Vim缓 ...

最新文章

  1. 正则表达式、事件调用
  2. vbox 设置linux共享文件夹,Windows 7下设置VirtualBox中Linux共享文件夹
  3. SOA面向服务架构打包部署
  4. 优化嵌套查询 || 优化OR条件
  5. 5g应用场景_5G新媒体场景应用解决方案(ppt)
  6. ARMS为深绘智能系统保驾护航
  7. 实现电子词典_它是一部电子词典,一部翻译机,一部口语机还是一部出游的随身WiFi...
  8. 阿里云MVP陈磊:数字化转型驱动业务创新
  9. 豆瓣评分8.0以上数据分析R、MySQL、Python等书籍,45本包邮送到家
  10. CTRL-Space always toggles Chinese IME (Windows 7、10)
  11. P2P终结者和反P2P终结者如何使用
  12. 【Python】torrentParser1.01
  13. 理解二重积分的几何意义及公式
  14. java开发微信付款码支付
  15. 一种简单的业务数据监控告警设计方案
  16. java培训班值得去吗?
  17. WSDM 2021 | 时间序列相关论文一览
  18. java 使用poi生成excel
  19. echarts大屏可视化,HTML+CSS加载全国、或某一省市(安徽省)(各个省市县)地图
  20. linux 设备驱动 probe,Linux驱动模型Probe解惑

热门文章

  1. 塑料疑云还是认知返祖?从荣耀9X看大小手机厂商之间的天堑
  2. android:foreground
  3. 解决Ubuntu 20.04 播放视频,因缺少编解码器无法处理音频/视频流,以及解决‘因没有公钥,无法验证下列签名’问题
  4. autoware 1.14 lgvsl simulator仿真
  5. 数据库(笔记)——候选码、主码、外码以及关系的完整性
  6. 微型计算机的i3或i5一般指的是,英特尔i3、i5、i7分别相当于骁龙哪个层次的处理器?...
  7. 机器视觉-相机镜头光源介绍及选型-3.光源分类
  8. a标签和阻止事件冒泡
  9. 雾计算中的数据安全问题综述
  10. 在家里免费下载知网内的论文方法