
Ubuntu 및 Debian에서 패치된 커널을 사용할 수 있을 때까지 CVE-2026-98432를 완화하기 위해 IP 옵션이 포함된 IPv4 TCP 패킷을 드롭하는 영구 iptables 규칙을 설치하는 멱등성 셸 스크립트입니다.
IP 옵션을 포함한 수신 IPv4 TCP 패킷을 차단하고, 재부팅 후에도 규칙을 유지하며, 제대로 작동하는지 확인하는 단일 멱등성 스크립트입니다. 아직 수정된 커널을 적용할 수 없는 Ubuntu(18.04 – 24.04) 및 Debian(11 – 13) 서버를 대상으로 합니다.
이것은 임시 방편이며 수정이 아닙니다. 유일한 실제 수정 방법은 패치된 커널과 재부팅입니다. 서버가 수정된 커널을 실행하게 되면 이 완화 조치를 제거하십시오.
curl -fsSL https://raw.githubusercontent.com/Mervent/cve-2026-98432/master/install.sh | sudo sh
원하는 만큼 여러 번 실행할 수 있습니다. 파일은 덮어쓰여지고 규칙은 절대 중복되지 않습니다. 마지막에 스크립트가 결과를 검증하고, 실패가 하나라도 있으면 0이 아닌 값으로 종료합니다:
--- validation ---
OK helper installed: /usr/local/sbin/cve-2026-98432-mitigation
OK cron entry: /etc/cron.d/cve-2026-98432
OK cron service enabled
OK iptables rule active (raw/PREROUTING)
OK exactly one rule (no duplicates)
plain SYN: connected, SYN with IP options: timeout
OK drop test: packets with IP options are dropped
--- rule counters ---
pkts bytes target prot opt in out source destination
3 204 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 u32 "0x0>>0x18&0xf=0x6:0xf" /* cve-2026-98432 */
| 경로 | 용도 |
|---|---|
/usr/local/sbin/cve-2026-98432-mitigation | 규칙을 보유하는 헬퍼입니다. 인수 없이 실행하면 규칙이 없을 경우 추가합니다. --check는 규칙이 활성 상태이면 종료 코드 0으로 종료합니다. --remove는 규칙을 삭제합니다. |
/etc/cron.d/cve-2026-98432 | 부팅할 때마다 규칙을 다시 적용하는 @reboot 항목 |
규칙 자체는 다음과 같습니다:
iptables -t raw -I PREROUTING -p tcp -m u32 --u32 "0>>24&0xF=6:15" \
-m comment --comment cve-2026-98432 -j DROP
sudo /usr/local/sbin/cve-2026-98432-mitigation --check && echo active
sudo iptables -t raw -L PREROUTING -v -n | grep cve-2026-98432
sudo /usr/local/sbin/cve-2026-98432-mitigation --remove
sudo rm /usr/local/sbin/cve-2026-98432-mitigation /etc/cron.d/cve-2026-98432
배포판이 수정 사항을 제공했는지 확인하려면
Ubuntu 또는 Debian을 확인하세요
(Debian 9 – 11의 경우 Freexian ELTS 트래커).
릴리스에 "Fixed"가 표시되면 apt update && apt full-upgrade를 실행하고 재부팅한 다음, 완화 조치를 제거하세요.
2026년 11월 1일 기준으로 Debian 12(linux 6.1.190-1, DLA-4841-1)와 Debian 13(linux 6.12.113-1,
DSA-6568-1)에는 이미 수정된 커널이 있으므로, 해당 릴리스에서는 이 스크립트를 사용하는 대신 업그레이드하세요.
Debian 11의 수정 사항(linux 5.10.272-1, ELA-1846-1)은 Freexian의 ELTS 저장소에만 있습니다: 상용이지만,
개인 및 소규모 비영리 단체의 경우 요청 시 무료입니다.
CVE-2026-98432("ipv4: free inet_opt and ireq_opt after an RCU grace period")는 IPv4 TCP 핸드셰이크에서 발생하는 use-after-free입니다. Linux 4.4 이상에 영향을 미치며 CVSS 9.8로 평가됩니다.
SYN에 IPv4 옵션이 포함되어 있으면, 커널은 SYN-ACK에 이를 에코할 수 있도록 요청 소켓에 해당 옵션을 저장합니다.
그런 다음 tcp_v4_syn_recv_sock()이 해당 버퍼를 복사하지 않고 자식 소켓에 넘깁니다.
자식 소켓이 종료되면 버퍼는 일반 kfree()로 해제되지만, 다른 CPU가 재전송된 SYN에 대한 SYN-ACK을
생성하기 위해 여전히 해당 버퍼를 읽고 있을 수 있습니다.
이 모든 것은 애플리케이션이 연결을 보기 전에 커널에서 발생합니다. 이 방식으로 모든 수신 대기 중인 IPv4 TCP 포트(SSH, HTTP, PostgreSQL 등)에 접근할 수 있으며, 자격 증명이 필요하지 않습니다. Anthropic은 멀티패스 TCP(MPTCP) 리스너가 있는 호스트를 대상으로 한 원격 루트 익스플로잇이 동작함을 보고했습니다. Go 보안 팀은 이 버그가 MPTCP에 국한된 것이 아니라고 언급합니다.
너무 일찍 해제되는 메모리는 수신 SYN에 IPv4 옵션이 포함된 경우에만 존재합니다. 옵션이 없으면 저장된 버퍼가 없으므로 use-after-free가 작동할 대상이 없습니다. 정상적인 TCP 트래픽은 실제로 IPv4 옵션을 거의 포함하지 않으므로, 해당 패킷을 드롭하는 데는 실질적인 비용이 들지 않습니다. Red Hat (RHSB-2026-016)과 AlmaLinux는 동등한 nftables 규칙을 공개했습니다.
u32 "0>>24&0xF=6:15"는 IHL 필드, 즉 32비트 워드 단위의 IPv4 헤더 길이를 읽습니다. 값 5는
옵션이 없는 20바이트 헤더입니다. 6에서 15까지의 값은 옵션이 존재함을 의미합니다.
Red Hat은 이러한 규칙이 "이 취약점에 대한 노출을 줄이지만 완전히 방지할 수는 없다"고 밝힙니다. 커널이 패치될 때까지는 위험 감소 조치로 취급하세요.
raw / PREROUTING을 사용하는 이유PREROUTING은 호스트로 향하는 트래픽과 게시된 포트의 Docker 컨테이너로 전달되는 트래픽 모두,
모든 수신 패킷을 확인합니다. ufw가 규칙을 배치하는 INPUT에 있는 규칙은 전달되는 트래픽을
놓치게 됩니다.raw 테이블은 연결 추적보다 먼저 실행되므로, 드롭된 패킷은 conntrack 항목을 생성하지 않습니다.raw/PREROUTING을 플러시하지 않으므로, 규칙은 이들의 재시작 후에도 유지됩니다.iptables는 모든 Ubuntu 대상 릴리스에 존재합니다. Ubuntu 18.04 및 20.04에서는 레거시
백엔드를 사용하며, Ubuntu 22.04부터 및 Debian 11+에서는 iptables-nft입니다. nft 바이너리는
모든 곳에 기본 설치되어 있지 않습니다. Debian에서는 iptables 자체가 없을 수 있으며, 이 경우 스크립트가
apt install iptables를 실행하라고 안내합니다.iptables-nft를 사용하면 ufw/Docker와 이 규칙이 nf_tables 백엔드를 공유하므로, 하나의 규칙으로 둘 다
처리됩니다.u32 매치는 xt_u32 커널 모듈이 필요합니다. 이 모듈이 없으면 스크립트가 실패하고
modinfo xt_u32를 확인하라고 안내합니다.@reboot 항목을 사용하는 이유nftables.service가 아닙니다. Ubuntu에서 /etc/nftables.conf는 flush ruleset으로 시작하며,
서비스는 중지 시 nft flush ruleset을 실행합니다. 둘 중 하나만으로도 ufw와 Docker 규칙이 모두 지워집니다.iptables-persistent가 아닙니다. netfilter-persistent save는 Docker의 규칙을 포함한 모든 현재 규칙을
덤프하며, 부팅 시 해당 스냅샷을 복원하면 Docker가 자체적으로 생성하는 규칙과 충돌합니다.before.rules가 아닙니다. 이는 ufw가 활성화된 경우에만 작동하며, 해당 체인은 컨테이너로 전달되는
트래픽을 보지 못합니다./etc/cron.d의 파일은
덮어쓰기 방식으로 멱등적이며, 제거는 rm 한 번이면 됩니다. 단점은 부팅 후 네트워크는 올라왔지만 cron이
아직 규칙을 적용하지 않은 몇 초간의 공백이 있다는 것입니다. 이는 다음 커널 업데이트까지만 유지되면 되는
완화책으로서 허용 가능합니다.net.mptcp.enabled=0을 쓰면 안 되는 이유MPTCP를 비활성화하면 공개된 익스플로잇 하나의 전제 조건이 제거될 뿐, 버그 자체가 사라지는 것은 아닙니다.
일반 TCP 리스너도 여전히 동일한 취약한 코드를 거칩니다. MPTCP 리스너가 없는 서버(ss -Mlnp가 아무것도
출력하지 않음)에서는 이 sysctl이 아무것도 바꾸지 않습니다. 이는 무해한 추가 조치일 뿐, 이 규칙을 대체하지
못합니다.
스크립트는 헬퍼와 cron 항목이 설치되었는지, cron이 활성화되었는지, 그리고 정확히 하나의 규칙이 활성 상태인지
확인합니다. 그런 다음 python3로 종단 간 드롭 테스트를 실행하며, python3가 없으면 건너뜁니다:
127.0.0.1에서 리스너를 엽니다.루프백 트래픽은 raw/PREROUTING을 거치므로, 이는 규칙이 실제로 패킷을 드롭하며 단순히 테이블에 존재하는
것이 아님을 증명합니다.
Ubuntu 24.04 커널 6.8.0-100-generic을 실행하는 Docker 호스트에서 컨테이너(ubuntu:18.04, 20.04, 22.04,
24.04, debian:11-slim, 12-slim, 13-slim)로 실행했습니다. 각 실행은 파이프 설치, 중복 규칙 없이
반복 설치, 드롭 테스트, 그리고 cron @reboot를 통한 제거된 규칙의 복구를 포함했습니다.
| 릴리스 | iptables | 결과 |
|---|---|---|
| Ubuntu 18.04 | 1.6.1 (legacy) | 통과 |
| Ubuntu 20.04 | 1.8.4 (legacy) | 통과 |
| Ubuntu 22.04 | 1.8.7 (nf_tables) | 통과 |
| Ubuntu 24.04 | 1.8.10 (nf_tables) | 통과 |
| Debian 11 | 1.8.7 (nf_tables) | 통과 |
| Debian 12 | 1.8.9 (nf_tables) | 통과 |
| Debian 13 | 1.8.11 (nf_tables) | 통과 |
모든 이미지는 호스트 커널을 공유했습니다. 이들 릴리스의 기본 커널에서 xt_u32의 가용성은 테스트되지
않았으며(Ubuntu 24.04의 6.8 커널만 실행됨), 실제 재부팅은 수행되지 않았습니다.