何为序列化?
了解反序列化漏洞前,先简单了解一下什么是序列化?
这里拿PHP序列化来举例:
PHP允许保存一个对象方便以后重用,这个过程被称为序列化。
为什么要有序列化这种机制呢?
在传递变量的过程中,有可能遇到变量值要跨脚本文件传递的过程。试想,如果为一个脚本中想要调用之前一个脚本的变量,但是前一个脚本已经执行完毕,所有的变量和内容释放掉了,我们要如何操作呢?难道要前一个脚本不断的循环,等待后面脚本调用?这肯定是不现实的。serialize和unserialize就是用来解决这一问题的。serialize可以将变量转换为字符串并且在转换中可以保存当前变量的值;unserialize则可以将serialize生成的字符串变换回变量。
这是一个简单的php序列化的代码:
1 <?php 2 class Hello{ 3 var $test = '123'; 4 } 5 $class1 = new Hello; 6 $class1_ser = serialize($class1); 7 print_r($class1_ser); 8 ?>
运行结果 => 调试运行一下代码后就会将$test这个变量进行serialize序列化转换为字符串的形式保存:
输出结果:O:5:"Hello":1:{s:4:"test";s:3:"123"},各个字符的意义:
这里的O代表存储的是对象(object),假如你给serialize()传入的是一个数组,那它会变成字母a。5表示对象的名称有5个字符。"Hello”表示对象的名称。1表示有一个值。{s:4:"test";s:3:“123";}中,s表示字符串,4表示该字符串的长度,“test"为字符串的名称,之后的类似。
PHP反序列化漏洞
PHP反序列化漏洞也叫PHP对象注入,是一个非常常见的漏洞,这种类型的漏洞虽然有些难以利用,但一旦利用成功就会造成非常危险的后果。
PHP反序列化漏洞的形成的根本原因是程序没有对用户输入的反序列化字符串进行检测,导致反序列化过程可以被恶意控制,进而造成代码执行、getshell等一系列不可控的后果。反序列化漏洞并不是PHP特有,也存在于Java、Python等语言之中,但其原理基本相通。
PHP反序列化漏洞简单利用方式
PHP反序列化漏洞构造的代码如下:
1 <?php 2 class Hello{ //定义一个类 3 public $test = '123'; //类中声明变量 4 function __wakeup() //反序列化之前进行的回调函数 5 { 6 $jieguo = fopen("shell.php","a+"); //读写方式打开shell.php,将文件指针指向文件末尾 7 fwrite($jieguo,$this->test); //把变量test的反序列后的结果写入到shell.php文件中 8 fclose($jieguo); //关闭打开的shell.php文件 9 } 10 } 11 $classX = $_GET['test']; //通过URL输入序列化的字符串参数传递给test变量 12 print_r($classX); 13 echo "<br />"; 14 @$classX_unser = unserialize($classX); //进行一个反序列化过程 15 include "shell.php"; //为显示效果,把shell.php包含查看输出结果 16 ?>
fanxulie.php(PHP反序列化漏洞构造的代码文件)和shell.php(反序列后的结果写入的文件)
在URL输入序列化的字符串参数传递给test变量,输入参数回车后进行反序列的过程,并在网页中显示输出shell.php结果
shell.php成功写入反序列化后的结果
利用拓展:
既然可以在URL中可以控制输入构造的序列化的字符串参数,那么构造反序列字符串为PHP一句话木马执行并写入到文件中,就可以成功写入shell到文件中,进而可以拿shell的操作
在URL输入序列化的字符串参数为PHP一句话木马,并在网页中显示输出shell.php结果
shell.php成功写入反序列化后的PHP一句话木马的结果
此时用菜刀来连接写入PHP一句话木马的shell.php,成功连接拿到shell
本次只在本地进行一个简单的PHP反序列化的利用,现实中除了PHP语言外,Java、Python等语言之中也同样存在反序列化漏洞。如果反序列化漏洞一旦利用成功,就会造成非常危险的后果,可以通过构造恶意的输入进行文件上传、命令执行、远程代码执行等漏洞利用。