内网网站 建设目标,wordpress 强大,广州市研发网站建设多少钱,网页设计入门书籍为什么要序列化百度百科上关于序列化的定义是#xff0c;将对象的状态信息转换为可以存储或传输的形式(字符串)的过程。在序列化期间#xff0c;对象将其当前状态写入到临时或持久性存储区(非关系型键值对形式的数据库Redis#xff0c;与数组类似)。以后#xff0c;可以通过…为什么要序列化百度百科上关于序列化的定义是将对象的状态信息转换为可以存储或传输的形式(字符串)的过程。在序列化期间对象将其当前状态写入到临时或持久性存储区(非关系型键值对形式的数据库Redis与数组类似)。以后可以通过从存储区中读取或反序列化对象的状态重新创建该对象。在PHP中每个类的定义都以关键字class开头后面不仅跟着类名还跟着一对花括号里面包含有类的属性与方法的定义。一个类可以包含有属于自己的属性(常量:值变量的值不会改变、变量)和方法(函数)。由于类的实例化对象比较抽象不方便用于传输和存储。tips:类为class对象是object举例来说就是动物为一个大类大类之后再分小一类如猫猫或者狗狗而具体的某个动物就为一个对象。一个对象就相当于一个变量对象是一种语言结构。简单来说序列化就是把一个对象变成可以传输的字符串(字符串便于传输,只需要把字符串赋给变量即可)。在传递和保存对象时为保证对象的完整性和可传递性程序将对象转换为有序字节流以保存在本地文件中可以以特定的格式在进程之间跨平台、安全的进行通信。比如从java平台传递到php平台反序列化则根据字符串中保存的对象状态及描述信息通过反序列化重建对象。序列化的优点将对象转为字节流存储到硬盘上实际上是存放在数据库一般是redis数据库-键值对数据库当JVM停机的话字节流还会在硬盘上默默等待等待下一次JVM的启动把序列化的对象通过反序列化为原来的对象。序列化后的二进制序列能够减少存储空间永久性保存对象。序列化成字节流形式的对象可以进行网络传输。通过序列化可以在进程间传递对象实际上用Redis数据库作为缓存一般用于存储序列化后的字符串待字符串需要使用时再反序列化为对象方便调用。PHP中的序列化与反序列化反序列化漏洞并不是PHP特有也存在于Java、Python等语言之中但其原理基本相通。序列化与反序列化的定义序列化程序将对象状态转换为可存储或传输的字节序列的过程(即对象状态转换为可存储或者可传输的过程)序列化是对象转换为字符串的过程反序列化程序把存储或传输的字节序列恢复为对象的过程。反序列化则是字符串转化为对象的过程 如果字符串客户端可控就会造成web应用反序列化任意对象严重的是在反序列化的过程中会触发一些可以执行的php代码例如phpinfoPHP中的序列化与反序列化基本都是围绕serialize()和unserialize()两个函数展开的。在介绍这两个函数之前我们可以先看一个简单的例子。简单的例子我们可以用json格式数据的编码与解码(json格式就是格式化的字符串也就是说json格式的数据它具备一定的格式)来理解序列化与反序列化的过程。虽然json数据与反序列化漏洞没有什么关系但是这个例子有助于我们理解。代码内容如下?php
$studentarray(nameAJEST,age18,SEXtrue,score89.9);
// echo不能直接输出数组但是如果把$student给做一个json_encode 的格式转换,就可以用echo来输出
echo $student;
echo hr/;
$student_jsonjson_encode($student);
echo $student_json;
?我们定义一个数组数组属于抽象的数据结构为了方便跨平台传输数据可以将其进行json编码。json格式的数据是以键值对的形式出现的。类似于这种格式的数据易于处理易于传输。结果如下序列化与反序列化Demo序列化会将一个抽象的对象转换为字符串。我们可以写一个Demo来说明序列化的过程首先创建一个类代码内容如下?php
class student{public $name;public $sex;public $age;public $score;
}
?类名是student该类中有四个变量。接下来我们可以将这个类实例化也就是创建一个对象(new)并给对象中变量赋值。代码如下?php
// 定义一个student类类中有四个属性
class student{public $name;public $sex;public $age;public $score;
}// 创建对象1
$student1 new student();
$student1-name wyy;
$student1-sex false;
$student1-age 20;
$student1-score 95;
?最后我们使用serialize()将$student1这个对象序列化成一个字符串。这样的字符串就很容易传输和存储了。如下?php
// 定义一个student类类中有四个属性
class student{public $name;public $sex;public $age;public $score;
}// 创建对象1
$student1 new student();
$student1-name wyy;
$student1-sex false;
$student1-age 20;
$student1-score 95;// 创建对象2
$student2 new student();
$student2-name xcc;
$student2-sex true;
$student2-age 25;
$student2-score 98;// 输出wyy和xcc的成绩
echo $student1-name.s score .$student1-score;
// 进行换行
echo br/;
echo $student2-name.s score .$student2-score;// 用var_dump输出对象
echo hr/;
var_dump($student1);
var_dump($student2);// 对对象进行序列化并输出
echo hr;
echo 序列化后采用echo输出br;
echo serialize($student1);?打开浏览器访问该文件显示如下可以看到对象被序列化成字符串同样我们可以使用unserialize()函数将字符串反序列化成为一个对象。由于字符串中含有双引号所以此处可以使用定界符的方法定义字符串。代码如下?php
// 定义一个student类类中有四个属性
class student{public $name;public $sex;public $age;public $score;
}// 创建对象1
$student1 new student();
$student1-name wyy;
$student1-sex false;
$student1-age 20;
$student1-score 95;// 创建对象2
$student2 new student();
$student2-name xcc;
$student2-sex true;
$student2-age 25;
$student2-score 98;// 输出wyy和xcc的成绩
echo $student1-name.s score .$student1-score;
// 进行换行
echo br/;
echo $student2-name.s score .$student2-score;// 用var_dump输出对象
echo hr/;
var_dump($student1);
var_dump($student2);// 对对象进行序列化并输出
echo hr;
echo br;
// 序列化后采用echo输出
echo serialize($student1);
$str HTML
O:7:student:4:{s:4:name;s:3:wyy;s:3:sex;b:0;s:3:age;i:20;s:5:score;i:95;}
HTML;
echo hr/;
var_dump(unserialize($str));
?综上序列化→我们将对象序列化成字符串反序列化→我们将字符串反序列化成对象运行这个脚本文件我们可以看到反序列化后的对象PHP反序列化漏洞PHP反序列化漏洞也叫php对象注入是一个非常常见的漏洞这种类型的漏洞虽然有些难以利用但一旦利用成功就会造成非常危险的后果。漏洞的形成的根本原因是程序没有对用户输入的反序列化字符串进行检测导致反序列化过程可以被恶意控制进而造成代码执行、getshell等一系列不可控的后果。PHP中的序列化与反序列化基本都是围绕serialize()和unserialize()两个函数展开的。实验步骤实验一在网站根目录新建Code文件夹在Code文件夹中新建PHP文件夹再从PHP文件夹中新建Class文件夹最后在Class文件夹下新建文件unserialize.php文件内容如下?php
// 定义一个test类类中有4个属性未定义方法
class Test{public $strAJEST;;function _destruct(){// echo This is function_construct();eval($this-str);}
}// 创建对象并序列化后输出
$test new Test();
echo serialize($test);
echo hr/;
$t serialize($test);
var_dump(unserialize($t));
?打开浏览器访问该文件显示如下如下修改文件内容meta charset utf-8
?php
//定义一个stu类类中有4个属性暂未定义方法。
class test{public $strAJEST;function __destruct(){ // 在销毁对象时自动调用echo This is function __destruct();eval($this-str);}
}//创建对象并序列化后输出
$test new test();
echo 序列化后采用echo输出:br;
echo serialize($test1);
echo hr;//输入序列化后的字符串并采用凡序列化后采用var_dump输入
$obj$_GET[obj];
echo 反序列化后采用var_dump输出:br;
var_dump(unserialize($obj));
?继续打开浏览器访问该文件输入参数?obj?objO:4:test:1:{s:3:str;s:5:hello;},网页内容显示如下含有两句“ This is function __destruct()”说明函数被调用两次。注意当销毁实例化类对象的时候__destruct()函数会被自动调用接下来修改参数?objO:4:test:1:{s:3:str;s:10:phpinfo();;}网页显示如下可以看到phpinfo()函数被成功执行。由以上代码我们会发现PHP的反序列化漏洞学院与其他漏洞配合如代码执行SQLi等。我们输入的phpinfo()为何会作为PHP语句运行呢我们观察代码发现在类中有一个函数_destruct()并且这个函数调用的eval语句执行$this-str变量。为什么_destruct()没有被调用函数内的语句就会被执行呢我们发现当销毁实例化类(对象)的时候_destruct()函数会被自动调用并输出字符串[This is function_destruct()]。实验二将unserialize.php文件修改如下将new新建test类对象的语句注释掉再次实验meta charset utf-8
?php
//定义一个stu类类中有4个属性暂未定义方法。
class test{public $strAJEST;function __destruct(){echo This is function __destruct();eval($this-str);}
}//创建对象并序列化后输出
//$test1 new test();
//echo 序列化后采用echo输出:br;
//echo serialize($test1);
echo hr;//输入序列化后的字符串并采用凡序列化后采用var_dump输入
$obj$_GET[obj];
echo 反序列化后采用var_dump输出:br;
var_dump(unserialize($obj));在浏览器中输入参数?obj?objO:4:test:1:{s:3:str;s:5:hello;}网页显示如下含有1句This is function_destruct()说明函数被调用1次注意当销毁实例化类对象的时候__destruct()函数会被自动调用继续在浏览器中输入?objO:4:test:1:{s:3:str;s:10:phpinfo();;}网页显示如下可以看到同样能执行phpinfo()函数因此可以判断输入对象成功反序列化为test类对象并自动执行了__destruct()函数。实验三unserialize.php文件修改将最后一行语句修改如下实验如下meta charset utf-8
?php
//定义一个stu类类中有4个属性暂未定义方法。
class test{public $strAJEST;function __destruct(){echo This is function __destruct();eval($this-str);}
}//创建对象并序列化后输出
//$test1 new test();
//echo 序列化后采用echo输出:br;
//echo serialize($test1);
echo hr;//输入序列化后的字符串并采用凡序列化后采用var_dump输入
$obj$_GET[obj];
//echo 反序列化后采用var_dump输出:br;
//var_dump(unserialize($obj));
$obj1unserialize($obj);
?浏览器同样输入参数?objO:4:test:1:{s:3:str;s:5:hello;}网页显示如下含有1句“ This is function __destruct()”说明函数被调用1次。浏览器同样输入参数?objO:4:test:1:{s:3:str;s:10:phpinfo();;}访问网页显示如下可以看到同样能执行phpinfo()函数因此可以判断输入对象成功反序列化为test类对象并自动执行了__destruct()函数。tips:我们发现当销毁实例化类的时候__destruct()函数会被自动调用并输出字符串This is function__destruct()。默认情况下PHP仅仅释放对象属性所占用的内存并销毁对象相关的资源__destruct()允许你在使用一个对象之后执行任意代码来清除内存当PHP决定你的脚本不再与对象相关时__destruct()将被调用.在一个函数的命名空间内这会发生在函数return的时候对于全局变量这发生于脚本结束的时候如果你想明确地销毁一个对象你可以给指向该对象的变量分配任何其它值通常将变量赋值勤为NULL或者调用unset。PHP魔术方法归纳以[_]开头的方法是PHP中的魔术方法类中的魔术方法在特定情况下会被自动调用。主要魔术方法及其触发条件如下。魔术方法触发条件_construct()构造方法当一个对象被创建时调用_destruct()析构方法PHP将在对象被销毁前(即从内存中清除前)调用_autoload()使用尚未被定义的类时自动调用。通过此函数脚本引擎在PHP出错失败前有了最后一个机会加载所需的类。_call($method,$arg_array)在对象中调用一个不可访问方法时_callStatic()在静态上下文中调用一个不可访问的方法时使用_clone()使用clone方法复制一个对象时_invoke()当尝试调用函数的方式调用一个对象时_invoke方法会被自动调用_get($property)从不可访问的属性中读取数据_set($property,$value)给一个未定义的属性赋值时调用_isset($property)在一个未定义的属性上调用isset()函数时调用此方法_unset($property)在一个未定义的属性上调用unset()函数时调用此方法_toString()在将一个对象转化成字符串时自动调用_sleep()序列化对象前调用(其返回需要是一个数组)_wakeup()反序列化恢复对象前调用_set_state()当调用var_export()时这个静态方法就会被调用注意serialize() 检查类中是否有魔术名称 __sleep 的函数。如果这样该函数将在任何序列化之前运行。它可以清除对象并应该返回一个包含有该对象中应被序列化的所有变量名的数组。使用 __sleep 的目的是关闭对象可能具有的任何数据库连接提交等待中的数据或进行类似的清除任务。此外如果有非常大的对象而并不需要完全储存下来时此函数也很有用。相反地unserialize() 检查具有魔术名称 __wakeup 的函数的存在。如果存在此函数可以重建对象可能具有的任何资源。使用 __wakeup 的目的是重建在序列化中可能丢失的任何数据库连接以及处理其它重新初始化的任务。