File-Upload

Web

文件上传漏洞,利用该漏洞使服务器执行我们所上传的 webshell 来达到我们的目的。🌙💤

简介

什么是文件上传漏洞

由于 web 服务器对用户上传的文件没有进行充分的检验,从而导致用户可以上传任意具有危险性的文件,这种具有危险性的文件可是木马、病毒、恶意脚本或者 webshell 等。如果服务器的处理逻辑不够安全,对这些有问题的文件进行了处理、解析那就会导致严重后果产生。

文件上传漏洞的影响

文件上传漏洞最终产生的影响或者说是影响的大小主要取决于2个因素

网站未能正确验证文件的哪个方面,无论是其大小、类型、内容等。

文件成功上传后会受到哪些限制。

如果服务器对上传的文件类型没有限制,且允许将某些类型的文件(例如.php 和 .jsp)作为代码执行。在这种情况下,最严重的后果可能是攻击者成功使服务器执行一个充当 webshell 的服务器端代码文件,并且获得服务器的完全控制权。

如果服务器对于上传的文件名没有充分限制,那么服务器还可能存在着目录遍历漏洞,这就意味着攻击者可以将文件上传至其他他们所想要的位置。

靶场体验

基础文件上传漏洞

这个靶场对于上传文件的类型和上传文件的内容都没有限制,因此我们只需要将读取文件的 PHP 代码文件上传即可。

image-20220504132801930

文件中的内容是

1
<?php echo file_get_contents('/home/carlos/secret'); ?>

服务器会接收并且执行这段代码,因此当我们用浏览器访问我们所上传的文件时,我们可以发现我们想要的东西已经通过服务器的执行显示出来了

image-20220504133509068

基础文件类型限制绕过

HTTP 请求的响应表头中有 Content-Type 类,该类中的内容是服务器通过我们所上传的文件内容自动判断后填入的。当服务器对于上传文件的类型作出限制时,服务器会对 Content-Type 中的数据与预期的 MIME 类型进行匹配,如果匹配结果不同那么服务器就会不接收此文件。

当我们直接上传 .php 类型的文件时,我们会发现服务器并不接收此文件,因为服务器对文件的类型进行了限制,只允许 jpeg 和 png 类型的图片文件上传。

image-20220504140728142

服务器拒绝文件的依据是通过比较请求标头中的 Content-Type 值与预期的 MIME 类型是否相同,但是 bp 是可以对请求进行拦截和修改的,因此我们可以利用 bp 来绕过服务器对于文件类型的限制。

因此,我们在上传文件时将请求拦截,并修改标头中 Content-Type 值,将其修改成 image/jpeg 或者是 image/png 然后再放行,我们可以发现我们的文件上传成功了

image-20220504141638645

接下来在浏览器中访问我们所上传的文件即可。

上传文件不执行绕过

在我们可以访问的上传目录中,服务器只会执行 MIME 类型明确配置的执行脚本,那也就以为这,在上传目录中我们的文件内容并不会被执行。

但是如果服务器存在着目录遍历漏洞,那么我们可以将文件传输至其他目录下,服务器依旧有可能执行我们所上传的脚本。

上靶场,我们发现我们的文件是可以成功上传的,但是当我们访问我们所上传的文件时,我们可以发现我们所上传的内容被原封不动地输了出来

image-20220504210328174

这也就说明了服务器在这个目录下并不会对我们的代码进行执行。

我们可以通过目录遍历,将文件传至其他目录下,但是该题目对目录遍历字符做了过滤。

image-20220504212946468

因此,正确的 payload 应该如下所示

1
filename="..%2f<your-filename>"

image-20220504213100092

我们通过对其进行 URL 编码绕过过滤,这样我们的文件就成功被上传至上一级目录了。

image-20220504212552686

文件黑名单绕过

黑名单是什么意思想必也不用多做解释了,服务器将一些存在危险的文件扩展名加入至黑名单,只要所上传的文件类型在黑名单中,那我们的文件就寄了。

修改服务器配置绕过

而服务器对于一个文件是否执行是由开发人员进行配置的。

例如,在 Apache 服务器执行客户端请求的 PHP 文件之前,开发人员可能必须将以下指令添加到他们的/etc/apache2/apache2.conf文件中

1
2
>LoadModule php_module /usr/lib/apache2/modules/libphp.so
>AddType application/x-httpd-php .php

如果我们能够通过一些方式改变服务器的这种配置,那么我们就能够让被列入黑名单的文件成功上传并且被执行。

当我们上传 .php 格式的文件时,我们会发现我们的文件被拒收了,和上一个类型的区别是:上一个类型的文件被接收了但是没有进行对文件内容的执行,而这个是直接不接收文件。

image-20220505094646811

接下来,我们要上传一个更改服务器配置的文件,修改方式如下

  • filename将参数 的值更改为.htaccess

  • Content-Type将标头 的值更改为text/plain.

  • 将文件的内容( PHP 有效负载)替换为以下 Apache 指令:

    1
    AddType application/x-httpd-php .l33t

这些操作能够使服务器将扩展名为 .l33t 的文件当做 php文件去执行。

image-20220505102641716

之后我们在我们原来提交的 php 文件请求中修改文件后缀名

image-20220505102855928

可以发现文件成功上传并且被执行了,接下来在浏览器中访问我们所上传的文件即可。

修改文件扩展名绕过

通过修改文件扩展名达到绕过初步验证的目的,我们可以通过如下方式进行修改绕过

  • 提供多个扩展名。如:webshell.php.jpg
  • 添加尾随字符。如 webshell.php. 这种可以在初期绕过后缀验证,由于一些组件对尾随字符的去除,我们的文件最后会被解析成 webshell.php
  • 对字符进行 URL 编码。如:webshell%2Ephp
  • 使用 %00 截断字符。如:webshell.asp%00.jpg %00最终会被解释成为空字符串,也就是 null。null 后面的内容会被忽略。最终 webshell.asp.jpg 的内容会被写入 webshell.asp中。
  • 混合大小写。如:webshell.pHp

同样,在该靶场中我们所上传的文件遭到了拦截

image-20220505110522502

接下来尝试各种方式绕过,首先尝试多重后缀名

image-20220505110822012

上传成功了,但是我们发现我们并没有得到我们想要的东西,可能是因为我们的文件被当成图片去解析了。

image-20220505111101856

尝试%00截断,我们可以发现 %00 后的内容被丢弃了

image-20220505111336807

最后还是老样子,访问我们所上传的文件即可。

文件内容验证绕过

在这种类型的漏洞中,服务器依靠对文件内容的检查来判断所上传的文件是否为预期类型。例如:

在图像上传功能的情况下,服务器可能会尝试验证图像的某些内在属性,例如其尺寸。如果我们上传的是 php 脚本,它根本不具有任何的维度,因此,服务器可以推断它不可能是图像,并相应地拒绝上传。

当然这只是服务器对文件内容的一种验证方式之一。

还有一些类型的文件可能在文件的头部或者尾部有一些字节存放指定的内容用来标识文件,例如,JPEG 文件总是以FF D8 FF bytes 开头。

在这题中我们需要通过使用工具 exiftool 来创建带有一句话木马的图片。

在该工具所在的文件夹下添加一个 jpg 文件,使用命令

1
./exiftool -Comment="<?php echo 'START ' . file_get_contents('/home/carlos/secret') . ' END'; ?>" <YOUR-INPUT-IMAGE>.jpg -o polyglot.php

image-20220505164021195

生成的 polyglot 文件就是我们所需要的的目标文件。

对目标文件进行上传,然后在回应中找到我们的东西即可

image-20220505164401626

这道题目我尝试过用 cmd 的 copy 命令来制作木马图片,但是总是有如图错误

image-20220505164633732

也尝试过使用 notepad++ 制作图片,但是也无果,访问上传文件时这句 php 脚本被原封不动地输了出来。

利用竞争条件上传 webshell

我的 bp 插件 turbo intruder 寄了,先挖坑到时候再填。

  • 首先需要了解什么是竞争条件(race condition)

    竞争条件(Race Condition):计算机运行过程中,并发、无序、大量的进程在使用有限、独占、不可抢占的资源,由于进程无限,资源有限,产生矛盾,这种矛盾称为竞争(Race)。竞争条件(Race Condition)旨在描述一个系统或者进程的输出依赖于不受控制的事件出现顺序或者出现时机。由于两个或者多个进程竞争使用不能被同时访问的资源,使得这些进程有可能因为时间上推进的先后原因而出现问题。

简单来说就是多个进程需要访问一个互斥的资源,但这些进程对于该资源的访问顺序是由调度算法所决定的,也就是说我们无法知道这些进行进程对于互斥资源的访问顺序。因此,数据变化的结果取决于线程调度算法,即两个线程都“竞相”访问/改变数据。详细了解竞争条件

简单说说解法,从服务器解析我们所上传的 php 文件到发现是无用文件并丢弃者之间是有一个时间间隔的,在这个时间间隔中,资源就被 webshell 所占用,而我们的攻击也就利用这时间间隔。

利用 bp 的插件 Turbo 使我们能够在短时间内发送多个 web 请求,第一个请求是上传 webshell 的请求,第二个请求是访问我们所上传的 webshell 文件,而这个访问就是在服务器从判断我们的文件到丢弃我们的文件之间的时间间隔中进行的。

本文作者:GhDemi

本文链接: https://ghdemi.github.io/2022/05/11/File-Upload/

文章默认使用 CC BY-NC-SA 4.0 协议进行许可,使用时请注意遵守协议。