序列化基础知识
序列化的作用
序列化(serialization)是将对象的状态信息 (属性) 转化为可以存储或传输的形式的过程
对象 ———— >序列化 —————-> 字符串
将对象或者数组转化为可储存/传输的字符串。
在php中使用函数serialize()来将对象或者数组进行序列化,并返回一个包含字节流的字符串来表示。
表达方式
可以看到是个N;
后面这个分号一定要的记得 ,
**数组序列化: **
1 |
|
先出现 数组 下标为0 的 数值
0 下标为 abc ;
a:3:{i:0;s:3:”abc”;i:1;s:3:”def”;i:2;s:3:”jhk”;}
解释 :
a array :3 参数数量 :{i:0 编号 ;s:3 字符型;长度:”abc”;i:1;s:3:”def”;i:2;s:3:”jhk”;}
对象序列化
序列化内容
O:4:”test”:1:{s:3:”pub”;s:6:”benben”;}
不能序列化‘类’可以序列化′对象’
对象序列化 不会序列化方法 ,只会序列化成员属性和他对应的值;
解释 :
O object :4 类名长度 :”test” 类名 :1 变量数量:{s:3 变量名字长度 :”pub” 变量名字 ;s:6 值的长度 :”benben” 变量值;}
增加一个 他也会随之增加
**私有属性 : **
private私有属性序列化时
在变量名前加”url编码之后的%00类名%00”
这里为什么是9 个呢
因为在类名前后都要加一个%00
%00 为空代表一个字符
O:4:”test”:1:{s:9:”%00testpub%00”;s:6:”benben”;}
受保护属性序列化 :
protected受保护属性序列化时,在变量名前加”%00*%00”
O:4:”test”:1:{s:6 变量名长度:”00pub”;s:6:”benben”;}
加了00 所以是6个
成员属性调用对象 :
O:5:”test2”:1:{s:3:”ben”;O:4:”test”:1:{s:3:”pub”;s:6:”benben”;}}
去new 一个test2()的时候 就已经把 test() 序列化了
去调用test2 对应的 成员属性是ben 但是ben对应的 是 一个完整的object 对象 赋值给ben 了
再来一个列子
实例化后的对象$a的成员变量’ben’调用实例化后的对象$b
反序列化
反序列化的作用
将序列化后的参数还原成实例化的对象
这样就拿到了个序列化
O:4:”test”:3:{s:1:”a”;s:6:”benben”;s:4:”*b”;i:666;s:7:”testc”;b:0;}
反序列化:
这里要将序列化的内容 , 受保护的 和私有的 类名要加上%00
再对其进行urldecode 进行解码
然后再进行反序列 (unserialize)
1 |
|
这是反序列化后的内容 和 还没有序列化的数据是一样的
反序列化生成的对象里的值,由反序列化里的值(字符串$a)提供;与原有类预定义的值无关;
意思就是原类里面的值是可以随便修改的
例如
现在 0 是flase 我们该成true 然后再修改一下数据
完全是可以修改的
调用成员方法
$f->displayVar();
调用的是 $d里面的成员属性
所属的值就 不是 benben 而是 abcdef
反序列化不改变类的成员方法;需要调用方法后才能触发;
反序列化例题
定义 test 类
定义了 $a 的 一个成员变量 输出一个 this istest!!
然后还有一个动作 ,displayVar
里面有一个eval 函数 (危险函数 ) 可以执行命令
存在一个 可控变量 benben
然后 对传进来的值进行反序列化 , 再赋值给 $b 去调用了 test类里面的 displayVar()
就是这么个过程
但是由于benben 可以构造
$b把字符串$get反序列化为对象,
通过更改字符串可改变得到的对象中$a的值,通过调用方法触发可控代码
构建payload :
序列化后的内容 :
O:4:”test”:1:{s:1:”a”;s:10:”phpinfo();”;}
然后去把序列化的内容 给 ?benben 就可以执行phpinfo();http://localhost:8002/class06/index.php?benben=O:4:"test":1:{s:1:"a";s:10:"phpinfo();";}
这样就执行了反序列化 执行 php命令