Istio 近期披露了安全公告 ISTIO-SECURITY-2026-004,对应 CVE-2026-47774,CVSS 评分 7.5(High)。漏洞根因落在 Envoy 的 HTTP/2 头部处理逻辑上——HPACK 编码的压缩率让攻击者用极小的请求体撑爆 Sidecar 内存。任何对外暴露 HTTP/2 或 gRPC 的 Istio 集群都在攻击面内,无需认证即可触发。
漏洞机制:编码字节 ≠ 解码字节
HTTP/2 使用 HPACK 算法压缩头部。HPACK 维护一张动态表,重复出现的头部字段(如 cookie)只需引用表中的索引,编码体积可以非常小。
问题出在两处校验的脱节:
-
Cookie 头字节未纳入请求头大小校验——Envoy 在验证请求头总大小时,没有完整统计 cookie 头占用的字节数。Cookie 本身就是 HTTP 中最容易膨胀的字段(多值、长 token),绕过了这一关就已经放大了攻击空间。
-
HPACK 块限制只看编码字节,不看解码字节——Envoy 对 HPACK header block 设了上限,但这个上限作用于 编码后 的字节数。HPACK 的压缩特性意味着:一个索引引用可能只占 1–2 字节编码,解码后还原出几百甚至上千字节的原始头部。攻击者反复发送大量引用同一 cookie 的请求,编码侧始终"合规",解码侧内存持续膨胀。
最终结果:Envoy 进程内存耗尽,被 OOM Killer 终止,所在 Pod 重启——服务拒绝。
影响范围:比你想象的更广
受影响版本:
| Istio 版本 | 受影响范围 | 修复版本 |
|---|---|---|
| 1.30.x | 1.30.0 | ≥ 1.30.1 |
| 1.29.x | 1.29.0 – 1.29.3 | ≥ 1.29.4 |
| 1.28.x | 1.28.0 – 1.28.7 | ≥ 1.28.8 |
触发条件只有一个:接受下游 HTTP/2 流量。以下场景均命中:
- Gateway 暴露 HTTPS 端口(TLS 解密后内部走 HTTP/2)
- Sidecar 接收来自集群内 gRPC 客户端的请求
- 任何对不可信工作负载开放 HTTP/2 的 Service
注意:即便攻击者走 HTTPS 入站,TLS 终止后 Envoy 仍然以 HTTP/2 处理请求,漏洞照样触发。
紧急排查与升级
先确认集群 Istio 版本和流量暴露面,再执行升级。
1. 查当前 Istio 版本
# 查看控制面版本
istioctl version
# 或直接看 Pilot Pod 的镜像 tag
kubectl get deploy -n istio-system istiod -o jsonpath='{.spec.template.spec.containers[0].image}'
输出类似 gcr.io/istio-release/pilot:1.29.3——落在受影响区间就需要升级。
2. 查哪些 Gateway/Sidecar 接收 HTTP/2
# 查 Ingress Gateway 配置中 HTTP/2 相关端口
kubectl get svc -n istio-system istio-ingressgateway -o yaml | \
grep -A2 -E 'name:.*https|name:.*http2|name:.*grpc'
# 查集群内 gRPC 服务(Service name 含 grpc 或 port name 含 grpc)
kubectl get svc --all-namespaces -o json | \
jq -r '.items[] | select(.spec.ports[]?.name | test("grpc|h2")) | "\(.metadata.namespace)/\(.metadata.name)"'
任何匹配结果都意味着该路径可被利用。
3. 升级 Istio
以 1.29.3 升级到 1.29.4 为例:
# 下载目标版本 istioctl
curl -L https://istio.io/downloadIstio?ISTIO_VERSION=1.29.4 | sh -
cd istio-1.29.4
# 执行升级(先控制面,再数据面)
./bin/istioctl upgrade
# 等待 istiod 就绪后,滚动重启 Sidecar 注入的工作负载
kubectl rollout restart deployment --all-namespaces
# 确认新版本生效
istioctl version
升级前在非生产环境验证兼容性。Istio 小版本升级(1.29.3 → 1.29.4)通常只含 bugfix 和安全补丁,API 无变化,但仍建议走标准变更流程。
临时缓解:升级前的止损手段
如果无法立即升级,可以通过 EnvoyFilter 限制 HTTP/2 解码后的头部总大小,缩小攻击窗口:
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: h2-header-size-guard
namespace: istio-system
spec:
configPatches:
- applyTo: NETWORK_FILTER
match:
context: ANY
patch:
operation: MERGE
value:
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
max_request_headers_kb: 32
http2_protocol_options:
max_concurrent_streams: 100
initial_stream_window_size: 65536
关键参数说明:
max_request_headers_kb: 32——将请求头总大小上限压到 32 KB(默认 96 KB),限制单次请求的头部膨胀空间。initial_stream_window_size: 65536——缩小 HTTP/2 流级窗口,减缓大头部请求的传输速率。
这不能根治漏洞(编码侧校验仍然缺失),但能显著降低单次攻击的内存消耗量,争取升级时间。
修复后的验证清单
升级完成后,做以下确认:
| 检查项 | 命令/方法 |
|---|---|
| Istiod 版本 ≥ 修复版本 | istioctl version |
| Sidecar 镜像版本同步更新 | kubectl get po -n app -c istio-proxy -o jsonpath='{.spec.containers[0].image}' |
| EnvoyFilter 缓解规则可移除 | 确认升级后删除临时 EnvoyFilter,避免限流参数影响正常大头部业务 |
| Gateway 正常转发 HTTP/2 | 用 curl --http2 或 grpcurl 对外部服务发请求,确认无异常 |
| OOM 事件消失 | kubectl events --all-namespaces --field-selector reason=OOMKilling 近期无新记录 |
留一个意识:HPACK 是 HTTP/2 的通用风险
这次漏洞的本质是"压缩侧限流、解压侧不限流"——这类问题不只出现在 Envoy。任何实现 HTTP/2 HPACK 的代理(Nginx、HAProxy、Go net/http2)都可能存在类似设计盲区。排查时不妨一并检查集群中非 Istio 的 HTTP/2 代理配置,确认它们对 解码后 头部大小有独立上限。
升级是必须的,但理解机制才能在下一次同类漏洞出现时更快反应。