Ssl

無法在 Apache 中關閉 SSLCompression?

  • January 2, 2021

我的 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>

要回答您的問題,了解一些背景知識會有所幫助:

背景 - 為什麼使用壓縮可能會帶來安全風險?

有一些所謂的“壓縮側通道攻擊”基本上是使用壓縮結果來嘗試猜測原始文本。每個基本上都是通過將輸入添加到壓縮然後觀察輸出來工作的。這是因為許多壓縮算法通過辨識重複的文本並用引用替換它們來工作,而不是多次完整地重複文本。這會導致較小的消息,但確實打開了攻擊機會。

這些攻擊如何運作?

基本上,如果您猜測部分或全部秘密部分,將其與未知秘密部分一起添加到消息中,然後觀察加密結果的大小,如果通過某些猜測它變得更小,那麼您必須重複部分消息因此受益於更高的壓縮率。

通過一些猜測,有可能找出秘密部分。這樣做取決於能夠添加到消息中,但有多種方法可以做到這一點。例如,如果您想知道tokenexample.com 的 cookie 集,然後發送一條消息(可能是當人們訪問您完全不相關的站點時發生的隱藏 XHR 消息?)example.com?token=1並測量生成的消息大小(因為瀏覽器會自動添加消息的 cookie 也是如此)。然後嘗試example.com?token=2看看它是否更大,更小或相同。對所有可能的值重複此操作,直到找到 cookie 的第一個字元,其中消息會更小。假設在這個例子中它是token=5. 然後嘗試第二個字元(例如example.com?token=51example.com?token=52…等)。重複直到你有完整的cookie。

您可以直接測量消息的長度(例如,如果您可以在網路中間人,則通過觀察加密的消息)或發送消息所需的時間,以便很好地猜測長度。

HTTP 消息可以通過多種方式進行壓縮

壓縮可以在 HTTP 消息中發生不同級別:1)在 SSL/TLS 級別,2)在 HTTP 正文級別和 3)在 HTTP 標頭級別。

SSL 壓縮

進行 SSL/TLS 壓縮基本上不管它是下面的 HTTP 消息這一事實 - 它是在 SSL/TLS 級別完成的。像CRIME這樣的攻擊基本上阻止了我們使用 SSL/TLS 壓縮,因為它引入了太多猜測消息隱藏部分的方法,基本上是使用上述算法。老實說,SSL/TLS 壓縮的收益並沒有那麼大,特別是如果我們已經使用 gzip 或類似方法在底層 HTTP 級別壓縮了正文響應,因此在加密後再次壓縮它並沒有真正節省那麼多更多數據。所以沒有真正的理由使用它,這給了一個真正的理由使用它。SSL/TLS 壓縮應始終關閉並使用SSLLabs 之類的工具確認這一點。在大多數伺服器中預設情況下它是關閉的,並且已經有一段時間了,所以打開它會非常驚訝。

HTTP 正文壓縮

HTTP Body 級別的壓縮更有趣。這通常使用 gzip 或較新的 Brotli 算法,並且建議在大多數情況下啟用,因為 Web 性能的提升非常顯著。這是因為 HTTP 主體通常很大(特別是響應主體)並且網路通常相對較慢——因此通過網路發送較小的主體會帶來真正的收益。現在是的,理論上這很容易受到類似的攻擊(所謂的BREACH 攻擊TIME變體)——但前提是秘密數據再次出現在正文中(因此任何相同的猜測在壓縮後都可以看出更小)。因此風險要小得多,因為大多數響應不包含秘密數據(例如,您最後一次看到您的 cookie 列印到頁面上的螢幕是什麼時候?),而標題中的 cookie 通常總是包含在內,並且在消息中佔較大比例.

當然,如果您有一些列印到螢幕上的秘密資訊(您的姓名、社會保險號、DoB、銀行詳細資訊等),那麼它可能很容易受到攻擊,也許應該考慮不使用 HTTP 壓縮這些響應,但這些響應是非典型的因此,為每個響應禁用 HTTP 壓縮很少是正確的答案。即使您在螢幕上顯示秘密資訊,也有更好的選擇:例如,根本不在螢幕上顯示該數據,或者至少不完整顯示(例如,除了最後 4 位之外的所有數字),不允許顯示使用者響應數據例如,同時在螢幕上顯示,用隨機字元填充數據或添加速率限制通常是更好的選擇。

回到你的問題

因此,要回答您的問題,SSL 壓縮和 HTTP 正文壓縮是兩件不同的事情,前者應該關閉,後者應該打開(除了在真正安全的應用程序中,儘管有收益但不想冒這個風險 - 但即便如此,通常有更好的方法來處理這個)。

最後,一些關於 HTTP Header 壓縮的額外資訊

為了結束這個故事,讓我們談談 HTTP 標頭壓縮,因為如上所述,它們通常包含攻擊者會發現有價值的 cookie 機密。

HTTP/1.1 直到最近還是使用的主要版本,它不允許這樣做,所以這裡沒有太多可談的。這些以完全未壓縮的形式發送(儘管如果使用 HTTPS 則使用 SSL/TLS 加密),因此不易受到側通道壓縮風險的影響(假設未使用 SSL 壓縮)。

與 HTTP 主體相比,它們通常也非常小,因此沒有人真正擔心壓縮它們太多。然而,隨著用於構成網頁的資源數量的增加(現在超過 100 個並不罕見),在一直來回發送幾乎相同的 HTTP 標頭時會出現很多冗餘(您看到大小了嗎?例如,使用者代理標頭的名稱隨每個請求一起發送,但對於所有這些請求從不更改?)。

因此,較新的 HTTP/2 和即將發布的 HTTP/3 協議確實允許 HTTP Header 壓縮,但它們特別選擇了一種不易受到這些攻擊的壓縮算法(HTTP/2 的 HPACK 和 HTTP/3 的類似 QPACK)。順便說一句,這是一個明確的選擇,因為 HTTP/2 所基於的早期 SPDY 協議確實使用了 gzip,因此很容易受到攻擊。因此,當它被標記時,它必須作為將其標準化為 HTTP/2 的一部分進行更改。

為什麼不總是使用“安全壓縮”?

那麼為什麼我們不能對 HTTP 響應體也使用安全壓縮技術(如 HPACK 或 QPACK)並避免這種情況呢?嗯,它們是非常具體的壓縮技術,它使用字典或已知和重複的值。這適用於值很少且大量重複的 HTTP 標頭,但對於更通用的 HTTP 主體響應來說,這並不是一個真正的選擇,因為每個響應可能完全不同。

希望這能解釋一些事情,從而回答你的問題。

引用自:https://serverfault.com/questions/1047579