我的 Apache 是 2.4.46,使用 Openssl 版本 1.1.1f
我已经设置了指令SSLCompression Off
。即使我启用它,它也会说不支持 SSL 压缩,我想这很好。
但是,当我使用 Firefox 查看网页的 HTTP 标头时,我看到了这些响应标头:
HTTP/2 200 OK
date: Fri, 25 Dec 2020 12:13:58 GMT
server: Apache
expires: -1
cache-control: no-store, no-cache, must-revalidate, max-age=0
pragma: no-cache
content-security-policy: default-src https: 'unsafe-inline' 'unsafe-hashes' 'self'; img-src data: https: 'self'
x-frame-options: DENY
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
strict-transport-security: max-age=63072000; includeSubDomains; preload
referrer-policy: no-referrer
permissions-policy: geolocation=();midi=();notifications=();push=();sync-xhr=(self);microphone=();camera=();magnetometer=();gyroscope=();speaker=(self);vibrate=();fullscreen=(self);payment=();
vary: Accept-Encoding
content-encoding: gzip
content-length: 3299
content-type: text/html; charset=UTF-8
X-Firefox-Spdy: h2
这句话的意思就是:content-encoding: gzip
让我担心。
但是,即使我使用 cURL 来获取使用 PHP 中的以下脚本的页面:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//enable headers
curl_setopt($ch, CURLOPT_HEADER, 1);
//get only headers
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 5000);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0");
curl_setopt($ch, CURLOPT_ENCODING, "gzip");
它返回以下 HTTP 标头:
HTTP/2 200
date: Fri, 25 Dec 2020 12:16:45 GMT
server: Apache
set-cookie: __Secure-CCJRLSESSID=g7m99kljvea2g5uk58f5lfskr1; path=/; secure; HttpOnly; SameSite=Lax
expires: -1
cache-control: no-store, no-cache, must-revalidate, max-age=0
pragma: no-cache
content-security-policy: default-src https: 'unsafe-inline' 'unsafe-hashes' 'self'; img-src data: https: 'self'
x-frame-options: DENY
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
strict-transport-security: max-age=63072000; includeSubDomains; preload
referrer-policy: no-referrer
permissions-policy: geolocation=();midi=();notifications=();push=();sync-xhr=(self);microphone=();camera=();magnetometer=();gyroscope=();speaker=(self);vibrate=();fullscreen=(self);payment=();
content-type: text/html; charset=UTF-8
这让我很困惑。我甚至清除了 Firefox 中的缓存,但还是没用。我不想受到 CRIME 攻击。反过来,我可以完全禁用 gzip。但在那之前,我想知道为什么会发生这种情况。也许是 Firefox 的一个错误??
更新:
在 chrome 中也会发生这种情况。
mod_deflate 配置:
SSLCompression Off
<IfModule deflate_module>
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE application/x-font
AddOutputFilterByType DEFLATE application/x-font-opentype
AddOutputFilterByType DEFLATE application/x-font-otf
AddOutputFilterByType DEFLATE application/x-font-truetype
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE font/opentype
AddOutputFilterByType DEFLATE font/otf
AddOutputFilterByType DEFLATE font/ttf
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
</IfModule>
答案1
为了回答你的问题,了解一些背景知识会有所帮助:
背景——为什么使用压缩可能存在安全风险?
有一些所谓的“压缩侧信道攻击”基本上是使用压缩结果来猜测原始文本。每种攻击的工作原理基本上都是将输入添加到压缩中,然后观察输出。这是因为许多压缩算法的工作原理是识别重复的文本并用引用替换它们,而不是多次重复完整的文本。这会导致消息变小,但确实为攻击提供了机会。
这些攻击是如何进行的?
基本上,如果您猜测出部分或全部秘密部分,将其与未知的秘密部分一起添加到消息中,然后观察加密结果的大小,如果它随着某些猜测而变小,那么您一定是重复了部分消息,因此受益于更高的压缩。
通过一些猜测,就可以找出秘密部分。 做到这一点取决于能否添加到消息中,但有多种方法可以做到这一点。 例如,如果您想知道token
example.com 的 cookie 设置,则发送一条消息(可能是当人们访问与您完全不相关的网站时发生的隐藏的 XHR 消息?)到example.com?token=1
并测量生成的消息大小(因为浏览器也会自动将 cookie 添加到消息中)。 然后尝试example.com?token=2
看看它是更大、更小还是相同。 对所有可能的值重复此操作,直到找到 cookie 的第一个字符,其中消息会更小。 假设在这个例子中它是token=5
。 然后尝试第二个字符(例如example.com?token=51
,example.com?token=52
...等)。 重复,直到您获得完整的 cookie。
您可以直接测量消息的长度(例如,通过观察加密消息,如果可以的话)中间人我们可以通过分析网络(或者计算发送消息所需的时间)来准确猜测消息的长度。
HTTP 消息可以通过多种方式压缩
压缩可以在 HTTP 消息的不同级别发生:1) 在 SSL/TLS 级别,2) 在 HTTP 正文级别和 3) 在 HTTP 标头级别。
SSL 压缩
基本上,无论底层是否是 HTTP 消息,都会进行 SSL/TLS 压缩 - 它是在 SSL/TLS 级别完成的。以下攻击犯罪基本上阻止了我们使用 SSL/TLS 压缩,因为它引入了太多猜测消息隐藏部分的方法,基本上使用上述算法。老实说,SSL/TLS 压缩的好处并不是那么好,特别是如果我们已经使用 gzip 或类似方法在底层 HTTP 级别压缩了主体响应,因此在加密后再次压缩它并没有真正节省那么多数据。所以没有真正的理由使用它,这给出了一个真正的理由不是使用它。SSL/TLS 压缩应该始终关闭,并使用类似SSL实验室确认这一点。大多数服务器默认关闭此功能,而且关闭已有一段时间,所以如果现在打开了,我会感到非常惊讶。
HTTP 主体压缩
HTTP Body 级别的压缩更有趣。这通常使用 gzip 或较新的 Brotli 算法,并且是在大多数情况下建议启用,因为 Web 性能的提升非常显著。这是因为 HTTP 主体通常很大(特别是响应主体),而网络通常相对较慢 — 因此通过网络发送较小尺寸的主体确实有好处。现在,理论上,这很容易受到类似的攻击(所谓的BREACH 攻击还有时间变体)——但前提是秘密数据再次出现在正文中(因此任何相同的猜测在压缩后都会变得更小)。因此风险要小得多,因为大多数响应不包含秘密数据(例如,您上次看到您的 cookie 打印到页面上的屏幕是什么时候?),而标题中的 cookie 通常总是包含在消息中,并且占消息的很大一部分。
当然,如果你有一些打印在屏幕上的秘密信息(你的名字,社会保险号,出生日期,银行详细信息...等),那么它可能会很脆弱,也许应该考虑不对这些响应进行 HTTP 压缩,但这些是非常不典型的,所以禁用 HTTP 压缩每一个响应很少是正确的答案。即使您在屏幕上显示秘密信息,也有更好的选择:例如,根本不在屏幕上显示该数据,或者至少完整显示(例如,用星号标记除最后 4 位数字之外的所有数字),不允许用户响应数据同时显示在屏幕上,用随机字符填充数据,或者添加速率限制通常是更好的选择。
回到你的问题
因此,回答你的问题,SSL 压缩和 HTTP 主体压缩是两个不同的东西,前者应该是离开后者在(除了真正安全的应用程序中,尽管有好处,但应用程序不想冒这个险 - 但即便如此,通常也有更好的方法来处理这个问题)。
最后,关于 HTTP 标头压缩的一些额外信息
最后,让我们来谈谈 HTTP 标头压缩,因为如上所述,它们通常包含攻击者认为有价值的 cookie 秘密。
HTTP/1.1 直到最近还是主流版本,但它不允许这样做,所以这里没什么好说的。这些是以完全未压缩的形式发送的(虽然如果使用 HTTPS 则使用 SSL/TLS 加密),因此不易受到侧信道压缩风险的影响(假设未使用 SSL 压缩)。
与 HTTP 主体相比,这些主体通常也非常小,因此没有人真正担心压缩它们太多。然而,随着构成网页所用资源数量的增加(如今超过 100 个并不罕见),一直来回发送几乎相同的 HTTP 标头会产生大量冗余(例如,您是否看到过用户代理标头的大小,它随每个单个请求一起发送,但对于所有这些请求都不会改变?)。
因此,较新的 HTTP/2 和即将发布的 HTTP/3 协议确实允许 HTTP 标头压缩,但它们专门选择了一种不易受到这些攻击的压缩算法(HTTP/2 的 HPACK 和 HTTP/3 的类似 QPACK)。顺便说一句,这是一个明确的选择,因为 HTTP/2 所基于的早期 SPDY 协议确实使用了 gzip,因此容易受到攻击。因此,当它被标记时,它必须作为将其标准化为 HTTP/2 的一部分进行更改。
为什么不一直使用“安全压缩”?
那么为什么我们不能对 HTTP 响应主体使用安全的压缩技术(如 HPACK 或 QPACK)并避免这种情况呢?因为它们是非常具体的压缩技术,使用字典或已知和重复的值。这对于 HTTP 标头非常有效,因为 HTTP 标头的值很少,而且重复很多,但对于更通用的 HTTP 主体响应来说,这实际上不是一个选择,因为每个响应可能完全不同。
希望这可以解释一些事情并回答您的问题。
答案2
针对 CRIME 的攻击CVE-2012-4929是关于加密压缩头而不适当混淆未加密数据的长度,这使得可以揭示纯文本头(通过猜测)。
在您的例子中,内容被压缩,压缩数据的大小(长度)作为另一个标头添加,然后所有这些都被加密。这不易受到 CRIME 攻击,因为未加密数据的长度永远不会被泄露。