php反序列化(小白学习心得)

首先问自己一个问题为什么要进行序列化与反序列化?
例如我们平时写的字符abcdef可以进行一个显示,但在网络上它是不能进行一个正常的传输的,所以序列化就是需要规定一种格式用来作用于网络的传输。

abcdef+空格,加了空格你看不到,你认为这里没有字符,但实际在url栏里它就是%20;
回车换行就是:%0a %0d;

php的序列化

php提供序列化和反序列化的函数serialize和unserialize,序列化之后的内容是简单的文本格式,但是对字母大小写和空白敏感(空
格,回车,换行)

序列化后字母标示及其含义:

a - array(数组),b-boolean(布偶类型),d-double(双精度浮点数),i-integer (整数),o- common object (对象,php4以后
被O取代了) , r-references (引用) .
s-string (字符串)O-class (类),N-null (空),R-pointer reference(指针),U-unicode string (unicode字符率,
php6才引入) ,C -custom object(自定义对象,php5引入)

N表示的是NULL,而b、d、i、 s表示的是四种标量类型,目前其它语言所实现的PHP序列化程序基本上都实现了对这些类型的序列化和反序列化,不过有—些实现中对s(字符串)的实现存在问题。
a、O属于最常用的复合类型,大部分其他语言的实现都很好的实现了对a的序列化和反序列化,但对О只实现了PHP4中对象序列化格式,而没有提供对PHP 5中扩展的对象序列化格式的支持。
r、R分别表示对象引用和指针引用

标量类型:
b:;
其中为0或1,当boolean型数据为false时,<digit为0,否则为1。bool类型的true和任何字符串弱类型比较为真
i:;
其中为一个整型数,范围为:-2147483648到2147483647。数字前可以有正负号,如果被序列化的数字超过这个范围,则会被序列化为浮点数类型而不是整型。如果序列化后的数字超过这个范围(PHP本身序列化时不会发生这个问题),则反序列化时,将不会返回期望的数值。
s::"";
其中是的长度,是非负整数,数字前可以带有正号(+)。为字符串值,这里的每个字符都是单字节字符,其范围与ASCII码的0 -255的字符相对应。每个字符都表示原字符含义,没有转义字符,两边的引号("")是必须的,但不计算在当中。这里的相当于一个字节流,而是这个字节流的字节个数。
d:;
其中为一个浮点数,其范围与PHP中浮点数的范围一样。可以表示成整数形式、浮点数形式和科学技术法形式。如果序列化无穷大数,则<number为INF,如果序列化负无穷大,则<number为-INF。序列化后的数字范围超过PHP能表示的最大值,则反序列化时返回无穷大(INF),如果序列化后的数字范围超过PHP所能表示的最小精度,则反序列化时返回0。
首先序列化的是对象是类本身,编号为1
R:1表示指针指向本身,2表示非本身的第一个参数,如果改变它的值将会把本身的类型改变表示对象在序列化中第一次出现的位置。
r;1表示引用对象本身,2表示非本身的第一个对象,如果改变它的值就只会改变引用对象的参数值。

<?php
class a{
    public $username='a' ;
    public $password='p';
    public $admin = '123';
    public function add(){
        echo "111";
    }
}
$b =new a();
$c = array('a','b');
echo serialize($c);
echo "<br />";
echo serialize($b);

运行结果:
a:2:{i:0;s:1:"a";i:1;s:1:"b";}<br />O:1:"a":3:{s:8:"username";s:1:"a";s:8:"password";s:1:"p";s:5:"admin";s:3:"123";}

php代码可以在网页上在线运行
在这里插入图片描述
r是个指针类型:1指向password本身,2指向前面的’a’也就是非本身的第一个数,3就是非本身的第二个数。

简单复合的序列化
4.1.数组的序列化
数组(array)通常被序列化为:
a:cn>:{<key 1><value 1><key 2><value 2> …}
其期<表示数组元素的个数,<key 1>、<key 2 .key i>表示数组下标,<value 1>、<value 2 …value n表示与下标相对应的数组元素的值。
仍如🅰️3:{:0;i:1,i:1;s:3:“123”;i:2;1:3,4.2.
4.2对象的序列化
对象(object)通常被序列化为:
0:clength .“class name> “.cn>:{(<field name 1><field value 1><field name 2><field value 2> …cfield name n>]
其中表示对象的类名的字符串长度。<>表示对象中的字段1个数。这些字段包括在对象所在类及其祖先类中用var、public、protected和private声明的字段,但是不包括static和const声明的静态字段。也就是说只有实例(instance)字段。
<liled name 1>、c<led name 2 …filed name n>表示每个字段的字段名,而<iled value 1>、<liled value 2 .…. .liled value n>则表示与字段名所对应的字段值。
字段名是字符串型,序列化后格式与字符串型数据序列化后的格式相同。
字段值可以是任意类型,其序列化后的格式与其所对应的类型序列化后的格式相同。例如:O:8:“stdClass”:3:{s:1:“c”;s:5:”$flag”;s:1:“d”;s:3:“123”;s:1:“f”;N;}
4.3.对象字段名的序列化
var和public声明的字段都是公共字段,因此它们的字段名的序列化格式是相同的。公共字段的字段名按照声明时的字段名进行序列化,但序列化后的字段名中不包括声明时的变量前缀符号S.
protected声明的字段为保护字段,在所声明的类和该类的子类中可见,但在该类的对象实例中不可见。因此保护字段的字段名在序列化时,字段名前面会加上
10*Y0
public声明不需要做任何添加
private声明的字段为私有字段,只在所声明的类中可见,在该类的子类和该类的对象实例中均不可见。因此私有字段的字段名在序列化时,字段名前面会加上
1010为声明这个私有类的类名
包含php漏洞的网站: https://bugs.php.net

php反序列化的原理
php的序列化函威: serialize (),反序列化函激数: unserialize ()序列化通俗的讲就是把一个对象变成可以传输的字符串
在这里插入图片描述
产生漏洞的原因:php的魔术方法
魔法函数一般以__开头,通常因为某些条件而触发不用我们手动调用
5个魔法函数:
_construct()当一个对象创建时被调用
destruct()当一个对象销毁时被调用
_toString()当一个对象被当作一个字符串使用
_sleep()在对象在被序列化之前运行
_wakeup将在序列化之后立即被调用

字符串逃逸问题
造成的原因;
字符过滤器放在序列化之后,替换字符串只会替换掉敏感字符串而不会里新修改字符丰的长度;从而导致后文被吃掉字符串导致逃逸或者
顶出亨符串导致逃逸。
; )作为结束,如果后面还有多余内容就不会解析。

过滤器:

1.多换少吃字符把zz替换为a
序列化过后的局部: s:5:“users”;s:3:“zz1”;s:4:“pass”;s:2:“1"11”;
变为s:5:“users”;s:3:“a1”;s:4: “pass”;s:2:11";
此时users的键值只有一个字符但是序列化的标识却有2个字符,也就是说第一个键值会往后吃掉一个字符,如我们能吃到pass前面的一个“,我们就可以自己构造想要的第二个键值对。
于是,需要吃掉的字符就是第一个键值的第二个”到第二个键的第一个“,就可以根据自己的需要构造想要的字符串了。
2.少换多,顶字符
把a换为zz:
s:5:“users”;s:1:“a”;s:4:“pass”;s:2:“11”;
s:5:“users”;s:1:“zz2zzzz s:4:“pass”;s:zzzz2zzzz2:“11”;zzzz”;s:4:“pass”;s:zzzzzzzz2:“11”;
例如我们需要构造的亨符—共有42个那么
s:1: " ax 42+需要的字符“(需要的字符里得闭合前面的”)
这个就可以顶出我们需要的字符,从而构造我们想要的序列化内容

核心: a的字符数+需要的字符数= a被替换后的字符数,这样就只会把a被替换掉的字符数解析完,后面的内容就可以是我们精心构
造的.(重点)
private修饰的变量反序列化后悔会变为(%00类名%00变量名)
public反序列化后内容啥也不加,就正常变量名
protected反序列化后的内容为%00*%00加变量名

不足之处还请师傅们指正!

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值