服务器端漏洞篇之文件上传漏洞专题
2023-8-13 15:51:25 Author: www.freebuf.com(查看原文) 阅读量:9 收藏

今天是之前梨子从来没发过的文件上传专题。

该系列共三篇,26个专题(截止2023.8.10),其中有21个专题的大部分内容已于2021年7-9月首发于安全客,由于某些原因,该系列后续更新部分梨子打算转投Freebuf社区(下称"社区")。因后续更新部分的部分内容为这21个专题中的,故在转投社区时会将更新部分一并加入对应的专题中,所以会与发布于安全客的版本略有出入,会更完整,望周知。

PortSwigger是信息安全从业者必备工具burpsuite的发行商,作为网络空间安全的领导者,他们为信息安全初学者提供了一个在线的网络安全学院(也称练兵场),在讲解相关漏洞的同时还配套了相关的在线靶场供初学者练习,本系列旨在以梨子这个初学者视角出发对学习该学院内容及靶场练习进行全程记录并为其他初学者提供学习参考,希望能对初学者们有所帮助。

梨子也算是Web安全初学者,所以本系列文章中难免出现各种各样的低级错误,还请各位见谅,梨子创作本系列文章的初衷是觉得现在大部分的材料对漏洞原理的讲解都是模棱两可的,很多初学者看了很久依然是一知半解的,故希望本系列能够帮助初学者快速地掌握漏洞原理。

burp官方说他们建议初学者先看服务器漏洞篇,因为初学者只需要了解服务器端发生了什么就可以了

文件上传漏洞就是在未经充分验证像文件名、类型、内容或大小时允许用户上传文件到文件系统。这就导致会有用户在一个简单的图片上传功能点在没有严格限制的情况下上传任意具有潜在危险的文件,甚至包括含有rce操作的脚本文件。

文件上传漏洞的影响通常取决于以下两个因素:

  • 网站未验证文件的哪个方面,比如大小、类型、内容等等

  • 文件上传成功后有那些限制

最坏的情况就是,网站未验证文件的类型,并且允许将这类文件(如.jsp或.php)作为代码执行。这种情况下,攻击者可以悄悄地上传一个作为webshell功能的代码文件,从而授予它们服务器完全的控制权。
如果网站未验证文件名,就可导致攻击者通过上传同名文件的方式轻而易举地覆盖关键文件。如果站点还存在目录穿越漏洞,攻击者甚至可以覆盖服务器上任意位置的任意文件。
如果网站没有保证文件大小在阈值范围内,攻击者可发动DOS攻击并借此填满磁盘。

正常来讲,开发者不会对上传不进行任何限制,但是他们只是做了他们认为很强的限制。
例如,开发者将危险的文件类型设置进黑名单,但是在检测文件扩展名的时候却忽略了解析差异。即使设置了黑名单,其实还是会忽略到很多危险的未知文件类型。
有的情况下,站点仅通过验证属性的方式检测文件类型,这很容易通过burp抓包修改。
这就产生了主机与目录之间的差异,从而被利用。

早些年,网站是完全由静态文件构成的,请求的路径与服务器上的文件目录是1:1对应的。但是随着技术的发展,网站越来越动态,用户请求的路径通常与文件系统没有直接关系,并且网站也在同时处理一些静态文件,如图表、图像之类的。
网站处理静态文件的过程都是大致相同的,用户请求即返回对应的静态文件。有时候站点通过解析请求中的路径识别文件的扩展名。站点通常是通过将扩展名与MIME类型之间的预配置列表进行对比的方式确定文件的类型。后面会发生什么取决于文件类型和服务器的配置。

  • 如果文件类型是不可执行的,如图像或html文件,服务器则只会在http响应中返回文件内容给客户端。

  • 如果文件类型是可执行的,如php文件,并且服务器被配置为允许执行这种类型的文件,服务器会先根据请求中的头和参数分配变量,然后带入脚本运行,然后再将输出通过http响应发送给客户端。

  • 如果文件类型是可执行的,但是服务器被配置为不执行这类文件,服务器一般会返回报错。不过有时候这些可执行文件的内容会以纯文本的形式发送给客户端,这就可能存在如泄漏源代码或其他敏感信息之类的风险。

从安全的角度看,最糟糕的情况就是网站允许用户上传动态脚本文件,如php、java或python文件并且还配置为将它们作为代码执行。这样我们部署webshell就非常容易了。
如果成功上传了webshell,我们就可能完全控制服务器。这就意味着你可以读写任意文件、泄漏敏感数据,甚至可以利用服务器对内部基础设施及其他服务器发起攻击。
例如,下面这行php代码可用于从服务器中读取任意文件:

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

上传后,就会在响应中接收到目标文件的内容。
一个更加通用的webshell可能长这样:

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

然后我们通过传入不同的请求参数就可以执行任意命令:

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

题目说有一个存在漏洞的图片上传点,并且它不会对上传的文件做任何限制。上传图片的功能点要用给的账号登进去。
image.png
我们发现它并没有限制上传文件的类型,所以我们直接上传一个txt,然后修改文件的内容,并且修改扩展名和文件类型。

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

image.png
然后我们通过访问头像即可触发执行我们上传的php脚本,从而看到/home/carlos/secret中的答案
image.png
成功解题!
image.png

有缺陷的文件类型验证

当我们提交HTML表单时,浏览器通常会在一个content-type为application/x-www-form-url-encoded的POST请求中发送提供的数据。这种方式适用于发送如姓名、地址等简单文本,而不适合发送大量二进制数据,如图像文件或pdf文档。这种情况下,content-type为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

[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标头,用于告诉服务器这个切片的内容类型。
站点可能会验证Content-Type和预期的MIME类型是否相匹配。如果站点只希望接收图像文件,那它可能会限制Content-Type为image/jpeg和image/png之类的类型。如果服务器默认相信请求包中的Content-Type即为预期的MIME类型,则可能会存在被抓包轻易绕过的风险。

题目已经给的很明显的,还是那个功能点,虽然已经限制用户上传非预期的文件类型的文件,但是它依赖于用户可控的输入的验证,这就很容易绕过了,我们抓包改一下就行了,这里需要比上一道题多改一个地方,就是将Content-Type修改为image/png或image/jpeg,直接上截图。
image.png
成功读到答案。
image.png
成功解


文章来源: https://www.freebuf.com/articles/web/374679.html
如有侵权请联系:admin#unsafe.sh