PNG图片藏XSS脚本:一张32x32的图片如何骗过安全扫描器?IDAT攻击完整攻防指南 PNG图片藏XSS脚本一张32x32的图片如何骗过安全扫描器IDAT攻击完整攻防指南【免费下载链接】xss2pngPNG IDAT chunks XSS payload generator项目地址: https://gitcode.com/gh_mirrors/xs/xss2png深夜的告警声毫无预兆一台承载用户头像上传的服务被打出了 XSS。安全同事把攻击样本递到你面前——一张 32×32 的 PNG肉眼看起来平平无奇文件头规范、像素完整、渲染毫无破绽。可就是这样一张正常得不能再正常的图片让一段SCRIPT在受害者的浏览器里被静默执行了。制造它的正是名为xss2png的开源工具一个把 XSS 载荷写进 PNG 的 IDAT 数据块、伪装成合法图片的载荷生成器。这篇文章不打算给你讲又一个漏洞演示而是站在防守方视角把这张图从里到外拆给你看它凭什么能藏东西、为什么扫描器集体失明、你的系统在哪一环会踩雷以及最终该怎么把它挡在门外。第一步搞清敌人到底藏在哪里先放下攻击重新认识一下你每天都在处理的 PNG 格式。它远不是一张图片那么简单——更准确的说法是PNG 是一个由若干数据块拼接而成的容器。开头的 8 个字节是固定签名\x89PNG\r\n\x1a\n几乎所有文件类型检测都只认这一行。紧随其后是IHDR块记录宽、高、位深、颜色类型等元信息。中间一大段IDAT块才是真正的图像本体——它存放的是经过 zlib/deflate 压缩后的扫描线数据。结尾是IEND块一个纯粹的终止标记。注意IDAT的定义它存的是压缩流。压缩意味着这段字节在任何人眼里都应该是杂乱无章的二进制——这正是攻击者最爱的掩护。xss2png 的整个思路可以浓缩成一句反直觉的话让压缩流里直接躺着你要的明文。第二步一张普通的图凭什么能攻破防线打开xss2png.py你会发现这个工具的偷渡流程只有三步但每一步都踩在 PNG 规范的盲区上。第一站反向霍夫曼。deflate 压缩内部依赖霍夫曼编码——固定码表把 0~143 的字面量映射为 8 位码字。xss2png 把这个过程倒过来先拿到你想植入的 payload反算出什么样的输入字节经压缩后恰好输出这段明文。于是压缩后的IDAT字节流里赫然就是SCRIPT SRC.../SCRIPT的可读文本。README 里的hexdump输出就是铁证IDAT数据区中间直接出现了3C 53 43 52 49 50 54也就是 ASCII 的SCRIPT。第二站反向过滤器。PNG 解码时每行像素要经过 0~4 号过滤器还原。xss2png 对 1 号Sub和 3 号Average过滤器做了逆向运算保证解压后得到的仍是合法的图像扫描线——图片能正常渲染不会变成花屏视觉上毫无破绽。第三站像素伪装。处理好的字节被逐个塞进 32×32 图像的 RGB 像素通道再用 Pillow 重新编码保存。Pillow 会按自己的流程重新做 deflate但因为第一步已经预演过压缩结果最终产出的文件里明文依然稳稳地躺在IDAT中。一个小细节工具会把 payload 强制转为大写——这是原版实现的关键细节也意味着你在防御侧做特征匹配时大小写都必须覆盖。第三步为什么传统扫描器集体失明这是整件事最让人后背发凉的部分你的常规检测手段在这张图面前几乎全部失效。魔数校验通过。文件头 8 字节签名分毫不差。格式合法性通过。块结构、长度字段、CRC 校验全部符合规范。渲染测试通过。解压、滤波、取色每一步都产出正常像素。病毒特征库通过。这段恶意内容不违反任何 PNG 规范它是合法的。根子上的问题是传统检测只回答这是不是一张 PNG从不回答这张 PNG 里藏着什么。而 xss2png 恰恰利用了规范允许的一切手段把恶意代码伪装成了合法的图片数据。扫描器不是不努力是它的检测模型里压根没有IDAT 里的明文这个维度。第四步什么样的系统会踩雷图片本身只是弹药真正引爆它的是下游处理链路的疏忽。踩雷场景通常长这样场景一Content-Type 混乱。服务器把用户上传文件按text/html类型回显多见于文件包含、调试接口或错误配置的静态目录。浏览器拿到响应发现 MIME 是 HTML就开始按 HTML 解析——于是IDAT里的SCRIPT被当成真实标签执行。历史上某社交平台的中招事故正是这类图片 错误内容类型的组合。场景二文件包含漏洞。经典如 DVWA 的page参数直接把上传的 PNG 当作页面包含进来响应头变成text/html图片里的脚本随之苏醒。场景三MIME 嗅探。当响应缺少明确 Content-Type 时某些浏览器会自作主张地嗅探内容、按 HTML 处理给攻击补上了最后一块拼图。场景四后端误处理。把用户图片交给 PHP 等后端include、或让图片处理管线把文件字节当文本回显都会让载荷获得执行机会。一句话总结只要是图片字节被当成文本返回的链路都是这张 PNG 的击穿点。第五步防守方行动手册好消息是理解了藏匿原理防御就有章可循。以下按优先级排列5.1 服务端重编码最有效的一招把上传的图片解码后再重新编码一次。像素被重排、压缩流被重建IDAT里的明文必然被打散。这是性价比最高的防御动作因为它直接摧毁了载荷的藏身形态。5.2 严格的内容类型纪律上传文件一律以image/png返回配合Content-Disposition: attachment阻止内联解析响应头必须显式给出X-Content-Type-Options: nosniff掐掉浏览器的 MIME 嗅探。代码层面可以这样做import struct, zlib, re PNG_SIGNATURE b\x89PNG\r\n\x1a\n def walk_idat_chunks(data: bytes): 遍历 PNG 数据块逐个产出 IDAT 块体 pos 8 while pos 8 len(data): length struct.unpack(I, data[pos:pos4])[0] ctype data[pos4:pos8] body data[pos8:pos8length] if ctype bIDAT: yield body pos 12 length def suspicious_png(data: bytes) - bool: # 第一道魔数校验只证明它自称是 PNG if data[:8] ! PNG_SIGNATURE: return False # 第二道直接扫 IDAT 原始字节xss2png 的明文就躺在压缩流里 raw b.join(walk_idat_chunks(data)) if re.search(rbscript|SCRIPT|javascript:|onerror, raw): return True # 第三道解压后再扫一遍防住只藏在解压结果里的变体 try: plain zlib.decompress(raw) return re.search(rbscript|SCRIPT|javascript:|onerror, plain) is not None except zlib.error: return False5.3 CSP 兜底即使脚本被浏览器解析script-src self且不开启unsafe-inline的 CSP 也能让内联脚本无法执行。CSP 不是用来替代前两层的而是最后的保险丝。5.4 隔离与最小暴露上传文件单独放 cookie-free 的独立域名后端永远不要include用户可控的图片图片处理库保持更新及时跟进解压与解码层面的安全补丁。各层防线的定位差异一张表说清防线防住什么局限魔数/格式校验伪装成图片的非图片文件对合法 PNG 里的载荷无效服务端重编码IDAT 明文载荷不防解压后才出现的变体Content-Type nosniff浏览器按 HTML 解析图片防不住后端主动回显文本CSP内联脚本执行需全站统一配置防不住外链绕过隔离域名会话 Cookie 被窃取不消除 XSS 本身第六步亲手复现一次然后自查纸上谈兵没意思按下面步骤跑一遍你会对这张图有更直观的体感git clone https://gitcode.com/gh_mirrors/xs/xss2png cd xss2png pip install -r requirements.txt python xss2png.py -p SCRIPT SRC//XSS.EXAMPLE.CZ/SCRIPT -o test.png生成后用hexdump -C test.png观察IDAT段你会亲眼看到明文SCRIPT就嵌在压缩流中间——这就是攻击的全部秘密。接着用上面 5.2 的suspicious_png()跑一遍同一文件验证防御代码能否命中。最后给你的业务做一次系统性自查所有用户上传文件返回时的 Content-Type 是否被强制锁定响应头是否带了X-Content-Type-Options: nosniff图片上传后是否经过解码→重编码的清洗流程是否存在把用户文件当文本回显或include的接口全站 CSP 是否已生效且未开放unsafe-inline安全测试是否覆盖了上传 → 回显 → 浏览器解析的完整链路写在最后别只盯着 PNGxss2png 只是一个缩影。它提醒我们一个朴素但常被遗忘的事实文件格式的合法与内容的恶意是两回事。今天的攻击者是借 PNG 的 IDAT 藏脚本明天就可能借 AI 生成图片、WebAssembly 字节码或云存储的多租户环境玩出新的花样。安全没有一劳永逸的银弹只有把输入校验、输出控制、执行隔离、兜底策略每一层都压实才能在被这类隐蔽载荷盯上时从容地回一句此路不通。【免费下载链接】xss2pngPNG IDAT chunks XSS payload generator项目地址: https://gitcode.com/gh_mirrors/xs/xss2png创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

最新新闻

drawio-desktop 新手入门:3 步装好免费跨平台画图工具,打开 VSDX 不再求人

drawio-desktop 新手入门:3 步装好免费跨平台画图工具,打开 VSDX 不再求人

drawio-desktop 新手入门:3 步装好免费跨平台画图工具,打开 VSDX 不再求人 【免费下载链接】drawio-desktop Official electron build of draw.io 项目地址: https://gitcode.com/GitHub_Trending/dr/drawio-desktop 同事发来一个 .vsdx 文件&…

2026/8/20 17:06:39
Keras-FCN 源码精读:全连接层如何转换为卷积层实现像素级分类

Keras-FCN 源码精读:全连接层如何转换为卷积层实现像素级分类

Keras-FCN 源码精读:全连接层如何转换为卷积层实现像素级分类 【免费下载链接】Keras-FCN Keras-tensorflow implementation of Fully Convolutional Networks for Semantic Segmentation(Unfinished) 项目地址: https://gitcode.com/gh_mi…

2026/8/20 17:06:39
Sketchfab下载器完整上手指南:一条Firefox用户脚本,把3D模型下载时间从半小时压到90秒

Sketchfab下载器完整上手指南:一条Firefox用户脚本,把3D模型下载时间从半小时压到90秒

Sketchfab下载器完整上手指南:一条Firefox用户脚本,把3D模型下载时间从半小时压到90秒 【免费下载链接】sketchfab sketchfab download userscipt for Tampermonkey by firefox only 项目地址: https://gitcode.com/gh_mirrors/sk/sketchfab 深夜…

2026/8/20 17:06:39
Typeplate核心函数深度剖析:context-calc与measure-margin计算原理

Typeplate核心函数深度剖析:context-calc与measure-margin计算原理

Typeplate核心函数深度剖析:context-calc与measure-margin计算原理 【免费下载链接】starter-kit Typeplate is a “Typographic Starter Kit.” We don’t make aesthetic design choices, but define proper markup with extensible styling for common typograph…

2026/8/20 17:06:39
GetQzonehistory备份神器:几步把QQ空间历史说说完整搬回本地

GetQzonehistory备份神器:几步把QQ空间历史说说完整搬回本地

GetQzonehistory备份神器:几步把QQ空间历史说说完整搬回本地 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你的QQ空间里,是不是也躺着几十上百条舍不得删的说说…

2026/8/20 17:06:39
jellyfin-plugin-douban剧集攻略:电视剧、季与单集元数据刮削的完整指南

jellyfin-plugin-douban剧集攻略:电视剧、季与单集元数据刮削的完整指南

jellyfin-plugin-douban剧集攻略:电视剧、季与单集元数据刮削的完整指南 【免费下载链接】jellyfin-plugin-douban Douban metadata provider for Jellyfin 项目地址: https://gitcode.com/gh_mirrors/je/jellyfin-plugin-douban 如果你正在使用 Jellyfin 搭…

2026/8/20 17:01:38