故事起源是90官方群有人愁不知道怎么拿shell所以帮忙看一下代码。其实是不太想看这套程序的因为太久远了。
phpweb前台getshell
漏洞分析
if($act=="upload"){
$file=$_FILES["file"];
$r_size=$_POST["r_size"];
if ($_FILES["file"]["ERROR"] > 0){
echo "ERROR:".$_FILES["file"]["ERROR"];
exit;
}else{
if($_FILES["file"]["size"]!=$r_size){
echo "ERROR:上传文件错误,文件大小和原文件不匹配";
@write_log("app.log",date("Y-m-d H:i:s",time())." ERROR: 上传文件错误,文件大小和原文件不匹配\n",FILE_APPEND);
exit;
}
//检查目录名
$ToPath="../effect/source/bg";
$Tofile=$ToPath."/".$_FILES["file"]["name"];
if(!is_writable($ToPath)){
echo "ERROR:".$ToPath." 目录不可写,请设置目录属性为可写";
@write_log("app.log",date("Y-m-d H:i:s",time())." ERROR: ".$ToPath." 目录不可写,请设置目录属性为可写\n",FILE_APPEND);
exit;
}
if(file_exists($Tofile) && !is_writable($Tofile)){
echo "ERROR:".$Tofile." 文件不能覆盖,请设置文件属性为可写";
@write_log("app.log",date("Y-m-d H:i:s",time())." ERROR: ".$Tofile." 文件不能覆盖,请设置文件属性为可写\n",FILE_APPEND);
exit;
}
//复制文件
copy($_FILES["file"]["tmp_name"],$Tofile);
switch($_FILES["file"]["type"]){
case "application/octet-stream":
@chmod($Tofile,0755);
break;
default:
@chmod($Tofile,0666);
break;
}
echo "OK";
@write_log("app.log",date("Y-m-d H:i:s",time())." 安装成功: ".$Tofile."\n",FILE_APPEND);
exit;
}
}
在这个upload功能中直接获取了FILE[name]进行路径拼接最后进行copy行为而且if也只是判断了是否与我们填入的r_size参数是否匹配以及路径是否可写等。
$k=md5(strrev($dbUser.$dbPass));
$h=$_SERVER["HTTP_REFERER"];
$t=$_POST["t"];
$m=$_POST["m"];
$act=$_POST["act"];
$path=$_POST["path"];
$md5=md5($k.$t);
if($m!=$md5){
echo "ERROR: 安全性校验错误";
exit;
}
但是在文件顶部有一个这么验证,通过数据库的账号和密码以及我们带入的t参数来MD5加密并且通过我们带入的M来判断是否匹配。这种情况要么知道数据库的账号和密码要么就是找找看有没其他的地方可以拿到这部分数据
case "appcode" :
$pluslable=$_POST['pluslable'];
$apptype=$_POST['apptype'];
$coltype=$_POST['coltype'];
$tempid=$_POST['tempid'];
if($apptype=="plus"){
$msql->query("select id from {P}_base_plusdefault where `pluslable`='$pluslable'");
if($msql->next_record()){
echo "1000";
exit;
}
$msql->query("select id from {P}_base_coltype where `coltype`='$coltype'");
if($msql->next_record()){
}else{
echo "2000";
exit;
}
}
if($apptype=="border"){
$msql->query("select id from {P}_base_border where `tempid`='$tempid'");
if($msql->next_record()){
echo "1000";
exit;
}
}
$code="k=".md5(strrev($dbUser.$dbPass))."&t=".time();
echo $code;
exit;
break;
然后我们在appcode这个功能可以看见这里刚好有满足需求的MD5后的内容并且进行了echo打印。我们只需要看页面是否满足访问需求
define("ROOTPATH", "../");
include(ROOTPATH."includes/common.inc.php");
include("language/".$sLan.".php");
$act = $_POST['act'];