【译】Fun with Gzip Bombs and Email Clients

原文:https://www.grepular.com/Fun_with_Gzip_Bombs_and_Email_Clients

gzip/zip炸弹已经存在几十年了。我们来创建一个10MB的gzip文件,解压后能达到10GB:

dd if=/dev/zero bs=1G count=10 | gzip > 10gb.gz

这就是所谓的“gzip炸弹”,因为解压后它的体积会急剧膨胀(大约是原来的1000倍)。把这个文件放到你的网站根目录,再配置Nginx将其当作图片来传输,并加上gzip的内容编码:

location /10gb.png {
    default_type image/png;
    add_header   Content-Encoding gzip;
    try_files    /10gb.gz =404;
}

当HTTP客户端获取这个文件时,看到内容编码设为gzip,通常会实时解压。这意味着你只通过网络发送了10MB的数据,而客户端却要处理10GB的解压后内容。

火狐浏览器似乎对此没什么问题。它能很快判断出这不是图片,而且似乎不会存储解压后的数据。

不过邮件客户端会怎样呢?一些邮件服务为了向发件人隐藏你的IP,开始使用代理,这些代理又会如何反应?发送一封包含以下内容的HTML邮件试试:

<img src="https://你的网站域名/10gb.png">

雷鸟邮件和Gmail的网页代理在获取图片时,会提前中断,不会下完这10MB的文件。不清楚这是因为它们识别出这不是图片,还是解压时触发了限制。不过不管怎样,效果还好。

Protonmail和iCloud网页版邮件的代理似乎会下载完整的10MB文件,然后直接丢弃。Protonmail会提示图片加载失败,并提供直接用浏览器加载的选项(不通过它们的代理)。如果选择加载,你的IP会泄露,但浏览器不会崩溃,这情况还算正常。

Fastmail网页版的代理会下载完整的10MB文件,还会继续传输385MB的数据后才停止。界面倒是一直保持响应,虽然它们早该中断,但总算没出大问题。我倒是好奇,它们的服务器上会不会留下一个10GB的文件。

iOS邮件会部分下载文件,然后直接崩溃。体验确实糟糕,但也不算无法挽回,重新进入后删除邮件就行。

Evolution邮件则毫无防备。它会下载完整的10MB文件,然后在缓存目录(cache/evolution/http/)里把文件完全解压。我给自发送了一封包含这些内容的邮件:

<img src="https://你的主机名/10gb.png">
<img src="https://你的主机名/10gb.png?x=1">
<img src="https://你的主机名/10gb.png?x=2">
<img src="https://你的主机名/10gb.png?x=3">
<img src="https://你的主机名/10gb.png?x=4">
<img src="https://你的主机名/10gb.png?x=5">
<img src="https://你的主机名/10gb.png?x=6">
<img src="https://你的主机名/10gb.png?x=7">
<img src="https://你的主机名/10gb.png?x=8">
<img src="https://你的主机名/10gb.png?x=9">

点击“加载远程内容”后不到一分钟,Evolution邮件就在我笔记本的磁盘里新增了100GB的数据。

从外部服务获取数据时,做好防御性编码总是没错的。毕竟得时刻想到,总会有自作聪明的人,让服务器给你发送远超合理范围的数据。

测试时我还发现Evolution邮件一个奇怪的地方:它会把下载的远程内容缓存到文件中,文件名是URL的MD5值。但如果URL的查询参数不符合它有限的几种格式,计算MD5时就会忽略查询参数。也就是说,在Evolution邮件的缓存机制里,这两个URL被视为相同,会缓存到同一个文件中:

所以,如果你收到一封包含<img src="https://www.example.com/foo?image1">的邮件,之后又收到一封包含<img src="https://www.example.com/foo?image2">的邮件,第二封邮件会显示第一封邮件缓存的图片。

posted @ 2025-07-23 16:23  talentzemin  阅读(23)  评论(0)    收藏  举报