【Portswigger 学院】文件上传

教程和靶场来源于 Burpsuite 的官网 Portswigger:File upload vulnerabilities - PortSwigger

原理与危害

很多网站都有文件上传的功能,比如在个人信息页面允许用户上传图片作为头像。如果网站应用程序对用户上传的文件没有针对文件名、文件类型、文件内容或文件大小做充分的验证,就可能导致允许攻击者上传有潜在危险的文件,比如服务端的脚本文件,然后访问该文件以触发代码执行。

文件上传漏洞的危害取决于两个因素:

  • 网站应用程序对文件名、文件类型、文件内容或文件大小等参数中的哪一个没有做充分的验证。
  • 上传文件成功后受到哪些限制。

最坏的情况是文件类型没有受到服务器的任何限制,允许 .php.jsp 作为脚本文件执行,那么攻击者可以上传 .php.jsp 文件作为 webshell,接管服务器。

其他的一些危害:

  • 对文件名没有做验证,攻击者上传一个同名的文件,覆盖服务器上已存在的文件,如果还存在路径遍历漏洞,那么危害更大,可以覆盖服务器的系统文件。
  • 对文件大小没有做验证,攻击者上传一个非常大的文件,占用服务器的磁盘空间,也就是 DoS 攻击。

由于文件上传漏洞的危害很大,所以现在大部分网站应用程序都做了防御,能直接上传 .php.jsp 文件的网站很少看到了。然而,漏洞仍然会产生,这是因为开发人员坚信他们的防御足够有效。

静态文件处理

在刚学习 Web 安全时,看了很多课程和书籍,我们潜意识认为一个 URL 对应网站服务器上的一个文件,对应关系是 1:1,比如 http://example.com/includes/func.php 这个 URL 在网站服务器上对应的文件位于网站根目录下的 includes 目录下的 func.php 文件。这种理解在以前静态网站甚至 PHP 网站和 ASP 网站流行的时候确实是这样,这只不过是 Apache 或 IIS 等中间件正好这样管理站点的文件,但是现代 Web 应用程序已经不是这样 URL 与文件呈现一对一的映射关系,我们现在看到一个 URL 比如  https://csdn.net/mp_blog/creation/editor,在网站服务器并不存在一个路径为 <网站根目录>/mp_blog/creation/editor 的文件

当然,像图片、CSS 和 JS 等静态资源,Web 服务器仍然用一对一的映射关系处理它们,处理步骤是:解析 URL 中的 path 部分,识别出请求的文件的扩展名,然后根据扩展名匹配对应的 MIME,最后根据服务器预先的配置执行下一步:

  • 如果文件类型是不可执行的,就作为静态文件把文件内容响应给客户端。
  • 如果文件类型是可执行的,例如 PHP 文件,就创建运行环境,根据请求头和请求参数分配变量,然后执行脚本。
  • 如果文件类型是可执行的,但服务器被配置成不执行该类型的文件,就给客户端响应一个错误。不过,大多数情况下,服务器仍然把这些当成普通文本,将它们的内容返回给客户端,这一点特性可能被利用实现泄露代码或其他敏感信息的目的。

实验

实验说明:

服务器没有对上传的文件没做任何验证,上传一个 PHP 脚本并读取 /home/carlos/secret 文件的内容就能完成实验。

进入实验场景:

用账号 wiener:peter 登录,进入个人信息页面:

点击最下面的“浏览”按钮,选择一个 PHP 脚本上传,PHP 脚本的内容:

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

读取并返回 /home/carlos/secret 文件的内容。

点击“Upload”按钮上传文件,响应结果:

结果表示文件上传成功并给出保存的文件路径。除了这里可以看到保存的文件路径,还可以返回个人信息页面打开 F12 查看路径:

访问 /files/avatars/info.php 就能读取到 /home/carlos/secret 文件的内容:

复制这段数据,返回到首页点击 “Submit solution” 按钮提交即可。

绕过验证机制

Content-Type 伪造

提交表单后客户端发送一个 POST HTTP 请求,Content-Type 是请求包中的一个请求头,表示请求体的内容类型,如果是发送一段简短的文本,Content-Type 的值一般是 application/x-www-form-url-encoded,但如果发送的是一个大文件,比如 PDF,那么就得用文件上传的方式发送,此时的 Content-Type 是 multipart/form-data,表示表单数据多个部分,而 HTTP 请求包内容类似于这样:

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--

表单中每个输入之间用一段 ---------------------------012345678901234567890123456 字符串分割,第一个输入是图片,它也有自己的 Content-Type,值是 image/jpeg,表示这部分属于图片类型。第二个输入是没有 Content-Type,其实它相当于一个请求参数,参数名是 decsription,参数值是 

This is an interesting description of my image.

第三个输入同上。

如果服务器在接受上传的文件时,根据 Content-Type 决定文件的类型,那么就能让攻击者利用伪造绕过。如图:

结合路径遍历漏洞

上传文件的存储目录可能被限制为不允许执行脚本,这的确是可以实现的配置。例如,Apache 服务器可以针对某个特定目录配置特性,只要在目录下放置一个 .htaccess 文件,里面配置如下的指令:

php_flag engine offphp_flag engine off

那么当前目录下的所有脚本被访问时都不会运行,而是当作普通文本返回。

尝试利用路径遍历漏洞绕过这个限制,把文件上传到存储目录的上一级目录:

访问该文件时注意它的路径,avatars/../info.php 其实就是 info.php。

这里用 URL 编码处理了斜杠,因为应用程序在保存上传之前对文件名做了一次 URL 解码处理:

<?php
$target_dir = "avatars/";
$target_file = urldecode($target_dir.$_FILES["avatar"]["name"]);if (strpos($target_file, ".htaccess")) {echo "The upload of .htaccess files is prohibited.";http_response_code(403);
} else if (move_uploaded_file($_FILES["avatar"]["tmp_name"], $target_file)) {echo "The file ". htmlspecialchars( $target_file). " has been uploaded.";
} else {echo "Sorry, there was an error uploading your file.";http_response_code(403);
}
?>

如果没有做 URL 解码处理,文件名中的 ../..\ 会被去掉。我在本地做了一个测试,如图:

也就是说文件上传漏洞结合路径遍历漏洞需要满足一定的条件。

重写服务器配置

有些应用程序对文件上传功能的安全防护是设置一个后缀名黑名单,里面包含不允许上传的文件后缀名,但这仍然存在风险,因为无法囊括所有不合法的后缀名,比如 .php5.shtml 等等,这些可能会被忽略。另外,相关配置文件的文件名或后缀名也应该被列为黑名单。

大多数 Web 服务器并不是在一开始安装成功后就能执行文件的,像 Apache,要执行 PHP 脚本,需要在 /etc/apache2/apache2.conf 配置文件中添加如下指令:

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

意思是加载 php 模块,以及当访问后缀名为 .php 的文件时,作为 php 脚本执行。

不止 Apache,Nginx 和 IIS 也都是要做一些配置才能执行脚本。

除了 apache2.conf 这个系统级的配置文件,Apache 服务器允许在每个目录下放置一个 .htaccess 文件,在该文件中添加的指令可以覆盖和补充 apache2.conf 的配置。如果应用程序允许上传 .htaccess,那么就能利用它绕过安全防护,执行代码。

首先,第一步是先上传 .htaccess

文件内容:

AddType application/x-httpd-php .png

这表示 .png 后缀的文件也被当成 PHP 脚本执行。

第二步是上传包含 PHP 代码的 .png 文件:

最后一步是访问 phpinfo.png 文件,触发代码执行。

IIS 服务器也有一个类似的配置文件,名为 web.config,它的指令示例:

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

表示 .json 文件被当成 json 发送给客户端。

PS:通常,.htaccess 和 web.config 被从客户端禁止访问。

混淆文件后缀

下面列举一些混淆技巧:

  • 如果在验证文件后缀名是否合法时区分大小写,但是在后缀名映射 MIME 时不区分大小写,那么可尝试大写后缀,比如 exploit.pHpexploit.PHP 等。
  • 多后缀名,比如 exploit.php.jpg。(Apache 多后缀解析漏洞)
  • 末尾加点,比如 exploit.php.  。(Windows不允许文件名末尾有点,如果有,会自动去掉)
  • 在验证文件后缀名之前没有做 URL 解码处理,但是在之后做了,那么可用 URL 编码绕过安全验证,比如 exploit%2Ephp
  • 如果服务器用低级语言如 C/C++ 写的,那么可尝试空字节绕过,比如 exploit.asp%00.jpg
  • 结合 IIS 6.0 解析漏洞,如:exploit.asp;.jpg
  • 如果应用程序匹配到不合法的后缀名后只做一次删除处理,而不是递归删除,那么可双写后缀绕过,比如 exploit.p.phphp

下图是利用空字节绕过的一个例子:

下面是应用程序处理这个文件名的代码,我们看看如何处理这个 %00 的:

<?php
$target_dir = "avatars/";
$target_file = urldecode($target_dir . $_FILES["avatar"]["name"]);
$uploadOk = true;$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));if($imageFileType != "jpg" && $imageFileType != "png") {echo "Sorry, only JPG & PNG files are allowed\n";$uploadOk = false;
}//去掉空字节及其后面的字符
$target_file = strtok($target_file, chr(0));if ($uploadOk && move_uploaded_file($_FILES["avatar"]["tmp_name"], $target_file)) {echo "The file ". htmlspecialchars( $target_file). " has been uploaded.";
} else {echo "Sorry, there was an error uploading your file.";http_response_code(403);
}

这很容易看懂。然而,在实际的场景中,并不会有开发人员会这样处理文件名,让攻击者有利用空字节绕过的可能,更多是服务器由 C/C++ 开发时才有可能出现。

文件内容验证绕过

当应用程序不信任 Content-Type 所指示的那样判断一个文件的类型,可能会直接通过验证文件的内容来判断。对于这种情况,最简单的验证方式就是查看文件开头几个字节,这几个字节又称魔术数字,大多数类型的文件都会在开头设置独一无二的字节序列,比如 JPEG 文件的就是 FF D8 FF,这种验证方式很容易绕过,因为攻击者也能在脚本的开头放置这几个字节并且不会影响代码执行。

比较复杂的情况是,应用程序用一些图片处理函数来判断上传的文件的数据是否真的是合法的图片数据,比如获取图片的尺寸,脚本文件就不会有这种数据。但是,攻击者可以将代码嵌入到图片的一些数据区,这些数据区不会破坏图片本身的数据和图片的渲染,比如 JPEG 图片的注释部分,用 Exiftool 工具可以做到这些事情。(Exiftool 工具在 kali 系统中已默认安装)

Exiftool 将 PHP 代码嵌入到 JPG 图片的注释部分:

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

意思是将 -Comment 参数指定的内容嵌入到 test.jpg 的注释部分,最后生成 polyglot.php 文件。

条件竞争上传文件

有些应用程序接收到上传的文件后先保存到网站的一个目录下,接着对文件的安全性做验证,如果文件被判断为不安全的就会删除该文件,这样的处理是有问题。在保存到目录后和被判断为不安全而删除之前存在一个时间空隙,攻击者在这段空隙访问所上传的文件就能执行该文件,这是能够做到,利用预先写好的程序快速不停地访问即可。

现代开发框架都内置了处理文件上传的组件,它们通常都能够阻止这类漏洞,其处理步骤是

  1. 把上传的文件保存到一个沙盒化的临时目录(这里的文件被隔离且无法被访问到并执行);
  2. 重命名为一个随机字符串以避免文件覆盖;
  3. 做安全性验证,如果文件被判断为安全的,就移动文件到最终保存的目录,否则就删除。

如果开发人员自己编写文件上传处理程序,那么就有可能存在这类漏洞。

攻击者很难在黑盒测试中找到这种漏洞,除非他能找到应用程序的源代码,通过审计发现这种漏洞。

另外,还有一种情况可能发生条件竞争文件上传漏洞,就是让用户提供一个 URL 来保存文件,这一般只能由开发人员自己编写处理程序,也必须先下载一份文件副本到本地,然后再做安全性验证,所以这种情况很容易出现漏洞。

如果上传的文件或通过 URL 下载的文件保存到一个具有随机名称的临时目录,这一般不太可能被攻击者知道,但如果临时目录是伪随机数,那么仍然有可能被攻击者用暴力破解的方法知道。

为了让条件竞争上传文件的攻击更容易,攻击者会上传一个恶意的大文件,里面填充大量无用字符,但不会影响到里面的代码被执行,应用程序处理这类大文件会处理得更久,那么文件在文件系统上停留的时间更久,也就更容易被攻击者趁机访问。

客户端攻击

能上传带有恶意代码的文件是最严重的漏洞,这是针对服务器的攻击,但文件上传也能用于针对客户端攻击。上传一个 HTML 文件或 SVG 图像,里面包含 XSS 代码,那么就相当于是一个存储型 XSS 漏洞了,然后把文件的 URL 发给受害者,因为域名是合法的,所以更容易被信任。(注意,上传的文件如果被保存到另一个网站,那么要考虑同源策略的影响)

PUT 文件上传

某些服务器被配置为允许 HTTP PUT 请求方法,这种请求方法是用于上传文件,攻击者可先用 OPTIONS 请求方法查看网站是否支持 HTTP PUT 请求方法,然后再尝试上传文件。

PUT 上传请求示例:

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'); ?>

防护

下面是一些防护方法:

  • 使用后缀名白名单而不是黑名单,因为列举出所有允许的后缀名更容易。
  • 文件名不能包含 ../ 序列。
  • 重命名文件避免文件覆盖。
  • 对文件做完安全性验证再移动它到永久保存的目录,在此之前保存到临时目录。
  • 尽量使用框架内置的文件上传处理组件,而不是自己编写。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/41277.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端基础:JavaScript(篇一)

目录 JavaScript概述 JavaScript历史&#xff1a; 须知&#xff1a; 基本语法 变量 代码 运行 数据类型 1、数值型(number)&#xff1a; 代码 运行 2、布尔型(boolean)&#xff1a; 代码 运行 3、字符串型&#xff1a; 代码 运行 4、 undefined类型 代码…

TCP的pop网络模式

TCP的pop网络模式 1、tcp连接的状态有以下11种 CLOSED&#xff1a;关闭状态LISTEN&#xff1a;服务端状态&#xff0c;等待客户端发起连接请求SYN_SENT&#xff1a;客户端已发送同步连接请求&#xff0c;等待服务端相应SYN_RECEIVED&#xff1a;服务器收到客户端的SYN请请求&…

MySQL 基本语法讲解及示例(下)

第六节&#xff1a;如何检索资料 在本节中&#xff0c;我们将介绍如何使用SQL语句检索数据库中的资料&#xff0c;具体包括选择特定列、排序、条件过滤以及组合排序等操作。我们以一个名为student的表格为例&#xff0c;演示不同的检索方法。 初始表格 student student_idname…

Python中frozenset,秒变不可变集合,再也不用担心多线程了!

目录 1、Frozenset基础介绍 🌐 1.1 Frozenset定义与创建 1.2 不可变集合特性 1.3 与Set的区别对比 2、Frozenset操作实践 🧩 2.1 初始化与添加元素尝试 2.2 成员测试: in & not in 2.3 集合运算: 并集、交集、差集 2.4 使用场景示例: 字典键、函数参数默认值 …

劲爆!华为享界两款新车曝光,等等党有福了

文 | AUTO芯球 作者 | 雷慢 劲爆啊&#xff0c;北汽的一份环境影响分析报告&#xff0c; 不仅曝光了享界S9的生产进展&#xff0c; 还泄露了自家的另两款产品&#xff0c; 第一款是和享界S9同尺寸的旅行车&#xff0c; 我一看&#xff0c;这不是我最喜欢的“瓦罐”吗&…

v-html 空格/换行不生效

接口返回的内容如下&#xff1a;有空格有换行&#xff0c;但 使用v-html无效 需加css样式 white-space: pre-wrap; <div class"pretty-html" v-html"Value"></div>.pretty-html {white-space: pre-wrap; /* 保留空格和换行&#xff0c;并允许…

掌握麦肯锡精英的6个技巧,你也能成为1%的精英!

不知道大家有没有想过&#xff0c;我们和那些全球顶尖精英的差距可能只有1%&#xff0c;只是99%的人还不知道这件事。 今天给大家推荐一本好书&#xff0c;《你和麦肯锡精英的差别只有1%》。优思学院发现&#xff0c;在我们的六西格玛、精益管理的学生中很多人对自己没有自信。…

软通动力子公司鸿湖万联最新成果SwanLink AI亮相世界人工智能大会

7月4日&#xff0c;2024世界人工智能大会暨人工智能全球治理高级别会议&#xff08;WAIC 2024&#xff09;在上海拉开帷幕&#xff0c;软通动力董事长兼首席执行官刘天文受邀出席开幕式。其间&#xff0c;软通动力携子公司鸿湖万联深度参与到大会各项活动中&#xff0c;并全面展…

数字化产科管理平台全套源码,java产科电子病历系统源码

数字化产科管理平台全套成品源码&#xff0c;产科电子病历系统源码&#xff0c;多家大型妇幼专科医院应用案例。源码完全授权交付。 数字化产科管理平台&#xff08;智慧产科系统&#xff09;是为医院产科量身定制的信息管理系统。它管理了孕妇从怀孕开始到生产结束42天以内的一…

BERT--学习

一、Transformer Transformer&#xff0c;是由编码块和解码块两部分组成&#xff0c;其中编码块由多个编码器组成&#xff0c;解码块同样也是由多个解码块组成。 编码器&#xff1a;自注意力 全连接 多头自注意力&#xff1a;Q、K、V 公式&#xff1a; 解码块&#xff1…

【anaconda】—“conda info“命令后conda配置和环境信息的理解

文章目录 conda配置和环境信息的理解 conda配置和环境信息的理解 安装anaconda成功后&#xff0c;打开cmd&#xff0c;输入"conda info"命令&#xff0c;结果显示如下&#xff1a; conda的配置和环境信息的输出。以下是对每个字段的解释&#xff1a; active environm…

H2 Database Console未授权访问漏洞封堵

背景 H2 Database Console未授权访问&#xff0c;默认情况下自动创建不存在的数据库&#xff0c;从而导致未授权访问。各种未授权访问的教程&#xff0c;但是它怎么封堵呢&#xff1f; -ifExists 很简单&#xff0c;启动参数添加 -ifExists &#xff0c;它的含义&#xff1a…

中电金信:加快企业 AI 平台升级,构建金融智能业务新引擎

在当今数字化时代的浪潮下&#xff0c;人工智能&#xff08;AI&#xff09;技术的蓬勃发展正为各行业带来前所未有的变革与创新契机。尤其是在金融领域&#xff0c;AI 模型的广泛应用已然成为提升竞争力、优化业务流程以及实现智能化转型的关键驱动力。然而&#xff0c;企业在积…

【C++ 】解决 C++ 语言报错:Null Pointer Dereferenc

文章目录 引言 在 C 编程中&#xff0c;空指针解引用&#xff08;Null Pointer Dereference&#xff09;是一种常见且危险的错误。当程序试图通过空指针访问内存时&#xff0c;会导致程序崩溃或产生不可预期的行为。本文将详细探讨空指针解引用的成因、检测方法及其预防和解决…

简单配置VScode轻量级C++竞赛环境

1. 安装拓展 Chinese是中文&#xff0c;需要重启才可以运行&#xff0c;C/C拓展只是进行语法代码提示&#xff0c;不需要进行任何配置修改&#xff0c;默认即可。 2. 创建文件 如上图创建好各级文件夹&#xff0c;其中C是工作文件夹&#xff0c;.vscode是配置文件夹&#xff0…

【网络安全】Host碰撞漏洞原理+工具+脚本

文章目录 漏洞原理虚拟主机配置Host头部字段Host碰撞漏洞漏洞场景工具漏洞原理 Host 碰撞漏洞,也称为主机名冲突漏洞,是一种网络攻击手段。常见危害有:绕过访问控制,通过公网访问一些未经授权的资源等。 虚拟主机配置 在Web服务器(如Nginx或Apache)上,多个网站可以共…

学习测试2-方法

设计测试用例 设计测试用例的万能公式 (在没有需求文档的情况下&#xff09; 软件质量模型 效率就是性能 兼容性测试 浏览器 谷歌 IE 火狐 苹果 百度 Windows7 10 11 苹果系统 app 不同品牌 小米 vivo 华为 苹果 不同的操作系统 安卓 鸿蒙 苹果 -----------------------…

TikTok马来西亚直播网络怎么配置?

TikTok是一款全球流行的社交媒体应用&#xff0c;在东南亚地区拥有大量用户。在马来西亚这个多元化的国家&#xff0c;配置高效稳定的直播网络对TikTok的运营至关重要。 配置马来西亚直播网络的必要性 广泛的地理覆盖&#xff1a;马来西亚包括大片陆地和众多岛屿&#xff0c;网…

性能压测 -优化 Nginx的动静分离

两件事情 1.以后将所有的项目的静态资源都应该放在nginx里面 2.nginx 规则&#xff1a;/static/***所有请求都有nginx直接返回 nginx 配置一下配置文件&#xff0c;然后把html 的静态资源&#xff0c;绑定好是Nginx优先级高的静态资源路径&#xff0c;就去交给nginx静态资源…

Prometheus + Grafana 监控系统搭建使用指南-Nacos 接入 Prometheus 监控

Nacos 接入 Prometheus 监控 系列文章目录 Prometheus 的安装部署Grafana的安装部署Linux服务器接入Prometheus监控-Node Exporter 安装指南Prometheus 接入SpringBoot微服务监控Mysql 接入 Prometheus RocketMQ 接入Prometheus 监控ElasticSearch 接入 PrometheusNacos 接入…