从PNG tEXt到存储型XSS
字数 1200 2025-08-18 11:37:15
PNG tEXt 块到存储型XSS漏洞利用技术详解
漏洞背景
本教学文档详细分析了一种通过PNG图像文件的tEXt块实现存储型XSS攻击的技术。这种攻击方式特别适用于那些严格限制上传文件类型(仅允许PNG)但又能通过特定方式解析上传文件的网站系统。
漏洞发现过程
初始测试环境
- 目标站点有严格的文件上传过滤机制,只接受
.PNG扩展名 - 意外发现一个上传点允许上传带有
.html扩展名的文件
初步尝试
- 尝试直接上传包含HTML内容的伪PNG文件:
{ "Name": "image.png.html", "Data": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" }- 这是一个简单的1像素红点PNG图像
- 尝试修改数据类型为
data:html或url等,但验证失败 - 直接修改PNG内容为非合法PNG也会导致验证失败
技术难点
- 系统会解码Base64并执行内容
- 尝试在Base64末尾添加
"/><script>alert("xss");</script>,但JS未执行 - 系统可能检查PNG的魔术字节头(前8个字节应为
0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A)
绕过尝试
-
构造包含魔术字节的"假"PNG,并附加XSS代码:
- 验证仍然失败
- 推测系统使用.NET的
Image.FromStream方法验证图像有效性
-
尝试在合法PNG的不同位置插入XSS代码字节数组:
- 通过迭代方式在位置1、位置2...插入或追加
- 所有尝试均未成功
成功利用技术
PNG tEXt块特性
- PNG规范允许通过tEXt块添加文本元数据(如版权、标题等)
- 这是PNG文件的合法组成部分,不会影响图像有效性
利用工具
使用ImageMagick工具注入恶意tEXt块:
convert Head_red.png \
-set 'Copyright' '/><script>alert("1");</script>' \
-set 'Title' '/><script>alert("2");</script>' \
-set comment '/><script>alert("3");</script>' \
OUT.png
攻击步骤
- 创建包含恶意tEXt块的PNG文件
- 通过允许上传.html文件的上传点提交文件:
{ "Name": "image.png.html", "Data": "data:image/png;base64,<恶意PNG的Base64编码>" } - 系统解码Base64并生成HTML页面
- 当用户访问该HTML页面时,嵌入在tEXt块中的XSS代码被执行
防御建议
-
输入验证:
- 严格验证上传文件的真实类型(检查魔术字节)
- 不仅验证文件扩展名,还要验证实际内容
-
内容过滤:
- 对PNG等图像文件中的元数据进行检查和过滤
- 移除或转义可能危险的tEXt块内容
-
输出编码:
- 在显示用户上传内容时进行适当的HTML编码
-
文件处理:
- 在处理上传文件时,使用安全的API和方法
- 考虑重新编码或清理上传的图像文件
-
扩展检查:
- 不要仅依赖文件扩展名判断文件类型
- 实现多层次的验证机制
扩展风险
- 类似漏洞不仅存在于PNG文件,JPEG、GIF等图像格式也支持元数据块
- 许多非图像文件类型也可能包含可执行内容
- 开发人员应全面考虑各种文件类型的潜在风险
总结
本技术展示了如何利用PNG规范中的合法特性(tEXt块)绕过严格的文件上传限制,实现存储型XSS攻击。这种攻击方式特别隐蔽,因为它使用的是完全符合规范的PNG文件。防御此类攻击需要多层次的验证和过滤机制,而不仅仅是简单的文件扩展名检查。