# Apache 2.4.71 修補 HTTP/2 RCE（CVE-2026-119618）：你的服務要查哪幾段

> Apache 2.4.55 到 2.4.70 用 Protocols 開了 h2 或 h2c 就在 CVE-2026-119618 範圍內。先逐段確認實際協定與源站能否直連，再決定更新或暫時關掉 HTTP/2。

原文：https://sheng.page/posts/apache-http2-cve-2026-119618-what-to-check/ · 發布：2026-11-12 · 作者：Sheng

Apache HTTP Server 在 2026 年 11 月 11 日發布 2.4.71，修補 mod_http2 一個評為 critical 的遠端程式碼執行漏洞 CVE-2026-119618。版本落在 2.4.55 到 2.4.70，載入了 mod_http2，而且用 `Protocols` 開了 h2 或 h2c，就在範圍內，只跑 HTTP/1.1 的伺服器不受影響。

先做的事是逐台確認 `Protocols` 設定，再用連線測試配合源站的 access log，確認每一段實際用的協定，有開又等不到修補套件，就先把 HTTP/2 關掉。資料查核到 2026-11-12 17:00（台北時間），沒有找到權威來源證實在野利用，CISA KEV 最新一版也沒有列入，不過 Red Hat 提到公開研究已經示範過可靠利用，確認受影響的服務現在就該排修補，不必等在野攻擊被證實。

## 受影響的條件

上游公告的影響範圍是 2.4.55 到 2.4.70，GitHub 上獨立發行的 mod_h2 則是 2.0.8 到 2.0.42。Red Hat 的分析補上現場要看的條件：用 `Protocols` 指令開了 HTTP/2 的伺服器才受影響，h2 與 h2c 都算在內。根因是 worker 執行緒用共用且沒上鎖的 allocator，寫入 connection 執行緒持有的記憶體，CVSS 3.1 評 9.8，攻擊者不需身分驗證就能從遠端利用。

所以版本字串、模組有沒有載入、`Protocols` 怎麼設、發行版有沒有回補，這四件事要分開確認。只看 `httpd -v` 判斷不了：號碼在範圍內，模組沒載入或 `Protocols` 沒開 h2、h2c，其實碰不到這個漏洞；發行版套件的版本字串常停在舊號碼，修補卻早已回補進去。官方 Docker image 是前一種的例子，實測 httpd:2.4.70 與 2.4.71 預設的 MPM 都是 mpm_event，http2_module 那行 LoadModule 是註解掉的，也沒有 `Protocols` 指令，2.4.70 在影響範圍內，預設卻沒開 HTTP/2。自己改過設定或用了別人包好的 image，就得回頭確認。

同一版另外修了 mod_md 的 NULL pointer dereference（CVE-2026-106023，important，影響 2.4.30 到 2.4.70）與 mod_vhost_alias 的 1 byte stack buffer overwrite（CVE-2026-109163，low，影響 2.4.69 與 2.4.70），關掉 HTTP/2 只能處理 mod_http2 這一個，更新還是要排進來。

## CDN 後面的那一段

很多人第一個反應是前面有 CDN 或反向代理擋著。前面那層跟源站之間用什麼協定，以及繞過這層能不能直接連到源站，都要驗。client 跟最外層講 HTTP/2，推不出源站自己有沒有開，要一段一段看。

下面是在 OrbStack 上用官方 image 做的檢查，只看每一段協商到什麼，沒有送任何攻擊流量，也沒有重現漏洞。源站 2.4.70 開成 `Protocols h2c http/1.1`，前面放一台開了 `http2 on;` 的 nginx 做 `proxy_pass`。第一個 `sed` 載入模組，接著的 `printf` 是為了測試故意把 h2c 打開，止血是後段把 `Protocols` 改成 `http/1.1` 那一行，別貼錯方向：

```sh
# 只看每一段講什麼協定，不送任何攻擊流量
docker network create h2check
docker run --detach --name origin --network h2check httpd:2.4.70 sh -c '
  sed -i "s/^#LoadModule http2_module/LoadModule http2_module/" conf/httpd.conf
  printf "ServerName origin\nProtocols h2c http/1.1\nLogFormat \"%%h %%>s proto=%%H\" p\nCustomLog /proc/self/fd/1 p\n" >> conf/httpd.conf
  exec httpd-foreground'
# nginx.conf: events {} http { server { listen 80; http2 on; location / { proxy_pass http://origin:80; } } }
docker run --detach --name front --network h2check --volume "$PWD/nginx.conf:/etc/nginx/nginx.conf:ro" nginx:1.29
sleep 3

c() { docker run --rm --network h2check curlimages/curl:8.17.0 --silent --output /dev/null --write-out "$1 -> HTTP/%{http_version} %{http_code}\n" "${@:2}"; }
c "client->front" --http2-prior-knowledge http://front/
c "client->origin direct" --http2-prior-knowledge http://origin/
docker logs origin 2>&1 | grep proto=

# 止血：只留 HTTP/1.1，再確認
docker exec origin sh -c 'sed -i "s/^Protocols .*/Protocols http\/1.1/" conf/httpd.conf && httpd -t && httpd -k graceful'
sleep 2
c "client->origin direct (--http2)" --http2 http://origin/
```

實際輸出（省略開頭三行 network 與容器 ID）：

```text
client->front -> HTTP/2 200
client->origin direct -> HTTP/2 200
192.168.97.3 200 proto=HTTP/1.1
192.168.97.4 200 proto=HTTP/2.0
Syntax OK
client->origin direct (--http2) -> HTTP/1.1 200
```

client 對 nginx 講 HTTP/2，經 nginx 轉進源站那一筆記成 HTTP/1.1，這段沒有碰到 mod_http2；同一台源站一旦能直接連到，記到的就是 HTTP/2.0，要擔心的是這一段。把源站改成 `Protocols http/1.1` 並 graceful 重啟後，`curl --http2` 只拿到 HTTP/1.1，另外測的 `--http2-prior-knowledge` 直接失敗，curl exit code 16。這裡用 graceful 只是示範新連線會拿到什麼，舊程序仍會把手上的連線服務完，既有的 HTTP/2 連線還留在舊設定上，正式止血要完整停止再啟動。

實測用 h2c 是為了省掉憑證，正式環境多半是 TLS 上以 ALPN 協商的 h2，判斷方式相同。主流瀏覽器只支援走 TLS 的 HTTP/2，可是 curl 照樣能對 h2c 連線，別因為瀏覽器不用就略過沒加密的那個埠。「前面有 CDN 擋著」沒拿 log 或 curl 驗過，就還是一個假設。

## 發行版各自的狀態

| 對象 | 查核時狀態 |
| --- | --- |
| 上游 Apache HTTP Server | 2.4.71 已於 2026-11-11 發布，影響 2.4.55 到 2.4.70 |
| RHEL 8 與更早 | 不受影響，mod_http2 2.0.8 之前沒有這段程式碼 |
| RHEL 9、RHEL 10 | RHSA 已於 2026-11-11 發布，例如 RHSA-2026:98981（mod_http2-2.0.26-7.el9_9.1）、RHSA-2026:98978（mod_http2-2.0.29-5.el10_3.1） |
| Debian | bookworm、trixie、forky 為 open，sid 已是 2.4.71-1 |
| Ubuntu | archive 還看不到修補套件；jammy 是否受影響以 Ubuntu 公告為準（需驗證） |
| 獨立 mod_h2 | 影響 2.0.8 到 2.0.42，repo 已封存、停止維護，最新仍是 v2.0.42，沒有修補版 |

Red Hat 把 RHEL 9、10 評為 Important，理由是這兩版的 mod_http2 套件每個 stream 用獨立 allocator，利用難度大幅提高，EUS 等分支也在同一天出了 RHSA；JBoss Core Services 與 Hardened Images 標為 Affected，還沒列出修補。Debian 的 bookworm 是 2.4.68-1~deb12u1，trixie 是 2.4.68-1~deb13u1（trixie-security 是 2.4.69-1~deb13u1），都還在影響範圍內。Ubuntu 各版最新的 security 與 updates 發布在 11 月 9 日到 10 日，早於上游公告，noble 2.4.58-1ubuntu8.18、resolute 2.4.66-2ubuntu2.7、stonking 2.4.68-1ubuntu6.1 的 changelog 都沒有這個 CVE；jammy 是 2.4.52 系列，上游版本號在範圍之前，有沒有回補到相關程式碼要看 Ubuntu 自己的判定，查核時 Ubuntu CVE 頁讀取失敗。GitHub 上獨立發行的 mod_h2，README 寫明 repo 已封存、不再維護，模組改由 Apache httpd 專案維護，自己編這個版本載入的人等不到新版，要改用上游或發行版修補過的模組。

## 公開研究、在野攻擊與 KEV 是三件事

10 月 26 日與 11 月 3 日，Anthropic 的 OSS Scanner（ANT-2026-MAPKT6MZ），以及 Google Cloud Vulnerability Research 的 Anthony Weems 與 Simon Scannell，回報了這個漏洞。Red Hat 寫到公開研究已示範對預設設定且啟用 mod_http2 的伺服器做出可靠利用，這只說明技術上做得到，沒有找到權威來源證實已有在野攻擊。漏洞彙整站上已有標示為 PoC 的 repo，真偽未驗證，本文不連結。

CISA KEV 最新一版是 2026-11-10 發布的 2026.11.10，共 1,779 筆，沒有 CVE-2026-119618，但這一版比 Apache 公告早一天，能說的只有它沒列入。KEV 沒收、在野沒證據，只代表還不知道，拿來當晚點處理的理由並不划算。

## 清點與更新步驟

1. 列出所有跑 Apache 的主機與容器，CDN 後面的源站、內部服務、別人包好的 image 都算進去。
2. 逐台確認版本與載入的模組，再檢查全域及各 virtual host 的 `Protocols`，個別站台可能覆寫全域設定。發行版套件另外對照廠商公告看有沒有回補。
3. curl 只看得到它自己連的那一段。用它查對外入口，以及繞過 CDN 直接連源站的結果（帶正式的主機名稱），port 80 的 h2c 和只有內網到得了的 listener 也各打一次；CDN 到源站講什麼，要看 CDN 的設定和源站的 access log。
4. 有修補套件就更新，接著完整重啟。`httpd -v` 讀的是磁碟上的新檔，證明不了正在聽 port 的程序已經換掉，要看程序的啟動時間晚於套件更新。
5. 用的發行版分支還沒有修補套件，就先把全域和各 virtual host 的 `Protocols` 改成 `http/1.1`，`httpd -t` 通過後完整停止再啟動，確認舊程序都退出。以實際載入的設定為準，確認沒有 listener 還開著 HTTP/2，curl 只當輔助。
6. 套件確認修補完成，才把 `Protocols` 改回來。

下面這段是唯讀檢查，指令名稱依發行版而異，未逐一實測。`curl --http2` 談不成會自己退回 HTTP/1.1，印出 `2` 才代表這一段有 HTTP/2，印出 `1.1` 只代表這次沒談成，先用 `curl -V` 確認手上的 curl 有編 HTTP2：

```sh
# 版本、模組、設定，三件事分開看
httpd -v || apache2 -v
httpd -M 2>/dev/null | grep -E 'http2|mpm_' || apache2ctl -M 2>/dev/null | grep -E 'http2|mpm_'
grep -R -n -E '^\s*Protocols' /etc/httpd /etc/apache2 2>/dev/null
# 從外面看某一段實際協商到什麼
curl --silent --output /dev/null --write-out '%{http_version}\n' --http2 https://your-origin.example/
```

停用 HTTP/2 後，瀏覽器會自己退回 HTTP/1.1，代價是沒有多工、連線數變多，資源多的頁面可能慢一點。上游若固定用 HTTP/2 連這台，就不會退回，例如前面的代理用 mod_proxy_http2 接它、gRPC，或寫死 h2c prior knowledge 的 client，這些會直接失敗，停用前先確認有沒有這種流量。前面有 CDN、而且 CDN 對源站本來就走 HTTP/1.1 的話，在源站關掉 HTTP/2 使用者幾乎無感。收尾一樣要小心，重啟後跑的還是舊程序，或套件還沒修好就把 `Protocols` 改回去，前面等於白做。

## 補充筆記

- 受影響條件是 2.4.55 到 2.4.70、載入 mod_http2、`Protocols` 開了 h2 或 h2c，只跑 HTTP/1.1 不受影響。
- 版本字串、模組、`Protocols`、發行版回補要分開確認，官方 httpd image 預設沒開 HTTP/2。
- 前面有 CDN 不代表源站安全，源站能直接連到時，要看的是源站自己開了什麼。
- RHEL 9、10 已有 RHSA，Debian 穩定版與 Ubuntu 查核時還沒有修補，獨立 mod_h2 已停止維護。
- 止血時全域與各 virtual host 的 `Protocols` 都要改，改完完整重啟，graceful 不會切掉既有連線。
- 查核時未找到權威來源證實在野利用，KEV 最新一版也未收錄，但公開研究已示範可靠利用。

## 延伸閱讀

- [Apache HTTP Server 2.4 安全公告](https://httpd.apache.org/security/vulnerabilities_24.html)：Apache 官方公告，一手來源，影響範圍與嚴重度以此為準。
- [CHANGES_2.4.71](https://downloads.apache.org/httpd/CHANGES_2.4.71)：Apache 官方變更紀錄，一手來源，列出 2.4.71 修了什麼。
- [Red Hat CVE-2026-119618](https://access.redhat.com/security/cve/cve-2026-119618)：Red Hat 的廠商一手分析，含 CVSS、各產品狀態與 RHSA。
- [Debian security tracker CVE-2026-119618](https://security-tracker.debian.org/tracker/CVE-2026-119618)：Debian 官方追蹤頁，一手來源，看各版本修補狀態。
- [Launchpad apache2](https://launchpad.net/ubuntu/+source/apache2)：Ubuntu 套件發布紀錄，一手來源，可查各版 changelog。
- [CISA Known Exploited Vulnerabilities Catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog)：CISA 官方清單，一手來源，收錄已證實遭利用的漏洞。
- [mod_h2 releases](https://github.com/icing/mod_h2/releases)：獨立 mod_h2 的發行頁，一手來源，repo 已封存，最新停在 v2.0.42。
- [Apache HTTP/2 guide](https://httpd.apache.org/docs/2.4/howto/http2.html)：Apache 官方 HTTP/2 設定文件，一手來源，說明 `Protocols` 用法。
- [HTTP/2（Wikipedia）](https://en.wikipedia.org/wiki/HTTP/2)：百科條目，只當 h2 與 h2c 的背景知識。

> 想法與技術判斷出自 Sheng，和 Claude 一起起草 · Codex 與 Grok 二審；協定檢查在 OrbStack 以 httpd:2.4.70、nginx:1.29 實測，未重現漏洞；資料查核至 2026-11-12 17:00（台北時間）