• 关于php的session.serialize_handler的问题


    前言

    php的session信息是储存在文件中的

    session.save_path="" 指定储存的路径
    session.save_handler="" 指定储存时使用的函数(默认是file)
    session.auto_start boolen
    session.serialize_handler="" 定义序列化和反序列化的处理器的名字,默认是php(5.5.4后改为php_serialize)
    

    session.serialize_handler存在以下几种

    • php_binary 键名的长度对应的ascii字符+键名+经过serialize()函数序列化后的值
    • php 键名+竖线(|)+经过serialize()函数处理过的值
    • php_serialize 经过serialize()函数处理过的值,会将键名和值当作一个数组序列化

    使用过程中如果想要修改,使用

    ini_set('session.serialize_handler','php_serialize');
    

    但这里设置的handler如果和默认的不同,就会出问题

    比如默认是php的handler,在该页面设置为php_serialize

    这是如果我们传入一个 '|O:5:"Class"';,这样的一个数据,在储存时就会加上键名进行序列化,但是进行读取的时候还是会按照php handler来处理,以|作为键和值的分隔符,将前半部分当作键,后半部分当作值,然后进行反序列化

    CTF

    jarvisoj PHPINFO

    引用官方文档的内容

    当 session.upload_progress.enabled INI 选项开启时,PHP 能够在每一个文件上传时监测上传进度。 这个信息对上传请求自身并没有什么帮助,但在文件上传时应用可以发送一个POST请求到终端(例如通过XHR)来检查这个状态

    当一个上传在处理中,同时POST一个与INI中设置的session.upload_progress.name同名变量时,上传进度可以在$_SESSION中获得。 当PHP检测到这种POST请求时,它会在$_SESSION中添加一组数据, 索引是 session.upload_progress.prefix 与 session.upload_progress.name连接在一起的值。 通常这些键值可以通过读取INI设置来获得

    通俗的说就是请求时加上与session.upload_progress.name同名的变量时就会在$_SESSION中加上一组新的数据

    来看这道题,题目给了源码

    <?php
    //A webshell is wait for you
    ini_set('session.serialize_handler', 'php');
    session_start();
    class OowoO
    {
        public $mdzz;
        function __construct()
        {
            $this->mdzz = 'phpinfo();';
        }
        
        function __destruct()
        {
            eval($this->mdzz);
        }
    }
    if(isset($_GET['phpinfo']))
    {
        $m = new OowoO();
    }
    else
    {
        highlight_string(file_get_contents('index.php'));
    }
    ?>
    

    看到这里使用了ini_set('sessionserialize_handler':'php'),有预感会出现handler不一样的问题

    接下来查看phpinfo,发现php版本是5.6.21,大于5.5.4,默认的handler是php_serialize,会出现上面所述的问题

    在使用session_start()时会自动加载session文件中的值,因为在这里在__destruct方法中使用eval,所以只要在session文件中写入这个类,就能够执行代码?

    但是我们如何将类写入session文件?

    这就用到刚才提到的东西,查看phpinfo,
    因为session.upload_progress.enabled=1,所以我们就可以post一个和session.upload_progress.name同名的变量,来使得我们上传的文件名写入session

    因为这里是php handler,是以|开头的,所以在反序列化时会按照|来识别键值对而不是按照默认的php_serialize来识别session,所以我们将文件名改为

    "|O:5:"OowoO":1:{s:4:"mdzz";s:36:"print_r(scandir(dirname(__FILE__)));";}"
    

    来读取文件目录

    问题

    session部分的问题大致是解决了……剩下的问题就是……为什么要将双引号转义?暂时还没有弄清楚,待日后分析吧

    参考链接

    https://blog.spoock.com/2016/11/15/jarvisoj-web-writeup-1/

    https://blog.csdn.net/wy_97/article/details/78430690

  • 相关阅读:
    MySQ随笔2(连接表、分组)
    MySQL随笔
    Python随笔1
    要学习但还没学的知识点2016年8月4号
    jQuery备忘录--私家版
    Chrome 中的彩蛋——T-Rex
    JavaScript多线程初步学习
    实例:jQuery实现标签切换
    实例:用jQuery实现垂直和水平下拉 菜单
    AJAX编程模板
  • 原文地址:https://www.cnblogs.com/hf99/p/9746038.html
Copyright © 2020-2023  润新知