文件上传漏洞绕过技巧

文件上传漏洞绕过技巧

一、文件上传漏洞介绍

通常web 站点会有用户注册功能,而当用户登入之后大多数情况下都会存在类似头像上传、附件上传一类的功能,这些功能点往往存在上传验证方式不严格的安全缺陷,是在web 渗透中非常关键的突破口,只要经过仔细测试分析来绕过上传验证机制,往往会造成被攻击者直接上传web 后门,进而控制整个web 业务的控制权,复杂一点的情况是结合webserver 的解析漏洞来上传后门获取权限。

二、验证方法与绕过


1.CONTENT-LENGTH验证
Content-Length验证是指服务器会对上传的文件内容长度进行检查,超出限制大小的文件将不允许被上传。虽然这种类型的验证不是很受欢迎,但在一些应用的文件上传中也时常能碰到

示例:

if ($_FILES["fileToUpload"]["size"] > 30) {
echo "Sorry, your file is too large.";
}

CONTENT-LENGTH绕过

1.针对这种类型的验证,我们可以通过上传一些非常短的恶意代码来绕过。上传文件的大小取决于,(Web服务器上的最大长度限制,我们可以使用不同大小的文件来fuzzing上传程序,从而计算出它的限制范围)

2.如果截断上传文件最大大小,修改文件大小的限制,然后再发送给服务端。

2.客户端javascript 检测(通常为检测文件扩展名)
顾名思义,就是在文件被上传到服务端的时候,对于文件名的扩展名进行检查,如果不合法,则拒绝这次上传
有两种策略:
黑名单策略,文件扩展名在黑名单中的为不合法

示例代码:

$postfix = end(explode('.','$_POST['filename']);

if($postfix=='php'||$postfix=='asp'||$postfix=='sh'){

echo "invalid file type";

return;

}

  

白名单策略,文件扩展名不在白名单中的均为不合法

示例代码:

$postfix = end(explode('.','$_POST['filename']);

if($postfix=='jpg'||$postfix=='png'||$postfix=='gif'){

//save the file and do something next

} else {

echo "invalid file type";

return;

}

  

黑名单绕过:
通过上传不受欢迎的php扩展来绕过黑名单。例如:pht,phpt,phtml,php3,php4,php5,php6

白名单绕过:
通过某种类型的技巧来绕过白名单,例如添加空字节注入(shell.php%00.gif),或使用双重扩展来上传文件(shell.jpg.php)。

此外,我们还可以尝试扩展名大小写来绕过,例如:pHp,Php,phP

白名单策略是更加安全的,通过限制上传类型为只有我们接受的类型,可以较好的保证安全,因为黑名单我们可以使用各种方法来进行注入和突破。

更多绕过技巧:

在一些 webserver 中,存在解析漏洞
1.老版本的IIS中的目录解析漏洞,如果网站目录中有一个 /.asp/目录,那么此目录下面的一切内容都会被当作asp脚本来解析
2.老板本的IIS中的分号漏洞:IIS在解析文件名的时候可能将分号后面的内容丢弃,那么我们可以在上传的时候给后面加入分号内容来避免黑名单过滤,如 a.asp;jpg
3.旧版Windows Server中存在空格和dot漏洞类似于 a.php. 和 a.php[空格] 这样的文件名存储后会被windows去掉点和空格,从而使得加上这两个东西可以突破过滤,成功上传,并且被当作php代码来执行
4.nginx空字节漏洞 xxx.jpg%00.php 这样的文件名会被解析为php代码运行
5.apache的解析漏洞,上传如a.php.rar a.php.gif 类型的文件名,可以避免对于php文件的过滤机制,但是由于apache在解析文件名的时候是从右向左读,如果遇到不能识别的扩展名则跳过,rar等扩展名是apache不能识别的,因此就会直接将类型识别为php,从而达到了注入php代码的目的


3. 服务端MIME 类型检测(检测Content-Type 内容)
如: content-Type:aplication/x-php

绕过方法:

改为如下类型:

Content-Type: image/jpg
Content-Type: image/png
Content-Type: image/jpeg
Content-Type: image/gif

常用的MIMETYPE表
text/plain(纯文本)
text/html(HTML文档)
text/javascript(js代码)
application/xhtml+xml(XHTML文档)
image/gif(GIF图像)
image/jpeg(JPEG图像)
image/png(PNG图像)
video/mpeg(MPEG动画)
application/octet-stream(二进制数据)
application/pdf(PDF文档)
application/(编程语言) 该种语言的代码
application/msword(Microsoft Word文件)
message/rfc822(RFC 822形式)
multipart/alternative(HTML邮件的HTML形式和纯文本形式,相同内容使用不同形式表示)
application/x-www-form-urlencoded(POST方法提交的表单)
multipart/form-data(POST提交时伴随文件上传的表单)


4.分析文件头内容来检查文件类型

一种检查类型的方式是使用对于文件内容的验证机制,这种方法利用的是每一个特定类型的文件都会有不太一样的开头或者标志位。可以通过比如php的exif_imagetype()函数

一个通过这种方法来过滤的示例代码如下:

if (! exif_imagetype($_FILES['uploadedfile']['tmp_name'])) {

echo "File is not an image";

return;

}

  

绕过方法:

给上传脚本加上相应的幻数头字节就可以,php引擎会将 <?之前的内容当作html文本,不解释而跳过之,后面的代码仍然能够得到执行比如下面:

(一般不限制图片文件格式的时候使用GIF的头比较方便,因为全都是文本可打印字符。)

GIF89a

<?

php echo shell_exec($_GET['cmd']);

?>

  

图片文件通常有称作幻数的头字节,我们来看一下几种图片文件的幻数:

(注意!下面是二进制而不是文本格式的数据)

JPG

FF D8 FF E0 00 10 4A 46 49 46

GIF(相当于文本的GIF89a)

47 49 46 38 39 61

PNG

89 50 4E 47

通过检查头几位字节,可以分辨是否是图片文件

如果是其他类型的二进制文件,也有响应的头字节,如下表

格式 文件头
TIFF (tif) 49492A00
Windows Bitmap (bmp) 424D
CAD (dwg) 41433130
Adobe Photoshop (psd) 38425053
Rich Text Format (rtf) 7B5C727466
MS Word/Excel (xls.or.doc) D0CF11E0
MS Access (mdb) 5374616E64617264204A
ZIP Archive (zip), 504B0304
RAR Archive (rar), 52617221
Wave (wav), 57415645
AVI (avi), 41564920
Real Media (rm), 2E524D46
MPEG (mpg), 000001BA
MPEG (mpg), 000001B3
Quicktime (mov), 6D6F6F76
Adobe Acrobat (pdf), 255044462D312E
Windows Media (asf), 3026B2758E66CF11
MIDI (mid), 4D546864

5.文件加载检测

一般是调用API 或函数去进行文件加载测试,常见的是图像渲染测试,再变态点的甚至是进行二次渲染(后面会提到)。

对渲染/加载测试的攻击方式是代码注入绕过;

对二次渲染的攻击方式是攻击文件加载器自身。
先说下对渲染/加载测试攻击-代码注入绕过,可以用图像处理软件对一张图片进行代码注入。用winhex看数据可以分析出这类工具的原理是在不破坏文件本身的渲染情况下找一个空白区进行填充代码,一般会是图片的注释区。对于渲染测试基本上都能绕过,毕竟本身的文件结构是完整的.

但如果碰到变态的二次渲染,基本上就没法绕过了,估计就只能对文件加载器进行攻击了。

一般进行遇到二次渲染,想绕过,它相当于是把原本属于图像数据的部分抓了出来,再用自己的API 或函数进行重新渲染,在这个过程中非图像数据的部分直接就被隔离开了。能想到的一个思路就是基于数据二义性,即让数据既是图像数据也包含一句话木马代码,就像shellcode 通过数据二义性绕过IDS 检测特殊字符一样的道理。

如果要对文件加载器进行攻击,常见的就是溢出攻击,上传自己的恶意文件后,服务器上的文件加载器会主动进行加载测试,加载测试时被溢出攻击执行shellcode比如access/mdb 溢出如果要对文件加载器进行攻击,常见的就是溢出攻击,上传自己的恶意文件后,服务器上的文件加载器会主动进行加载测试,加载测试时被溢出攻击执行shellcode比如access/mdb 溢出。

总之对文件完整性检测的绕过,通常就直接用个结构完整的文件进行代码注入即可没必要再去测到底是检查的幻数还是文件头结构之类的了。

解析攻击

攻击角度来分是这样的:

直接解析(完全没防御或有一点简单的防御)

比如我们直接就可以上传一个扩展名是.php的文件,只需要简单地绕过客户端javascript 检测或者服务端MIME 类型检测就行了。

配合解析(有一定程度的防御)

我们可以理解为先代码注入到服务器上,上传一个带有一句话木马的图片或文件之类

让它待在某个位置,等待这一个解析的配合。(比如php 的文件包含解析,web 服务器的解析漏洞,.htaccess 解析等)

本地文件包含解析

主要是php 的本地文件包含(远程文件包含不属于上传攻击绕过范畴)

htaccess解析

就不用多说了,看看之前.htaccess 文件攻击的那个案例,用户自己定义如何去调用解析器解析文件就可以了。

web应用程序解析漏洞以及其原理

Apache 解析漏洞

解析: test.php.任意不属于黑名单且也不属于Apache解析白名单的名称

描述: 一个文件名为x1.x2.x3 的文件,Apache 会从x3 的位置往x1 的位置开始尝试解析,

如果x3 不属于Apache 能解析的扩展名,那么Apache会尝试去解析x2 的位置,这样一直往前尝试,直到遇到一个能解析的扩展名为止

IIS 解析漏洞

解析- test.asp/任意文件名|test.asp;任意文件名| 任意文件名/任意文件名.php

描述- IIS6.0 在解析asp 格式的时候有两个解析漏洞,一个是如果目录名包含”.asp”字符串,那么这个目录下所有的文件都会按照asp 去解析,另一个是只要文件名中含有”.asp;”会优先按asp 来解析。

IIS7.0/7.5 是对php 解析时有一个类似于Nginx的解析漏洞,对任意文件名只要在URL后面追加上字符串”/任意文件名.php”就会按照php 的方式去解析。

Nginx 解析漏洞

解析- 任意文件名/任意文件名.php | 任意文件名%00.php

描述- 目前Nginx 主要有这两种漏洞,一个是对任意文件名,在后面添加/任意文件名.php

的解析漏洞,比如原本文件名是test.jpg,可以添加为test.jpg/x.php进行解析攻击。还有一种是对低版本的Nginx 可以在任意文件名后面添加%00.php 进行解析攻击。

 6.限制Web Server对于特定类型文件的行为

导致文件上传漏洞的根本原因在于服务把用户上传的本应是数据的内容当作了代码,一般来说,用户上传的内容都会被存储到特定的一个文件夹下,比如我们很多人习惯于放在 ./upload/ 下面要防止数据被当作代码执行,我们可以限制web server对于特定文件夹的行为。

大多数服务端软件都可以支持用户对于特定类型文件的行为的自定义,以Apache为例:

在默认情况下,对与 .php文件Apache会当作代码来执行,对于 html,css,js文件,则会直接由HTTP Response交给客户端程序对于一些资源文件,比如txt,doc,rar等等,则也会以文件下载的方式传送的客户端。我们希望用户上传的东西仅仅当作资源和数据而不能当作代码

因此可以使用服务器程序的接口来进行限制

以Apache为例,我们可以利用 .htaccess 文件机制来对web server行为进行限制

在这里插一句,如果不是专门的文件下载目录,请务必关掉文件夹浏览的权限,以防止嗅探和可能的越权,也是使用.htaccess文件,在其中加上一句

Options All -Indexes

即可。

禁止脚本执行有多种方式可以实现,而且分别有不同的效果,我们分别来看一下

1.指定特定扩展名的文件的处理方式,原理是指定Response的Content-Type可以加上如下几行

AddType text/plain .pl .py .php

这种情况下,以上几种脚本文件会被当作纯文本来显示出来,你也可以换成其他的Content-Type

2.如果要完全禁止特定扩展名的文件被访问,用下面的几行

Options -ExecCGI

AddHandler cgi-script .php .pl .py .jsp .asp .htm .shtml .sh .cgi识别

在这种情况下,以上几种类型的文件被访问的时候,会返回403 Forbidden的错误

3.也可以强制web服务器对于特定文件类型的处理,与第一条不同的是, 下面的方法直接强行让apache将文件识别为你指定的类型,而第一种是让浏览器

<FilesMatch "\.(php|pl|py|jsp|asp|htm|shtml|sh|cgi)$">

ForceType text/plain

</FilesMatch>

看代码就可以很明白的知道,符合上面正则的全部被认为是纯文本,也可以继续往里面加入其他类型。

4.只允许访问特定类型的文件

<Files ^(*.jpeg|*.jpg|*.png|*.gif)>

order deny,allow

deny from all

</Files>

在一个上传图片的文件夹下面,就可以加上这段代码,使得该文件夹里面只有图片扩展名的文件才可以被访问,其他类型都是拒绝访问。

这又是一个白名单的处理方案

永远记得,白名单是最有保障的安全措施

反制

可以通过 move_uploaded_file 函数把自己写的.htaccess 文件上传,覆盖掉服务器上的文件,来定义文件类型和执行权限如果做到了这一点,将获得相当大的权限。

猜你喜欢

转载自www.cnblogs.com/-wenli/p/9911556.html