一、文件上传漏洞
1、意义:
1、原理:文件上传漏洞是指Web服务器允许用户将文件上传到其文件系统,而不充分验证文件的名称、类型、内容或大小等内容。如果不能正确地执行这些限制,可能意味着即使是基本的图像上传功能也可以用来上传任意的和潜在危险的文件。这甚至可以包括支持远程代码执行的服务器端脚本文件
2、危害:在某些情况下,上传文件的行为本身就足以造成损害。其他攻击可能涉及对文件的后续HTTP请求,通常是为了触发服务器执行该文件
2、影响
1、文件上传漏洞的影响通常取决于两个关键因素:
网站未能正确验证文件的哪个方面,无论是文件的大小、类型、内容等。
文件成功上载后会对其施加哪些限制
2、在最坏的情况下,文件的类型没有得到正确的验证,服务器配置允许某些类型的文件(如.php和.jsp)作为代码执行。在这种情况下,攻击者可能会上载充当Web外壳的服务器端代码文件,从而有效地授予他们对服务器的完全控制权。
3、如果文件名未正确验证,则攻击者只需上载同名文件即可覆盖重要文件。如果服务器也容易受到目录遍历的攻击,这可能意味着攻击者甚至能够将文件上载到意想不到的位置。
4、如果无法确保文件大小预期阈值范围内,还可能会启用某种形式的拒绝服务(DoS)攻击,攻击者会借此填满可用磁盘空间。
3、产生
1、现状:考虑到相当明显的危险,很少有网站对用户可以上传的文件没有任何限制。更常见的情况是,开发人员实现他们认为是健壮的验证,但这些验证要么存在固有缺陷,要么很容易被绕过。
2、绕过:如试图将危险的文件类型列入黑名单,但在检查文件扩展名时无法考虑解析差异。与任何黑名单一样,它也很容易意外地忽略了更模糊的文件类型,这些文件类型可能仍然是危险的。
3、工具:在其他情况下,网站可能会尝试通过验证攻击者可以使用Burp Proxy或Repeater等工具轻松操纵的属性来检查文件类型。
4、结论:即使是稳健的验证措施也可能在构成网站的主机和目录网络中应用不一致,导致可能被利用的差异。
4、服务器处理静态文件请求的机制
1、前提:在研究如何利用文件上传漏洞之前,必须了解服务器如何处理静态文件请求
2、历史:网站几乎完全由静态文件组成,当用户请求时,这些静态文件将被提供给用户。因此,每个请求的路径可以与服务器文件系统上的目录和文件的层次结构1:1映射。
3、现状:网站的动态性越来越强,请求的路径通常与文件系统没有任何直接关系。但web服务器仍然处理对一些静态文件的请求,包括样式表、图像等等。
4、结论:处理这些静态文件的过程在很大程度上仍然相同。在某些时候,服务器解析请求中的路径以标识文件扩展名。然后使用该映射来确定所请求文件的类型,通常是将其与扩展名和MIME类型之间的预配置映射列表进行比较。接下来会发生什么取决于文件类型和服务器的配置。
5、示例
(1)不可执行文件:文件类型是不可执行的,例如图像或静态HTML页面,则服务器可能只会在HTTP响应中将文件的内容发送到客户机。 (2)可执行文件:文件类型为可执行文件(如PHP文件),并且服务器配置为执行此类型的文件,则服务器将在运行脚本之前根据HTTP请求中的标头和参数分配变量。然后可以在HTTP响应中将结果输出发送到客户端。 (3)可执行文件,但配置不执行:文件类型为可执行文件,但服务器不是配置为执行此类型的文件时,它通常会以错误响应。但在某些情况下,文件的内容可能仍以纯文本形式提供给客户端。此类错误配置偶尔会被利用来泄漏源代码和其他敏感信息。
二、利用不受限制的文件上载来部署Web Shell
1、简述:
1、从安全角度来看,最糟糕的情况是网站允许您上载服务器端脚本(如PHP、Java或Python文件),并且还配置为将它们作为代码执行。这使得在服务器上创建自己的web shell变得很简单。
2、Web shell是一种恶意脚本,攻击者只需通过向正确的端点发送HTTP请求,就可以在远程Web服务器上执行任意命令
3、如果能够成功地上传一个web shell,那么实际上就拥有了对服务器的完全控制。这意味着可以读取和写入任意文件、泄露敏感数据,甚至使用服务器来针对内部基础架构和网络外部的其他服务器发起攻击。
例如,以下PHP一行程序可用于从服务器的文件系统读取任意文件: <?php echo file_get_contents('/path/to/target/file'); ?> 上传后,发送此恶意文件的请求将在响应中返回目标文件的内容
1、更通用的web shell可能如下所示: <?php echo system($_GET['command']); ?> 2、此脚本允许通过查询参数传递任意系统命令,如下所示: GET /example/exploit.php?command=id HTTP/1.1
4、涉及实验:
实验1:通过web shell上传的远程代码执行
实验1:通过web shell上传的远程代码执行
本实验包含易受攻击的图像上载函数。在将用户上传的文件存储到服务器的文件系统之前,它不会对这些文件执行任何验证。
要完成实验,请上传一个基本的PHP Web shell,并使用它来过滤文件/home/carlos/secret的内容并提交
已有账号:wiener:peter
part1:
通过Burp代理流量时,登录您的帐户,注意上传头像图像的选项
上传任意图片,然后返回您的帐户页面(页面上现在显示了虚拟形象的预览)
(测试发现,其实对于上传的文件类型,没有任何限制)
效果展示
part2:
分析数据包
HTTP历史记录-----单击过滤器栏以打开"过滤器设置"对话框------启用"图像"复选框
在代理历史记录中,请注意您的图像是使用 GET 请求/files/avatars/<获取的
part3:
完成实验
电脑上,创建一个php的文件,其中包含用于获取Carlos秘密文件内容的脚本(或者直接使用后门代码get shell),如:
<?php echo file_get_contents('/home/carlos/secret'); ?>
使用头像上传功能上传恶意PHP文件
并上传成功(因为不是图片,所以加载不出来)
在响应中可以回显加载的内容,被以text文件形式显示
也可以在Burp Repeater中,更改请求的路径以指向PHP文件
完成实验
三、利用文件上载的错误验证
1、简述:
1、现状:不太可能找到对文件上传攻击没有任何保护的网站。但仅仅因为防御到位,并不意味着他们是强大的。
2、将了解Web服务器尝试验证和清理文件上载的一些方法,以及如何利用这些机制中的缺陷来获取用于远程代码执行的Web shell。
2、有缺陷的文件类型验证
1、提交HTML表单时,浏览器通常将提供的数据发送到后请求的内容类型application/x-www-form-url-encoded。这适用于发送简单文本,如姓名、地址等,但不适用于发送大量二进制数据,如整个图像文件或PDF文档。在本例中,内容类型multipart/form-data是优选的方法。
2、考虑一个表单,其中包含用于上载图像、提供图像描述和输入用户名的字段。提交这样的表单可能会导致类似下面的请求:
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--
3、处理:消息正文被拆分为表单的每个输入的单独部分。每个部分都包含一个Content-Disposition头,它提供了与之相关的输入字段的一些基本信息。这些单独的部分还可能包含它们自己的Content-Type头,它告诉服务器使用此输入提交的数据的MIME类型。
4、利用:网站尝试验证文件上载的一种方法是检查此特定于输入的Content-Type标头是否与预期的MIME类型匹配。如果服务器只需要图像文件,它可能只允许image/jpeg和image/png这样的类型。当服务器隐式信任此标头的值时,可能会出现问题。如果没有执行进一步的验证来检查文件的内容实际上是否与假定的MIME类型匹配,则可以使用Burp Repeater之类的工具轻松绕过此防御
5、涉及实验:
实验2:通过内容类型限制旁路的Web shell上载
实验2:通过内容类型限制旁路的Web shell上载
本实验包含易受攻击的图像上载函数。它试图阻止用户上载意外的文件类型,但依赖于检查用户可控的输入来验证这一点。
要完成实验,请上传一个基本的PHP Web shell,并使用它来过滤文件/home/carlos/secret的内容并提交
已有账号:wiener:peter
part1:
登录并上传图像作为头像,然后返回帐户页面
HTTP历史记录中,请求类型GET /files/avatars/
在您的系统上,创建一个php文件,其中包含一个用于获取Carlos秘密内容的脚本。
例如: <?php echo file_get_contents('/home/carlos/secret'); ?>
图片样式未变,说明有检测(上传失败)
分析数据包(对文件类型应该是有检测)
part2:
拦截数据包进行分析
响应表明您只能上载MIME类型为image/jpeg或image/png的文件
修改Content-Type值,并发送
文件成功上传
part3:
完成实验
直接在HTTP记录中查看响应包中返回的数据
Cw5LnCcKlcIEB9qeBBXq5bQl1t88jRx9
3、防止在用户可访问的目录中执行文件
1、虽然首先防止危险的文件类型被上传显然更好,但第二道防线是阻止服务器执行任何从网络上溜走的脚本。
2、作为预防措施,服务器通常只运行那些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
3、这种行为可能会提供一种泄漏源代码的方法,但它会使任何创建web shell的尝试无效
4、这种配置通常因目录而异。用户提供的文件上载到的目录可能比文件系统上其他位置(假定最终用户无法访问)具有更严格的控制。如果能找到一种方法将脚本上载到不应该包含用户提供的文件的不同目录,那么服务器最终可能会执行您的脚本
5、还应该注意到,即使可能将所有请求发送到同一个域名,这通常指向某种反向代理服务器,如负载平衡器。请求通常由其他服务器在后台处理,这些服务器的配置也可能有所不同。
6、涉及实验:
实验3:经由路径遍历的Web外壳上载
实验3:经由路径遍历的Web外壳上载
本实验包含易受攻击的图像上载函数。服务器配置为阻止执行用户提供的文件,但利用次要漏洞可以绕过此限制。
要完成实验,请上传一个基本的PHP Web shell,并使用它来过滤文件/home/carlos/secret的内容并提交
已有账号:wiener:peter
part1:
登录并上传图像作为您的头像,然后返回帐户页面
电脑上,创建一个php文件,其中包含一个用于获取Carlos秘密内容的脚本。
例如: <?php echo file_get_contents('/home/carlos/secret'); ?>
虽然上传成功,但服务器没有执行脚本并返回输出,而是以纯文本形式返回PHP文件的内容
part2:
在Burp的代理历史记录中,找到用于提交文件上传的POST/my-account/avatar请求,并将其发送到Burp Repeater
找到与PHP文件相关的请求主体部分。在Content-Disposition标头中,更改文件名以包含目录遍历序列: Content-Disposition: form-data; name="avatar"; filename="../1.php"
注意响应显示文件avatars/1.php已经上传。这表明服务器正在从文件名中剥离目录遍历序列
part3:
进行URL编码
filename="..%2fexploit.php"
程序对URL编码进行了解码
刷新主页,并在Burp的代理历史记录中,找到GET /files/avatars/..%2f1.php文件请求,发送到repeater
将请求修改为../1.php
返回包中包含了数据
4、危险文件类型的黑名单不足
1、机制:防止用户上传恶意脚本的一个更明显的方法是将具有潜在危险的文件扩展名(如.php)列入黑名单。黑名单的做法是有内在缺陷的,因为很难显式地阻止每一个可能用于执行代码的文件扩展名。这种黑名单有时可以通过使用不太为人所知的、仍然可以执行的替代文件扩展名(如.php5、.shtml等)来绕过。
2、覆盖服务器配置
服务器通常不会执行文件,除非它们被配置为执行文件。
例如,在Apache服务器执行客户端请求的PHP文件之前,开发人员可能需要将以下指令添加到/etc/apache 2/apache2.conf文件中: LoadModule php_module /usr/lib/apache2/modules/libphp.so AddType application/x-httpd-php .php
3、许多服务器还允许开发人员在各个目录中创建特殊的配置文件,以便覆盖或添加到一个或多个全局设置。例如,Apache服务器将从名为. htaccess网站如果存在话。
同样,开发人员可以使用web.config文件。这可能包括如下指令,在本例中,这些指令允许将JSON文件提供给用户:
Web服务器使用这些类型的配置文件(如果存在),但通常不允许使用HTTP请求访问它们。但可能偶尔会发现服务器无法阻止上载自己的恶意配置文件。在这种情况下,即使需要的文件扩展名被列入黑名单,也可以欺骗服务器将任意的自定义文件扩展名映射到可执行MIME类型
————
4、涉及实验:
实验4:通过扩展黑名单旁路的Web外壳上传
5、混淆文件扩展名
即使是最详尽的黑名单也可以使用经典的模糊技术绕过。假设验证代码区分大小写,无法识别exploit.pHp实际上是一个.php文件。如果随后将文件扩展名映射到MIME类型的代码不区分大小写,则这种差异允许您偷偷地让恶意PHP文件通过最终可能由服务器执行的验证。
方法: 1、提供多个扩展名。根据用于解析文件名的算法,以下文件可能被解释为PHP文件或JPG图像:exploit.php.jpg 2、添加尾随字符。有些组件会去除或忽略尾随的空格、点等:exploit.php. 3、尝试对点、正斜杠和反斜杠使用URL编码(或双URL编码)。如果在验证文件扩展名时没有解码该值,但后来在服务器端解码了该值,这也会允许您上传恶意文件,否则这些文件将被阻止:利用%2Ephp 4、在文件扩展名前添加分号或URL编码的空字节字符。例如,如果验证是用PHP或Java等高级语言编写的,但服务器使用C/C++中的低级函数来处理文件,则这可能会导致文件名末尾的处理不一致:开发工具. asp;.jpg或利用. asp%00.jpg 5、尝试使用多字节unicode字符,在unicode转换或规范化之后,这些字符可能会转换为空字节和点。像这样的序列xC0 x2E,xC4 xAE或xC0 xAE可以被翻译成x2E如果文件名被解析为UTF-8字符串,但在用于路径之前转换为ASCII字符。
6、其他防御措施包括剥离或替换危险的扩展名,以防止文件被执行。如果此转换不是递归应用的,则可以将禁用的字符串放置在适当的位置,以便在删除它时仍然保留有效的文件扩展名。
例如,php语言(非递归剥离) exploit.p.phphp
————
7、涉及实验:
实验5:通过模糊文件扩展名的Web外壳上传