CTF实战:手把手教你用Hex Fiend绕过PNG上传限制,拿下BUUCTF [HarekazeCTF2019] Avatar Uploader 1的Flag
CTF实战Hex Fiend破解PNG检测机制的艺术当你面对一个看似简单的PNG上传界面时背后可能隐藏着精妙的安全检测机制。这次我们要挑战的是BUUCTF平台上的[HarekazeCTF2019] Avatar Uploader 1题目——一个需要同时绕过finfo_file()和getimagesize()双重检测的文件上传关卡。1. 理解题目防御机制在开始操作前我们需要先拆解题目中的两个关键检测函数1.1 finfo_file()的工作原理这个PHP函数通过读取文件的魔术数字(Magic Number)来识别文件类型。对于PNG文件它会检查文件开头是否包含以下十六进制签名89 50 4E 47 0D 0A 1A 0A这个签名对应ASCII字符是.PNG....是PNG文件的唯一标识符。有趣的是finfo_file()只验证文件头不会深入检查文件实际内容是否完整。1.2 getimagesize()的检测逻辑相比前者这个函数会进行更深入的图像解析$size getimagesize($_FILES[file][tmp_name]); if ($size[2] ! IMAGETYPE_PNG) { // 触发Flag的条件 error(What happened...? OK, the flag for part 1 is: . getenv(FLAG1)); }关键点在于$size[2]这个返回值它表示图像的实际类型代码。我们需要构造一个文件让getimagesize()认为这不是有效的PNG文件返回非3的值但同时保留PNG文件头让finfo_file()识别通过。2. 准备攻击环境2.1 工具选择与安装我们将使用Hex Fiend这款十六进制编辑器Mac平台首选Windows用户可用HxD替代# Mac用户通过Homebrew安装 brew install --cask hex-fiend # Windows替代方案 # 下载HxDhttps://mh-nexus.de/en/hxd/2.2 创建测试PNG文件准备一个合规的PNG图片256x256像素以内可以使用以下命令快速生成convert -size 200x200 xc:white test.png3. 十六进制手术实战3.1 初始文件分析用Hex Fiend打开正常PNG文件你会看到类似这样的结构偏移量数据ASCII表示000089 50 4E 47 0D 0A 1A 0A.PNG....000800 00 00 0D 49 48 44 52....IHDR001000 00 00 C8 00 00 00 C8.................关键区块说明文件头签名前8字节固定不变IHDR块包含图像宽度(00 00 00 C8200)、高度(00 00 00 C8200)等关键信息3.2 构造畸形文件我们的攻击策略是保留完整的PNG文件头签名前8字节破坏IHDR块的结构使其无法被正常解析具体操作步骤在Hex Fiend中删除从偏移量0x08开始的所有数据只保留前8字节的签名文件最终内容应仅为89 50 4E 47 0D 0A 1A 0A注意不要添加任何额外字节纯8字节文件是最理想的攻击载荷4. 上传与验证将修改后的文件上传观察服务器响应finfo_file()检测看到有效的PNG文件头 → 通过getimagesize()检测无法解析残缺的文件结构 →$size[2]返回非3的值 → 触发Flag条件预期你会看到类似这样的响应What happened...? OK, the flag for part 1 is: flag{your_flag_here}5. 防御机制深度解析为什么这种攻击会成功关键在于两个函数解析深度的差异检测函数解析深度验证内容绕过方法finfo_file()浅层文件头魔术数字保留有效文件头getimagesize()深层完整结构实际图像数据和结构破坏关键数据块这种差异正是安全防御中的常见盲点——当多个检测机制对同一属性的验证标准不一致时就可能出现绕过机会。6. 进阶思考与变种在实际CTF比赛中这类题目可能有多种变体双重文件头技巧在文件开头构造多个不同格式的文件头块结构混淆故意错位PNG的块结构如修改IHDR长度字段多阶段检测绕过配合文件扩展名白名单等其他检测机制一个有趣的实验是尝试构造一个既是PNG又是ZIP的文件# 创建混合文件 cat normal.png dual.puZ zip -A dual.puZ这种文件在不同检测上下文中会呈现不同属性但需要注意现代安全系统对这种手法的检测越来越严格。