[EIS 2019]EzPOP
我们查看源码
1 | <?php |
进行代码审计,我们发现A类的调用关系为__destruct->save()->getForStorage->cleanContents
然后再进行到save()中的$this->store->set($this->key, $contents, $this->expire);
然后调用B类中的set方法
1 | public function set($name, $value, $expire = null): bool{ |
set中前面调用的getxxx都是对变量数据类型进行处理的没什么好看的,然后是到了serialize方法
1 | protected function serialize($data): string { |
这里有个$serialize($data)
函数动态调用
再到$data = gzcompress($data, 3)
,这里由于if条件不满足可以直接跳过
再到这个很明显的漏洞地方
1 | $data = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data; |
我们可以利用file_put_contents写入php文件,直接getshell
这里data前面拼接了<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n"
绕过exit可以参考p牛的这篇文章,
$filename=php://filter/convert.base64-encode/resource=xx.php就可以破坏掉exit(),
1 | sprintf('%012d', $expire) |
$expire
可控
还让我们可以填base64_decode,填充为4的倍数,让php代码被正确解码出来
1 | $filename和$data都可控 |
它们在set中的处理过程:
1 | $data = $this->serialize($value) |
所以$filename
的值由A类中$key
决定
$data
由A类中的$cache
和$complete
决定
(注意函数传入变量的类型要求
构造exp
1 | <?php |
然后访问x.php,连接蚁剑