php反序列化字符逃逸
php反序列化字符逃逸
php的序列化有几个特性
1.PHP 在反序列化时,底层代码是以
;
作为字段的分隔,以}
作为结尾(字符串除外),并且是根据长度判断内容的 .2.当长度不对应的时候会出现报错
3.可以反序列化类中不存在的元素
我们一般的序列化是这么操作的
1 |
|
所以我们知道反序列化函数是有一定读取的范围的,由里面的数字决定,同时必须要有对应的闭合符号
反序列化字符逃逸题目的特点
反序列化函数一般是先序列化,然后进行一个过滤函数,然后再进行一个反序列化,我们可以根据这个过滤来进行字符的逃逸
1 |
|
结果是
1 | a:3:{s:4:"user";s:24:"flagflagflagflagflagflag";s:8:"function";s:59:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";} |
然后由于有过滤机制,所有flag会被替换成空,那么就会变成
1 | a:3:{s:4:"user";s:24:"";s:8:"function";s:59:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";} |
我们就会发现24可以继续往后面读取,一直读取了;s:8:”function”;s:59:”a,而且刚好后面是”;满足了闭合的要求,于是可以继续反序列化,我们就可以造成一些注入
我们传入两个键值对,第一个键对应的值因为过滤函数被过滤掉了,在我们巧妙的长度构造下,第二个键变成了第一个键的值,而第二个值在反序列化后变成了第二个键值对
[安洵杯 2019]easy_serialize_php
1 |
|
传参为phpinfo的时候发现了flag的地址是d0g3_f1ag.php
于是根据最后一个判断语句 我们要get传show_image,然后会对$serialize_info进行一个反序列化,这里是一个数组的反序列化,然后输出数组里面的img内容,同时这个img是base64加密过的
代码执行的顺序是
1.把get的f赋值给$function
2.检测是否有session,若有就释放掉重新赋值,user赋值为guest,function赋值为前面得到的$function
3.把post的数组进行一个extract赋值
4.检测是否有get一个img_path,若没有,则把session里面的img赋值为base64加密的guest_img.png;若有,则把session里面的img赋值为经过sha和base64加密后的img_path
5.把$serialize_info定义为序列化后的session,而且过滤关键字
6.如果$funtion等于show_image的时候,反序列化$serialize_info里面的img同时base64解码
这里面向wp做题,从SESSION原本就有的键user入手,由于不能直接给img赋值,因为后面会把img赋值覆盖掉,所以我们要构造一个键值对使得img在反序列化后是flag,同时使得原本的img的内容不在读取的范围内
所以要创造出img
s:3:”img”;s:20:”ZDBnM19mMWFnLnBocA==”;
$_SESSION[user]=”flagflagflagphp”;
$_SESSION[function]=”;s:8:”function”;s:0:””;s:3:”img”;s:20:”ZDBnM19mMWFnLnBocA==”;”
由于要吞掉”;s:8:”function”;s:68:”
构造payload
?f=show_image
_SESSION[user]=flagflagflagflagflagphp&_SESSION[function]=”;s:8:”function”;s:0:””;s:3:”img”;s:20:”ZDBnM19mMWFnLnBocA==”;}
得到flag{58277f1a-3352-4990-8289-e4586be8bc3a}