upload-labs刷题笔记

1

源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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验证代码,对上传文件的类型进行限制,把一句话脚本的名字改成hack.php.jpg,burp suite抓包把jpg去了即可,复制图片链接,蚁剑链接

2

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)) {
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语言,是后端验证,同样是对上传的文件有图片格式的限制

image/jpeg image/png这种格式叫做MIME,上传时直接上传php脚本,bp抓包改content-type内容即可

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

函数解释:deny_ext :黑名单列表

trim(): :删除字符串两端的空格或其他预定义字符。用trim()函移除字符。我们没有添加移除的字符,就默认移除下列字符”\0” - NULL、”\t” - 制表符、”\n” - 换行、”\x0B” - 垂直制表符、”\r” - 回车、” “ - 空格(ltrm、rtrim)

deldot() :把文件后面的点删除windows的特性会自动对后缀名去”.” 处理比如: webshell.php. 。

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

str_ireplace():替换字符串中的一些字符(不区分大小写)。遵循的一些规则如果搜索的字符串是一个数组那么它会返回一个数组,且对数组中的每个元素进行查找和替换。(str_replace区分大小写)用str_ireplace(’::$DATA’, ‘’,fileext ) 函 数 防 止 在 后 缀 中 添 加 “ : : file_ext)函数防止在后缀中添加”::file
e

xt)函数防止在后缀中添加”::DATA”绕过利用windows特性,可在后缀名中加” ::$DATA”绕过

strtolower(): 故名思意,转换为小写

strrpos() 函数查找字符串在另一字符串中最后一次出现的位置。strrpos() 函数对大小写敏感。

stripos() - 查找字符串在另一字符串中第一次出现的位置(不区分大小写)
strpos() - 查找字符串在另一字符串中第一次出现的位置(区分大小写)
strripos() - 查找字符串在另一字符串中最后一次出现的位置(不区分大小写)
getimagesize() :用于获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息。

从源码中我们可以看出设定了黑名单,’.asp’,’.aspx’,’.php’,’.jsp’后缀的文件都不允许上传,并且会检查大小写、删除点和空格。

#后缀绕过常用手段
PHP:
php2、php3、php5、phtml、pht(是否解析需要根据配置文件中设置类型来决定)
ASP:
asa、cer、cdx
ASPX:
ascx、ashx、asac
JSP:
jsp、jspx、jspf

有时候需要挨个进行尝试

4

根据源代码得知,黑名单限制太多,换一种方式绕过,使用’.htaccess’文件绕过

htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能

//.htaccess 修改文件
SetHandler application/x-httpd-php

再上传一个图片格式的木马即可,自动解析为php

ps:phpstudy的apache有问题,复现不了

另一种方法是后缀名冗余(未知拓展名绕过)绕过,例如修改成one.php.aaa、one.php.xxxx等。然后直接使用中国菜刀连接。5,6也是这种方法绕过

7

加.(空格)a.php.

8

加.a.php.

9

增加后缀::$DATA

10

冗余后缀名

11

$file_name = str_ireplace($deny_ext,"", $file_name);替换了后缀名

pphphp(php) phphpp(hpp)复写尝试

12

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$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类型文件!";
}
$is_upload = false;
}

可以通过截断上传(0x00,%00,/00 )实现。a.php%00,filename要改成jpg

(1)php版本要小于5.3.4。

(2)文件路径可控。

(3)magic_quotes_gpc需要为OFF状态。(在php.ini中)

13

save_path变成了POST提交,区别在于不对%00自动编码,需手动解码

14-16

图片马cmd执行copy a.jpg/b+ b.php c.jpg

可以绕过getimagesize()函数来实现对文件类型的识别判断,exif_imagetype()函数获得图片文件的类型,从而实现文件白名单的过滤操作。

利用文件包含来使用木马

17

二次渲染绕过

绕过二次渲染的核心思想便是先上传一张图片,再将上传完成后的图片下载下来,对比渲染前后图片的编码变化,将我们的代码写在未被渲染的区域便可绕过二次渲染。
由于不同格式文件的特性,在进行绕过二次渲染时,选用gif的图像最容易成功,对于jpg和png这两种图片需要用脚本进行改写,也不在进行尝试。

用winhex工具,在最后加上php代码

将渲染后的gif文件下载到本地,通过对比软件对比渲染前后的十六进制数据。下图左为渲染前,右为选然后的文件。未标红的即为前后未发生变化的区域。

将木马写到该区域再次进行尝试上传并利用文件包含访问。

17

条件竞争

分析源码,对于上传的文件处理是先保存到服务器,再对比拓展名,如果拓展名不属于白名单中的三种后缀,便由18行的操作执行unlink操作将保存的文件删除

<?php fputs(fopen('info.php','w'),'<?php phpinfo();?>');?>通过写入这行代码,一旦竞争成功,文件会留在服务器,可访问此文件调用phpinfo()

bp的intruder模块发包,自己去浏览器刷新或者用python脚本

1
2
3
4
5
6
7
8
import requests
url = "http://192.168.159.128/upload-labs-master/upload/eval.php"
while True:
html = requests.get(url)
if html.status_code == 200:
print("OK")
break

19

同样是条件竞争,只不过需要图片马,把上面的代码写进图片即可

Pass19 — %00截断,参考Pass11
Pass20 — 0X00截断,参考Pass12