一文详述文件上传漏洞

2025-04-10 7 0

文件上传漏洞

文章 - Upload-labs通关手册 - 先知社区

文章 - 由Upload-labs的几关引发的思考 - 先知社区

文件上传漏洞(详解) - FreeBuf网络安全行业门户

漏洞描述

文件上传漏洞是指由于程序员未对上传的文件进行严格的验证和过滤,而导致用户可以向服务器上传可执行的动态脚本文件。如常见的头像上传、图片上传、oa 办公文件上传、媒体上传、允许用户上传文件之处,如果过滤不严格,恶意用户利用文件上传漏洞,上传有害的可以执行脚本文件到服务器中,可以获取服务器的权限,进一步危害服务器。

危害:非法用户上传的恶意文件能够控制整个网站,甚至是控制服务器。这样的恶意脚本文件,被称为 webshell,也被称为网页后门。Webshell功能很强大,可以很方便地查看服务器信息,查看目录,执行系统命令等。

相关知识

文件上传的一般过程:

  1. 客户端准备:用户通过文件选择器选择要上传的文件。
  2. 上传请求:提交表单,表单会将文件数据和表单字段打包成一个HTTP请求发送到服务器。
  3. 服务器接收并解析请求:服务器端解析HTTP请求,提取文件内容和表单字段。在PHP中,文件信息存储在$_FILES超全局数组中,文件内容会临时存储在服务器的临时目录中。

4.文件验证:服务器端会对上传的文件进行验证,以确保文件的安全性和合法性。

5.文件存储:验证通过后,服务器会将文件从临时目录移动到指定的存储位置。

  1. 响应客户端:服务器端完成文件存储后,会向客户端发送一个响应,告知上传是否成功。
  2. 客户端处理响应:客户端接收到服务器的响应后,可以根据响应内容提示用户上传结果。

$_FILES超全局数组

在PHP中处理文件上传时,文件的相关信息存储在$_FILES超全局数组中,而文件的实际内容则存储在服务器的临时文件目录中。文件信息存储在$_FILES超全局数组中,用于存储与文件上传相关的元数据。当用户通过表单上传文件时,$_FILES数组会自动填充以下信息:

键名

说明

name

客户端上传文件的原始文件名(如example.jpg)。

type

文件的MIME类型(如image/jpeg),它来自 HTTP 请求中的 Content-Type 头。这是客户端提供的信息,可能不可靠,需要服务器端验证。

size

文件的大小(以字节为单位)。

tmp_name

文件在服务器临时目录中的存储路径。

error

文件上传过程中可能出现的错误代码(如UPLOAD_ERR_OK表示无错误)。

MIME(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展)类型是一种用于标识文件类型的标准方式,最早用于电子邮件系统,现在广泛用于 HTTP、浏览器、文件系统等场景。MIME 类型主要用于告诉服务器或客户端(如浏览器),某个文件或数据属于哪种类型,以便正确解析和处理。

Error键

error键会返回一个整数值,表示文件上传过程中是否发生错误以及错误的类型。客户端可以根据这些值判断上传是否正常。

文件上传错误代码及其含义:

错误代码常量

含义

0

UPLOAD_ERR_OK

没有错误发生,文件上传成功。

1

UPLOAD_ERR_INI_SIZE

上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。

2

UPLOAD_ERR_FORM_SIZE

上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。

3

UPLOAD_ERR_PARTIAL

文件只有部分被上传。

4

UPLOAD_ERR_NO_FILE

没有文件被上传。

6

UPLOAD_ERR_NO_TMP_DIR

缺少临时文件夹。PHP 4.3.10 和 PHP 5.0.3 开始引入。

7

UPLOAD_ERR_CANT_WRITE

文件写入失败。PHP 5.1.0 开始引入。

8

UPLOAD_ERR_EXTENSION

PHP 扩展阻止了文件上传。PHP 5.2.0 开始引入。

漏洞分类

一、直接文件上传漏洞

上传无任何限制,服务器端对上传文件没有进行有效的文件类型、大小、扩展名、内容等检查。攻击者可以直接上传Webshell,利用该漏洞直接控制网站服务器。

二、有条件的文件上传漏洞

这种漏洞虽然对文件上传做了一定的限制,但存在不严谨的安全检查或绕过逻辑,主要包括以下几种情况:

  1. 前端验证不足,只在前端使用 JavaScript 限制文件类型、大小等,可以通过工具直接构造 HTTP 请求,绕过前端验证。
  2. 文件头检测缺陷,开发者可能仅通过检测文件的头部(Magic Number)来判断文件类型。可通过修改文件内容或者利用部分文件头信息与实际内容不符的情况绕过检测。
  3. 文件名未进行严格过滤等,例如对文件后缀设置的过滤规则不完善。攻击者可能利用这些规则缺陷,绕过原有的文件类型或大小检查,上传恶意文件。
  • 权限认证缺失导致的漏洞

上传页面或接口没有进行有效的权限认证,匿名用户即可访问。攻击者能直接访问上传接口,将恶意文件上传到服务器。

  • 利用中间件或系统特性的文件上传漏洞。中间件/系统误配置: 利用服务器或中间件默认配置中的漏洞,上传文件后被错误解析为脚本文件。 例如,某些环境下上传的文件虽然经过初步过滤,但服务器配置允许对某些扩展名(如 .php、.asp)的文件直接执行,导致远程代码执行。

常见脚本文件的后缀名

  1. 常见的可执行脚本文件后缀名:

这些后缀名对应的文件可以在网站目录中被解析和执行

ASP 系列: asp、asa

PHP 系列: php、php3、php.a、phtml

ASPX 系列: aspx、ashx

JSP 系列: jsp

其他类型: cdx、cer、shtml

  1. 绕过过滤的变种方式:

有些网站会对常见的危险后缀名(如 asp 或 php)进行过滤,可能将这些后缀转为空或直接拒绝上传。为了绕过这种过滤,攻击者可能会对文件后缀进行变形,例如:

重复字母变形: 如 aspasp、asaspp、phpphp

这种方法试图利用简单的字符串匹配漏洞,使得过滤机制无法识别实际的危险后缀,进而上传可执行脚本。

攻击方法

  1. 识别和定位上传接口

寻找网站中提供上传功能的模块,如头像上传、文件编辑器中的文件上传、图片/媒体上传等。检查上传模块是否有权限认证,是否只对认证用户开放。分析上传请求的结构、参数和返回信息,初步判断是否存在安全漏洞。

  1. 抓包与测试

利用 Burp Suite、Fiddler 或其他抓包工具捕获上传请求,了解 HTTP 请求的细节。

分析请求头、请求体以及服务器响应信息。

基础测试:直接上传常见动态脚本文件(如 asp、php、aspx、jsp 等),观察服务器是否拒绝或返回错误信息。通过返回状态和提示信息,判断服务器的文件类型检测是否有效。

  1. 绕过文件类型和内容限制

利用双扩展名或伪装:如果上传接口只允许图片格式,可尝试上传“shell.php.jpg”或“shell.jpg”文件。部分系统可能仅检查后缀名或 MIME 类型,攻击者可以在文件中嵌入恶意代码,同时利用后续接口(如文件修改接口)更改文件后缀。

前端/服务端验证绕过:如果前端有严格的验证,使用抓包工具直接构造请求绕过客户端检查。服务端验证不严时,可利用逻辑漏洞(如上传时限制图片格式,但后续修改接口未做限制)来达到上传恶意文件的目的。

高级绕过技巧:利用零字节注入(Null Byte Injection)或特殊编码手法,试图绕过服务器端对文件后缀或内容的检测。利用文件内容混淆,让文件在保持图片扩展名的同时,其内容中包含有效的脚本代码(配合服务器配置失误可能被解析执行)。

  1. 后续利用和进一步渗透

上传成功后,直接通过访问文件的 URL 查看是否能够执行文件中的代码。检查上传目录是否对外公开、是否具备执行权限,这往往是进一步 getshell 的关键。

利用中间件或逻辑缺陷:通过分析服务器端配置(如目录执行权限、文件重命名逻辑),判断是否能利用上传后的文件获得更高权限。对部分存在逻辑漏洞的上传模块,测试是否能通过修改文件属性或调用其他接口实现更深层次的攻击。

  1. 综合补充与注意事项

上传接口的多重验证漏洞:攻击者可能发现部分模块仅依赖前端验证或简单的文件头检测,而这些检测机制很容易被绕过。需要同时关注文件名、扩展名、MIME 类型、文件内容以及服务器返回的信息等多个维度。

利用配置缺陷:如果服务器配置错误(例如上传目录允许脚本执行),即使部分验证存在,也可能被绕过。攻击者常会针对上传目录的执行权限进行测试,尝试上传后门脚本来获取进一步控制。

多接口联动:部分系统不仅有上传接口,还有修改接口或管理接口。如果上传接口限制严格,但修改接口没有对文件后缀进行验证,攻击者可以上传图片后再利用修改接口将扩展名改为动态脚本格式,实现 getshell。

Upload-labs通关记录

文章 - Upload-labs通关手册 - 先知社区

Pass-00任意文件上传

服务器直接将接收的文件放到hackable/uploads 目录下

上传一个简单的webshell

上传一句话木马
木马上传后用中国蚁剑连接webshell

连接成功后就能查看修改网站内容

Pass-1 绕过前端js检测

直接上传php文件会弹窗阻止上传,而且并没有发出网络请求,因此大致可以判断文件检测可能在设置在前端

查看前端代码会发现,文件上传时会触发一个js函数

这个函数用于检查文件类型是否为指定类型

绕过方法一:删除用于文件检测的前端代码,使其在文件上传时不进行检测

绕过方法二:将要上传的webshell的文件后缀先修改成符合上传的文件类型,表单提交后(此时已经通过了前端检测)再抓包将文件后缀修改回来。

上传修改后缀的webshell

恢复原来的后缀

Pass-2绕过contnet-type 检测

查看源码可以看到服务器端对$_FILES['upload_file']['type']字段的内容进行检查。而在 PHP 中,$_FILES['upload_file']['type'] 获取的是 客户端提供的 MIME 类型,它来自 HTTP 请求中的 Content-Type 头,但这个信息并不可靠,因为它是由客户端(如浏览器或上传工具)提供的,我们可以进行被伪造。

原本的Content-Type: application/octet-stream

修改为Content-Type: image/jpeg,然后重新发送

测试是否上传成功

Pass-3黑名单绕过上传

下面这段代码设置了一些禁止上传文件的后缀黑名单,上传文件的后缀将与黑名单进行对比,如果在黑名单中,则禁止上传。

代码解释

  • 从$_FILES超全局数组中获取上传文件的原始名称,并使用trim()函数去除文件两端名的空格。
  • 调用自定义函数deldot()去除文件名末尾的点,防止用户通过在文件名末尾添加点来绕过扩展名检查。
  • 使用strrchr()函数从文件名中获取从最后一个.开始的扩展名部分。
  • 将扩展名转换为小写,以便后续的比较操作不区分大小写。
  • 使用str_ireplace()函数去除扩展名中可能包含的::$DATA字符串,这是NTFS文件系统中的一种特殊数据流标记,防止利用此特性进行攻击。
  • 再次使用trim()函数去除扩展名两端的空格。
  • 最后,上传的文件会再次随机命名。

绕过方法:上传目标中间件可支持的其它后缀的脚本,如Apache可能将phtml、php3、php5也解析成php文件。

条件:找到apache2.conf或者httpd.conf这个文件,添加application/x-httpd-php配置选项,有的 apache 版本默认就会开启。

将该项配置为:AddType application/x-httpd-php .php .phtml .php3 .php5

这样后缀名为 phtml 、php3、php5的文件就都会被解析成 php文件。

上传.phtml文件,有个问题是上传后的文件被重命名了,上传后不能被直接访问到。但是,文件上传后会重新展示在上传页面,因此我们可以右键点击展示的文件,访问其url便能够得知修改后的文件名:

显示所在文件夹及文件名

访问文件并输入“指令”:

Pass-4重写htaccess 的上传

服务器端的黑名单几乎覆盖了所有的可执行脚本,也就是说所有的可执行文件都没法直接上传。如果能将黑名单之外的文件后缀也解析成php文件就好了,然而.htaccess文件能够做到恰好能够做到这一点。

.htaccess 文件是 Apache 服务器的一种目录级配置文件,用于控制特定目录及其子目录的服务器行为。通过在网站目录中放置 .htaccess 文件,网站管理员可以无需修改全局配置文件(如 httpd.conf),便可实现以下功能:

身份验证与访问控制:限制对特定目录的访问,设置密码保护等。

URL 重写与重定向:实现友好的 URL 结构,或将旧链接重定向到新地址。

自定义错误页面:为 404 等错误状态码设置自定义响应页面。

MIME 类型设置:指定特定文件扩展名的 MIME 类型,控制浏览器对文件的处理方式。

需要注意的是,.htaccess 文件的存在会在每次请求时被服务器读取,可能对性能产生影响。

在存在文件上传漏洞的情况下,攻击者可能利用 .htaccess 文件来控制服务器对特定文件的处理方式,从而执行恶意代码。常见的攻击方式包括:

1、更改文件解析方式:通过上传包含以下内容的 .htaccess 文件,攻击者可以让服务器将特定扩展名的文件作为 PHP 脚本解析:

AddType application/x-httpd-php .jpg

这意味着,服务器会将 .jpg 文件当作 PHP 代码执行。如果攻击者随后上传一个包含恶意 PHP 代码的 .jpg 文件,该代码将被服务器执行。

2、设置目录索引:通过上传 .htaccess 文件,攻击者可以修改目录的默认索引文件,或者启用目录列表功能,暴露敏感文件。

要做到更改文件解析方式,我们需要重写.htaccess 文件,而重写.htaccess 文件则需要在 apache 开启 rewrite 重写模块,因为 apache是多数都开启这个模块,所以规则一般都生效。

构建一个.htaccess文件,文件内容为:
<FilesMatch "jpg">

SetHandler application/x-httpd-php

</FilesMatch>

  • <FilesMatch "jpg"> ... </FilesMatch>
  • FilesMatch 指令用于匹配文件名,这里的 "jpg" 只包含 jpg,它实际上会匹配任何文件名中包含 "jpg" 的文件,比如:

image.jpg

shell.jpg

hackjpg.php(⚠️ 注意,这可能会带来额外风险)

  • SetHandler application/x-httpd-php
  • 这个指令告诉 Apache 服务器:对匹配的文件使用 PHP 解析器执行,而不是按普通图片处理。结果是,即使文件的扩展名是 .jpg,服务器仍会把它当作 PHP 代码运行。

或者将文件内容设为:
AddType application/x-httpd-php .jpg

服务器会将 .jpg 文件当作 PHP 代码执行。

上传.htaccess文件

再将一个webshell的后缀改为jpg并上传,

此时.htaccess文件和webshell01.jpg文件在同一个目录中,访问webshell01.jpg文件时.htaccess文件会将其解析为php文件

Pass-5大小写绕过

服务器将所有可执行脚本以及.htaccess文件都加入黑名单

查看源码可以发现,将文件后缀与黑名单进行匹配前并没有将其统一转化为小写,也就是说当我们输入大写或大小写混合的后缀时可以绕过检查

上传.PHP文件

Pass-6空格绕过

观察源码发现,在服务器端在提取文件后缀时(提取的后缀是字符串表示)没有去除后缀左右两边多余的空格,如果在上传时抓包并在文件后缀加上空格就能够绕过黑名单的检测。(提取到的后缀名是有空格的字符串,而黑名单中的后缀都没有空格这个字符,所以会匹配不上)

抓包修改文件名为:“webshell01.php ”,这样提取到的后缀名为“.php ”

Ps:将“webshell01.php ”作为一个文件名时,后面的空格是被忽略不及的

Pass-7 Windows系统特征绕过

正常的后缀提取:先去掉文件名末尾(可能是人为恶意添加)的“.”,然后再截取最后一个“.”以及其后面的字符

如果没有先检测并去掉文件名末尾的“.”,而是直接截取最后一个“.”以及其后面的字符可能会导致截取不到真正的后缀名。

比如上传文件名为“webshell01.php.”,则截取的后缀名为“.”,这样便绕过了黑名单检测

系统特征:

在 Windows 中,如果你尝试创建名为 webshell.php. 的文件,文件系统可能会自动去掉文件名末尾的点,文件将被重命名为 webshell.php

Linux 文件系统(如 ext4、Btrfs 等)允许文件名以点结尾,这意味着文件名 webshell.php. 将被接受,并且会保持文件名的原样。在 Linux 中,文件的扩展名(如 .php)仅作为文件的一部分,并不会影响文件的实际类型或可执行性。系统和应用程序(如 Web 服务器)会按照文件的内容来判断文件类型,而不是仅依赖于扩展名。因此,如果文件内容是 PHP 代码,webshell.php. 文件将会被执行。

macOS(基于 HFS+ 或 APFS 文件系统)与 Linux 类似,也允许文件名以点结尾。因此,webshell.php. 文件可以被创建,并且文件名中的点不会被自动去掉。但与 Linux 类似,macOS 会检查文件内容而不是仅仅依赖扩展名。因此,如果文件的内容包含 PHP 代码,webshell.php. 文件可能会被当作 PHP 脚本来执行。

Web 服务器(如 Apache 或 Nginx):如果你尝试上传一个名为 webshell.php. 的文件到 Web 服务器上,且服务器配置允许上传 PHP 文件,文件的扩展名仍然会被视为 .php(通常是 Web 服务器通过 MIME 类型或文件扩展名来判断文件是否需要执行 PHP 脚本)。

因此即使上传的文件名为“webshell.php.”,访问该文件时仍能够被视为php文件进行解析

Pass-8 NTFS 交换数据流::$DATA 绕过上传

NTFS(新技术文件系统)中的交换数据流(Alternate Data Streams,简称ADS)是一种允许单个文件关联多个数据流的功能。这些数据流的表示方式为“文件名:流名”,例如“text.txt:extrastream”。

zh.wikipedia.org

ADS最初在Windows NT 3.1中引入,旨在支持Macintosh的资源分叉功能。如今,虽然Windows服务器不再包含此功能,但某些第三方Apple归档服务产品仍在使用ADS。此外,Internet Explorer等浏览器会在从网络下载的文件中添加一个小型ADS,用于标记其来源于外部网站,以提示用户可能存在的安全风险。

上传文件:webshell01.php::$DATA

在windows系统中文件命名不能包含“:”符号

因此需要上传时抓包修改请求体中的文件名

访问上传的文件

Pass-9 利用 windows 环境的叠加特征绕过上传

去除左右空格

先删除文件末尾的点

读取文件名最右边的点及后面的内容

转小写

去除::$DATA

再去除左右空格

(Line15)最后保存的文件名是处理过的(去了空格和末尾的点)

方法一:多重后缀名

代码中只去除了一次文件末尾的点,如果添加多个后缀就能够绕过

上传webshell.php. ph.

Apache自右向左解析后缀:

或者设置文件名为:webshell01.php. .

Windows的特性会去掉空格和点,访问webshell.php

方法二:

NTFS 交换数据流(Alternate Data Streams)与文件上传漏洞

在 Windows 的 NTFS 文件系统中,除了我们通常看到的主数据流之外,每个文件还可以包含一个或多个附加数据流。默认数据流标记为 “::$DATA”。这种特性最初是为了兼容 Mac OS X 的资源叉(Resource Fork)而设计的,但后来也被恶意利用。

例如,上传一个文件名为 "moonsec.php:.jpg" 的文件时,系统会将文件名中的“:.jpg”解释为一个附加数据流标记。结果:

主数据流 的文件名为 "moonsec.php"(文件主体实际上为空或被单独处理),

“:.jpg”部分被当做附加数据流,不显示在常规文件列表中。

在这种情况下,虽然上传的文件名看似后缀为 .jpg,但实际存储的主文件是 moonsec.php,这样就绕过了上传限制(例如过滤 .php 后缀)而使得 PHP 代码得以执行。

正则匹配中的字符“等价”问题

在某些文件上传过滤逻辑中,会对文件扩展名进行正则匹配。Windows 环境下,由于历史遗留或兼容性考虑,有些特殊符号在比较时被视为等价,例如:

双引号 (") 与 点号 (.)

大于符号 (>) 与 问号 (?)

小于符号 (<) 与 星号 (*)

这意味着,在正则匹配或字符串比较时,如果检测程序将这些字符看作相同,就可能出现漏洞。例如:

上传文件名为 文件名.< 或 文件名.<<< 或 文件名.>>> 或 文件名.>>< 时,由于比较时这些符号与其他字符(如点)被等价处理,可能会导致过滤程序判断文件扩展名为空,从而绕过了黑名单检查。

结合第1部分,攻击者可以利用这些特性构造上传文件名,使得:

上传时表面上文件扩展名看似不属于被禁用的后缀;

实际上,经过 Windows 的处理后,真正保存的主文件名是带有 .php 后缀(例如 "moonsec.php"),从而使得恶意代码得以执行。

上传webshell.php:.jpg

此时上传的文件内容是空的:

上传webshell.>>>,该文件名会匹配到webshell.php,并把内容写进去

写进内容

访问文件

Pass-10双写后缀名绕过上传

str_ireplace() 函数用于在字符串中替换某些字符,与 str_replace() 类似,但它执行的是不区分大小写的替换操作。这意味着在替换过程中,函数会忽略字母的大小写差异。

只是将黑名单中的后缀替换成空字符

双写后缀:webshelll.pphphp,替换后:webshell.php

Pass-11白名单 目录可控%00 截断绕过上传

过滤的规则采用白名单

strrpos() 函数用于查找字符串在另一个字符串中最后一次出现的位置。与 strpos() 不同,strrpos() 查找的是字符串最后一次出现的位置,而不是第一次。

$img_path这个变量用于指定文件保存的路径,而文件目录是通过get方法获取的,我们可以借此改写文件保存路径

将.php后缀的一句话木马后缀改为.jpg,上传webshell.jpg(用于绕过白名单),然后抓包修改文件保存目录。将文件目录改为:/upload/webshell.php%00,前面的部分/upload/webshell.php是一个完整的文件路径,即把文件内容存放在upload目录下的webshell.php文件中(完成了对webshell.jpg的重命名),%00用于截断系统的文件命名。

访问webshell.php

Pass-12目录可控 POST 绕过上传

和上面一样,我们也可以控制文件保存目录,但是此处的save_path是在post请求体中获取的。

%00字符在请求体中不会自动解码,因此需要输入解码后的%00字符,即空字符(null)

空字符(Null Character)的 URL 编码:

ASCII 编码值:空字符的 ASCII 编码值是 0(十进制)。

URL 编码形式:在 URL 编码中,空字符会被编码为 %00。

为什么是 %00?

URL 编码是一种将特殊字符或不可打印字符转换为可打印形式的编码方式。它通过将字符的字节值转换为十六进制形式,并在前面加上 % 符号来表示。

空字符的 ASCII 编码值是 0,其十六进制表示为 00。

因此,在 URL 编码中,空字符表示为 %00。

访问上传的文件

Pass-13文件头检测绕过上传

读取一个文件的前两个字节,并尝试解析这两个字节的内容,将其转换为一个整数值。这种操作通常用于检测文件的类型或格式,因为许多文件格式在文件头的前几个字节中存储了特定的标识符(称为“文件签名”或“Magic Number”)

图片文件的开头两个字节(通常称为文件签名或魔数,Magic Number)具有特定的特征,用于标识文件的格式。这些字节是文件格式的“指纹”,可以帮助程序快速判断文件类型,而无需依赖文件扩展名。以下是一些常见图片格式的开头两个字节特征:

文件类型

文件签名(十六进制)

说明

JPEG(.jpg)

FF D8 FF

JPEG 图像文件的开头字节序列。

PNG(.png)

89 50 4E 47 0D 0A 1A 0A

对应 ASCII 字符串 ‰PNG,标识 PNG 图像文件。

GIF(.gif)

47 49 46 38 37 61 或 47 49 46 38 39 61

对应 ASCII 字符串 GIF87a 或 GIF89a,分别表示不同版本的 GIF 文件。

制作图片马:copy pic.jpg /b + webshell01.php /a webshell02.jpg

一句话木马被添加到图片数据的末尾

图片马上传后还需要用到文件包含漏洞

利用文件包含漏洞使服务器读取并解析图片中的一句话木马

或者直接上传webshell,然后在请求体中添加字符串:GIF89a

Websehll的后缀会被修改为.jpg 没关系,还能通过文件包含漏洞解析php代码

pass-14图片检测函数(getimagesize())绕过上传

使用 getimagesize() 函数获取文件的图像信息。这个函数返回一个数组,其中包含图像的宽度、高度、类型等信息。如果文件不是图像,getimagesize() 会返回 false。 image_type_to_extension() 函数将图像类型转换为文件扩展名。$info[2] 是 getimagesize() 返回的数组中的第三个元素,表示图像的类型。

继续上传图片马,然后用文件包含漏洞读取并解析图片中的php代码

Pass-15图片检测函数(exif_imagetype())绕过上传

使用 exif_imagetype() 函数获取文件的图像类型。这个函数需要 PHP 的 EXIF 模块开启。它返回一个常量,表示图像的类型(如 IMAGETYPE_GIF、IMAGETYPE_JPEG、IMAGETYPE_PNG 等)。

继续上传图片马来绕过

Pass-16绕过图片二次渲染上传

服务器端首先获取上传文件的基本信息:

设置目标路径

获取文件扩展名

判断文件后缀与类型(分别判断jpg,png,gif)

移动上传文件到目标路径

使用上传的图片生成新的图片(JPEG):$im = imagecreatefromjpeg($target_path);

检查图像创建是否成功

生成新图片名称

保存新图片

删除临时文件(原文件)

标记上传成功

总的来说,服务器会先对上传的图片后缀和文件类型进行判断,然后将图片二次渲染后保存生成的图片删除原来的图片。这样的话会可能会把图片中的php代码打乱,使其无法被解析。但是在渲染后图片有些地方的数据可能是不会被改变的,因此如果在数据不被改变的地方插入php代码,则可以绕过渲染进行文件上传。gif图片在二次渲染后,与原图片差别不会太大,所以二次渲染攻击最好用git图片马。

先用HxD Hex Editor打开原图和被渲染后的图片进行对比,查看哪块数据没被改变:

在数据未被修改的地方插入木马

上传后利用文件包含漏洞解析图片中的木马

Pass-17文件上传条件竞争漏洞绕过

服务器先将上传的文件移动到目标目录中,然后再判断文件是否符合过滤规则。这就导致上传的木马有一定的存活期。虽然存活期很短,但是如果我们构造大量的请求包一直上传,会使得这个木马文件在上传期间有很多时刻是存活的。

构造请求包

在burpsuit持续地上传期间访问webshell

访问时,webshell可能被删除了

多尝试几次,如果在webshell存活期访问便能顺利解析执行

Pass-18 Apache解析漏洞+条件竞争

上传流程 (upload() 方法)

按顺序执行以下检查,任意一步失败则终止上传:

验证是否为合法上传文件

isUploadedFile() 检查文件是否通过 HTTP POST 上传,防止伪造临时文件路径。

设置上传目录

setDir() 确保目录存在且可写。

检查文件扩展名

checkExtension() 验证文件扩展名是否在白名单中。

检查文件大小

checkSize() 可能限制文件最大尺寸。

检查文件是否已存在

如果 $cls_file_exists == 1,则 checkFileExists() 防止覆盖。

移动文件到目标目录

move() 从临时路径移动到 UPLOAD_PATH。

重命名文件

如果 $cls_rename_file == 1,调用 renameFile()(例如使用时间戳命名)。

使用burpsuite持续上传文件,我们可以在文件在移动到目标目录之后、重命名之前访问文件。

构造一个木马:<?php fputs(fopen('shell2.php','w'),'<?php @eval($_POST["x"])?>');?>

用于生成一句话木马

然后其改名为webshell03.php.7 利用的是多重扩展名解析漏洞

漏洞原理:文件名解析逻辑:Apache 的 mod_mime 模块默认会从右向左解析文件扩展名,直到找到一个已知的 MIME 类型。例如:文件名为 test.php.abc 时,Apache 会先检查 .abc(若未定义 MIME 类型),继续向左检查 .php,最终将文件识别为 PHP 脚本。

持续上传文件时,多次尝试访问这个文件,使PHP代码被解析执行(生成webshell)

访问失败

访问成功

然后访问生成的webshell

Pass-19文件名可控绕过上传

pathinfo() 是 PHP 中的一个内置函数,用于获取文件路径的相关信息。它可以从一个完整的文件路径中提取文件名、目录路径、扩展名等部分。PATHINFO_EXTENSION:返回路径的文件扩展名部分。

文件名可以自定义,尝试用%00截断,设置文件名为webshell.php%00.jpg,文件名阶段后为webshell.php

由于save_name是在post请求体中,因此需要解码将%00解码

访问webshell.php(注意不是webshell.php.jpg)

方法二:save_name多重文件名

Pass-20数组绕过上传

同样可以自定义save_name,不过save_name可以是数组(不是数组也会被分成数组),然后最终的文件名被设置为索引为0的值,后缀则设置为将该数组中元素数量作为索引的元素的值。

在 PHP 中,数组的索引可以是不连续的。count() 函数返回数组中元素的总数,而不是数组的最大索引值。从直觉上认为$file[count($file)-1]的值是数组中索引,但 count() 函数只统计元素数量,所以 $file[count($file)-1] 实际上访问不一定是数组中索引最大的值。

设置save_name[0]=webshell.php/

save_name[2]=jpg

此时save_name[1]=null,那么服务器中$file[count($file)-1]的值也是null

拼接好的$file_name就会变成:webshell.php/.

php在调用函数保存文件时会自动去掉/.

设置save_name[0]=webshell.php

save_name[2]=jpg

此时save_name[1]=null,那么服务器中$file[count($file)-1]的值也是null

拼接好的$file_name就会变成:webshell.php.

在linux中允许存在.php. Apache自右向左解析后缀

在windows中保存文件会去掉末尾的.

在php中,有一个数组,$file[0]为“smi1e.php”,然后再令$file[2]为“jpg”,那么$file[count($file) - 1]的值是什么,请具体解释

在 PHP 中,数组的索引不一定连续,count() 返回的是数组中元素的总数,而不是最大索引值。

举例说明:

$file[0] = "smi1e.php"; // 数组中设置了键 0 的元素

$file[2] = "jpg"; // 数组中设置了键 2 的元素

此时,数组中实际上有两个元素,键分别为 0 和 2。
使用 count($file) 得到的结果为 2(即数组中有 2 个元素)。

$file[count($file) - 1]

这里 count($file) 为 2,所以 count($file) - 1 为 1,即代码等同于 $file[1]。

由于数组中并未设置键 1 的值,因此 $file[1] 是未定义的(在严格模式下可能会报 Notice)。

总结:
即使从直觉上认为$file[count($file)-1]的值是数组中最后一个设置的索引为 2(值为 "jpg"),但 count() 函数只统计元素数量,结果为 2,所以 $file[count($file)-1] 实际上访问的是 $file[1],而这个键未被设置,其值为 未定义NULL

在 PHP 中,数组的索引可以是不连续的。count() 函数返回数组中元素的总数,而不是数组的最大索引值。在处理可能存在非连续索引的数组时,直接使用 count($array) - 1 来获取最后一个元素可能并不可靠。更安全的方式是使用 end() 函数获取数组的最后一个元素值:

文件上传其他漏洞

nginx0.83/1.jpg%00php

apahce1x或者2x

当apache遇见不认识的后缀名,会从后向前解析例如1.php.rar不认识rar就向

前解析,直到知道它认识的后缀名。

phpcgi漏洞(nginxiis7或者以上)上传图片后1.jpg。访问1.jpg/1.php也会解析成

php。

ApacheHTTPD换行解析漏洞(CVE-2017-15715)

apache通过mod_php来运行脚本,其2.4.0-2.4.29中存在apache换行解析漏洞,

在解析php时xxx.php\x0A将被按照PHP后缀进行解析,导致绕过一些服务器的

安全策略。

文件上传漏洞通用检测方法

判断是否为黑白名单,如果是白名单寻找可控参数。如果是黑名单禁止上传,

可以用有危害的后缀名批量提交测试,寻找遗留的执行脚本。

.php

.php5

.php4

.php3

.php2

.html

.htm

.phtml

.pht

.pHp

.phP

.pHp5

.pHp4

.pHp3

.pHp2

.Html

.Htm

.pHtml

.jsp

.jspa

.jspx

.jsw

.jsv

.jspf

.jtml

.jSp

.jSpx

.jSpa

.jSw

.jSv

.jSpf

.jHtml

.asp

.aspx

.asa

.asax

.ascx

.ashx

.asmx

.cer

.aSp

.aSpx

.aSa

.aSax

.aScx

.aShx

.aSmx

.cEr

.sWf

.swf

.htaccess

使用burpsuite抓包上传将后缀名设置成变量,把这些文件设置成一个字典批量

提交,查看数据包大小查看确定时候可上传即可。

文件上传的攻击方法

一文详述文件上传漏洞插图

修复建议

  1. 权限管理与认证

严格访问控制:确保上传模块仅对经过身份认证和授权的用户开放,避免匿名用户直接访问上传接口。对上传页面进行权限校验,并记录上传用户的身份信息,便于事后追溯。

最小权限原则:

  1. 上传目录配置

禁止执行权限:将文件上传目录配置为禁止执行脚本文件。

在 Apache 中,可通过 .htaccess 禁用 PHP、CGI 等脚本执行;在 Nginx 中,则通过配置文件设置相应目录的执行权限。这种措施确保即使上传了恶意代码,也不会被服务器直接解析执行。

隔离存储:尽可能将上传文件存储在与应用逻辑隔离的目录中,降低文件与应用服务器核心业务间的耦合风险。

  1. 文件类型与内容检测

白名单机制:严格设置允许上传的文件类型,推荐只允许上传图片格式(如 jpg、png、gif)等。使用服务器端的 MIME 类型检测,不仅依赖文件后缀,还要验证文件的实际内容(如读取文件的 Magic Number)。

内容安全检测:对上传文件进行进一步扫描,例如使用防病毒软件检测文件是否包含恶意代码。对图片等允许的格式,也需防范隐藏数据或脚本植入的情况。

文件大小限制:设置合理的文件大小上限,防止超大文件上传导致资源耗尽或拒绝服务攻击。

  1. 文件名与后缀处理

强制重命名:上传文件应自动生成随机且唯一的文件名,避免使用原始文件名,从而防止恶意文件通过特殊文件名进行攻击。重命名后应统一采用安全的文件后缀(如 .jpg、.png、.gif),即使文件内容发生变化,后缀也固定。

后缀验证:上传后应对文件后缀进行校验和转换,确保与预期文件类型一致。

同时记录原始文件信息,便于后续管理和审计。

  1. 其他防护措施

输入验证与过滤:对上传的所有参数进行严格的输入验证,防止路径遍历等攻击。使用白名单策略对允许上传的 MIME 类型、扩展名等进行过滤。

日志记录与监控:对所有上传操作进行详细日志记录,包括上传用户、文件名、时间和上传结果。配置实时监控和报警系统,及时发现异常上传行为。

分片上传与临时存储:对大文件采用分片上传,上传过程中在服务器端先存储到临时目录,待所有分片上传完成后再进行安全检查和最终保存。

定期审查与更新:定期对文件上传模块进行安全审查,及时更新白名单和安全策略。

引入第三方安全测试,模拟上传攻击场景,确保防护措施有效。


4A评测 - 免责申明

本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。

不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。

本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。

如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!

程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。

侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)

相关文章

不是哥们,北大被”RCE”了?
WAF开发之防护HTTP洪水攻击
打靶日记——prime1
Fenjing 作者的 Jinja SSTI 完全进阶教程
“剪贴板劫持”攻击:黑客利用虚假验证码通过入侵网站窃取数据
护网还没开始,电脑先中毒了,那就实战

发布评论