PHP反序列化入门手把手详解
前言
本文内容主要分为三个部分:原理详解、漏洞练习和防御方法。这是一篇针对PHP反序列化入门者的手把手教学文章,特别适合刚接触PHP反序列化的师傅们。本文的特色在于对PHP反序列化原理进行了深入细致的分析,并提供了一系列由简入深的PHP反序列化习题,配以详细的练习和分析讲解。
序列化介绍
序列化是指将变量转换为一种可保存或传输的字符串形式的过程;
而反序列化则是在需要的时候,将这个字符串重新转换回原来的变量形式以供使用。
这两个过程相辅相成,为数据的存储和传输提供了极大的便利,同时也使得程序更加易于维护和扩展。
例子
将一大段对象序列化压缩成字符串.然后根据要求反序列化重新构造对象.(②是序列化的格式,下文详解)
代码语言:javascript复制class Person{ public $name; //public 修饰的这个成员在任何地方都可以使用 private $age; //private 修饰的成员只能被 其所在类 的其他成员访问 protected $sex; //protected 修饰的类成员 所在类的子类以及同一个包内的其他类 访问 function sayName() { echo $this->name; } function sayAge() { echo $this->age; } function saySex() { echo $this->sex; } function __construct($name, $age,$sex) { $this->name = $name; $this->age = $age; $this->sex = $sex;//protected修饰的sex }}$person=new Person('张三',20,'boy');$person->sayName();//张三$person->sayAge();//20$person->saySex();//boyecho '</br>';// 序列化:serialize将php的遍历变量(数组、对象等)转化成一个 可以存储或传输的字符串 表示的函数。即---对象压缩成字符串echo serialize($person);//O:6:"Person":3:{s:4:"name";s:6:"张三";s:11:"Personage";i:20;s:6:"*sex";s:3:"boy";}echo "</br>";// 因为我们需要使用url进行测试,所以将这个转化后的字符串进行url编码,便于之后进行反序列化测试echo urlencode(serialize($person));//O:6:"Person":3:{s:4:"name";s:6:"张三";s:11:" Person age";i:20;s:6:" * sex";s:3:"boy";}
get.php进行反序列化,将上面进行url编码的内容传到这个php,进行反序列化(将字符串还原成对象)
代码语言:javascript复制<?php$html =unserialize($_GET['html']);echo $html;
在上面的代码中我们可以看到序列化之后的内容为,将其进行分段详细解析
代码语言:javascript复制O:6:"Person":3:{s:4:"name";s:6:"张三";s:11:"Personage";i:20;s:6:"*sex";s:3:"boy";}O : 自定义对象 object6 : 类名的长度:3 : 3个成员属性s:4 : 你的成员属性名 长度为4 ,并且是一个字符串 strings:3 : 刚刚那个成员属性对应的值 是string类型,并且长度是3位s:11:"Personage" : 因为该属性是私有属性,所以需要在属性名前加上类名,方便我们进行反序列化的时候的识别.i:20 : 20是age的属性值 , i是代表 integer类型s:6:"*sex"; sex这个属性是一个受保护的属性,特征就是 * 号s:3:"boy : 代表 string类型,属性值长度为3位 boy对应是 sex的属性值
private和 protected详解
代码语言:javascript复制//protected举例class Animal{ protected $name; //构造函数,即当你创建一个新对象时,这个方法会自动被调用,用于被初始化对象。 //构造函数可以接收参数,这些参数可以用来设置对象的初始状态。 public function __construct($name) { $this->name = $name; } protected function getName() { echo $this->name ." 小羽网安"; }}///extends继承class Dog extends Animal{ public function __construct($name) { //调用父类的构造函数 parent::__construct($name); }// public function introduce()// {// //调用父类的eat方法// parent::getName();// echo $this->name ." Dog类别的输出";// } public function getDog() { $this->getName();//调用继承类的getName方法 echo '<br/>继承之后,继续调用的函数'; }}$myDog=new Dog("<br/>hellow");$myDog->getDog(); //hellow 小羽网安<br/>继承之后,继续调用的函数$myName=new Animal("游不动的小鱼丶");//$myName->getName();//无法从外部访问这个成员,Fatal error: Uncaught Error: Call to protected method Animal::getName() from context //$myDog->getName();//无法从继承之后的类访问这个成员Fatal error: Uncaught Error: Call to protected method Animal::getName() from context?>
PHP在序列化含有private和protected权限的变量时,会在变量名前添加ASCII码为0的不可见字符,表现为