前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >常见文件上传漏洞解析

常见文件上传漏洞解析

原创
作者头像
竹紫
发布2022-04-09 21:22:24
1.6K1
发布2022-04-09 21:22:24
举报

# 常见文件上传漏洞解析

### 前言

> 文件上传漏洞是我们平时渗透过程中经常利用的漏洞,利用文件上传我们可以直接得到 webshell,是非常直接的测试方式。写这篇文章主要是想对常见的文件上传检测和绕过进行总结,同时练习文件上传 PHP 代码的编写。

以下上传测试使用的 HTML 表单的代码为:

```

<html>

<head>

<title>File Upload</title>

<meta charset="utf-8">

</head>

<body>

<form action="upload.php" method="POST" enctype="multipart/form-data">

<input type="hidden" name="MAX_FILE_SIZE" value="1000000">

选择文件: <input type="file" name="myfile">

<input type="submit" value="Upload">

</form>

</body>

</html>

```

### 1.1 前端 JavaScript 检测

前端一般都是使用 js 来限制我们的上传类型和文件大小,这里以 upload-labs Pass-01 的源码为例:

```

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;

}}

```

对于前端的检测我们可以抓包来修改文件类型,也可以禁用掉 JavaScript。总之,只有前端的限制是非常不安全的,非常容易被绕过。

### 2.1 后端检测文件类型

2.1.1 检测 content-type 后端代码大致为:

```

<?php

$allow_content_type = array("image/gif", "image/png", "image/jpeg");$path = "./uploads";$type = $_FILES["myfile"]["type"];if (!in_array($type, $allow_content_type)) {

die("File type error!<br>");} else {

$file = $path . '/' . $_FILES["myfile"]["name"];

if (move_uploaded_file($_FILES["myfile"]["tmp_name"], $file)) {

echo 'Success!<br>';

} else {

echo 'Error!<br>';

}}

?>

```

绕过方法: 抓包将 content-type 改为图片形式(即 image/png 等),即可成功上传

### 2.1.2 检测文件头判断文件类型

后端代码大致为:

```

<?php

$allow_mime = array("image/gif", "image/png", "image/jpeg");$imageinfo = getimagesize($_FILES["myfile"]["tmp_name"]);$path = "./uploads";if (!in_array($imageinfo['mime'], $allow_mime)) {

die("File type error!<br>");} else {

$file = $path . '/' . $_FILES["myfile"]["name"];

if (move_uploaded_file($_FILES["myfile"]["tmp_name"], $file)) {

echo 'Success!<br>';

} else {

echo 'Error!<br>';

}}

?>

```

此时虽然检查的也是文件类型,但是是使用 getimagesize () 函数来获取文件的 MIME 类型,此时检测的不是数据包中的 content-type,而是图片的文件头,常见的图片文件头如下:

```

gif(GIF89a) : 47 49 46 38 39 61

jpg、jpeg : FF D8 FF

png : 89 50 4E 47 0D 0A

```

绕过方法:

当上传 PHP 文件时,可以使用 winhex、010editor 等十六进制处理工具,在数据最前面添加图片的文件头,从而绕过检测

### 2.2 后端检测文件扩展名

### 2.2.1 黑名单检测

后端代码大致为:

```

<?php

$blacklist = array('php', 'asp', 'aspx', 'jsp');$path = "./uploads";$type = array_pop(explode('.', $_FILES['myfile']['name']));if (in_array(strtolower($type), $blacklist)) {

die("File type errer!<br>");} else {

$file = $path . '/' . $_FILES['myfile']['name'];

if (move_uploaded_file($_FILES['myfile']['tmp_name'], $file)) {

echo 'Success!<br>';

} else {

echo 'Error!<br>';

}}

?>

```

众所周知使用黑名单是非常不安全的,很多网站会使用扩展名黑名单来限制上传文件类型,有些甚至在判断时都不用 strtolower () 来处理,因此造成漏洞

**绕过方法:**

使用一些特殊扩展名来绕过(如 PHP 可以使用 php3、php4、php5 等来代替) 在后端比较没有转换大小写处理时,使用大小写混淆(如将 PHP 改为 PHP 等)来绕过

### 2.2.2 白名单检测

大致代码如下,与黑名单检测没有太大差别:

```

<?php

$whitelist = array('png', 'jpg', 'jpeg', 'gif');$path = "./uploads";$type = array_pop(explode('.', $_FILES['myfile']['name']));if (!in_array(strtolower($type), $whitelist)) {

die("File type errer!<br>");} else {

$file = $path . '/' . $_FILES['myfile']['name'];

if (move_uploaded_file($_FILES['myfile']['tmp_name'], $file)) {

echo 'Success!<br>';

} else {

echo 'Error!<br>';

}}

```

白名单相对与黑名单就安全许多,要求只能是特定扩展名的文件才能上传,虽然我们无法从代码层面来绕过,但这样也不是绝对的安全,可以利用其他漏洞来绕过

**绕过方法:**

使用 %00 截断文件名来上 如果目标还存在文件包含漏洞,那么就可以上传图片马再文件包含来拿 shell

### 2.3 后端检测文件内容

### 2.3.1 文件内容替换

这种主要是将文件中的敏感字符替换掉,大致代码类似于下面这样:

```

<?php

$path = "./uploads";$content = file_get_contents($_FILES['myfile']['tmp_name']);$content = str_replace('?', '!', $content);$file = $path . '/' . $_FILES['myfile']['name'];if (move_uploaded_file($_FILES['myfile']['tmp_name'], $file)) {

file_put_contents($file, $content);

echo 'Success!<br>';} else {

echo 'Error!<br>';}

?>

```

此时如果我们要上传 PHP 的一句话 <?php @eval($_POST['shell']);?> 时,PHP 的语言标记中的?会被替换为!,这样一句话就不能被执行了

**绕过方法:**

主要还是要根据实际过滤的字符来判断,如果写死的话可能是没办法的(一般不会,因为还要兼顾图片上传)

比如过滤掉问号,我们就可以使用 这样的一句话。具体方法要看实际代码过滤了哪些字符。

### 3.1 解析漏洞及其他漏洞

### 3.1.1 IIS 解析漏洞

**IIS6.0**在 IIS6.0 中有两个很重要的 asp 解析漏洞:

假设当前有一个名为 "xxx.asp" 的目录,那么该目录下的所有文件都将被作为 asp 文件解析 假设上传一个名为 "test.asp;xxx.jpg" 时,该文件会被当做 asp 文件解析**IIS7.5**这个其实不能算 IIS 的洞,它其实是 PHP 的解析漏洞,这个漏洞利用条件是服务器在 php.ini 中将 cgi.fix_pathinfo 的值设置为 1

然后当我们访问服务器上任意一个文件时(如:[url]http://127.0.0.1.com/a.jpg[/url]),当我们在 URL 后面添加。PHP(即:[url]http://127.0.0.1/a.jpg/.php[/url]),那么文件 a.jpg 就将被作为 PHP 文件来解析

### 3.1.2 Apache 解析漏洞

利用低版本 apache 扩展名解析特性 在了解这个解析漏洞之前,我们要首先了解 apache 和 PHP 的三种结合方式:

### 3.1.3 %00 截断

这个多数被利用在截断路径,利用的条件是:

- PHP < 5.3.4

- magic_quotes_gpc 关闭 因为 0x00 是字符串的结束标志符,所以 PHP 在读取到 0x00 时就不会再往后读取,我们可以利用这些截断字符后面不需要的内容

以 upload-labs 的 Pass-12 为例,源码如下:

```

$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;

if(move_uploaded_file($temp_file,$img_path)){

$is_upload = true;

} else {

$msg = '上传出错!';

}

} else{

$msg = "只允许上传.jpg|.png|.gif类型文件!";

}

}

```

由于是白名单限制了上传文件类型,因此我们无法在文件名处做文章。但最终 move_uploaded_file()的目标目录是我们可控的,我们可以将 POST 传入的 save_path 改为../upload/shell.php%00,这样后面的内容就会被截断掉,这就导致了任意文件上传

还要注意的是 %00 是 url 编码,在以 POST 传参时应该使用 burpsuite 对其进行 url decode,或者修改 hex 值为 00;而当 GET 传参时因为浏览器会做一遍 url decode,所以直接传 %00 即可。

### 3.1.4 利用。htaccess 解析

.htaccess 文件 (或者 "分布式配置文件"), 全称是 Hypertext Access (超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过 Apache 的 AllowOverride 指令来设置。 利用。htaccess 的条件:Apache 中配置 AllowOverride All

.htaccess 文件可以配置将特定的文件按规定的文件类型进行解析,可以用以下两种方式来配置:

```

<FilesMatch "test">

SetHandler application/x-httpd-php

</FilesMatch>

```

这一种采用正则匹配,只要文件名为 test 的文件都将被作为 PHP 文件解析

AddType application/x-httpd-php .jpg第二种是将.jpg 文件都作为 PHP 文件解析

这样我们如果能将。htaccess 上传到服务器的话,就可以再根据我们自己设定的规则来解析上传的文件,以此来绕过上传过滤

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档