
CVE-2026-98432(Linux IPv4 TCP use-after-free)에 대한 가이드 및 읽기 전용 점검 스크립트: 커널 패치 상태를 탐지하고, iptables 임시 방편을 적용하며, 수정 후 검증합니다.
네트워크를 통해 공격 가능하며, 로그인도 사용자 조작도 필요 없습니다. 이 버그는 들어오는 모든 IPv4 TCP 연결을 처리하는 커널 코드에 있습니다.
이 가이드는 서버를 점검하고, 패치된 커널이 나올 때까지 보호하며, 이후 정리하는 방법을 보여줍니다. 아래 명령은 Ubuntu 22.04 및 24.04 서버에서 사용되었습니다.
이 문서의 상태는 2026-10-30 기준입니다. 패치 상태는 빠르게 바뀌므로 항상 사용 중인 배포판의 자체 보안 트래커를 확인하세요.
e3f33b0a1d89쉽게 말하면: 연결 요청(SYN)은 IPv4 옵션을 실을 수 있는데, 이는 Record Route나 Timestamp처럼 패킷 헤더에 드물게 쓰이는 추가 정보입니다. 이런 옵션이 도착하면 커널은 해당 옵션의 사본을 보관합니다. 공격자가 정확한 순간에 SYN을 다시 보내면, 한 CPU가 그 사본을 해제하는 동안 다른 CPU는 여전히 그 사본을 사용해 응답을 만들 수 있습니다. 이것이 ip_options_build()의 use-after-free이며, 서버를 충돌시키거나 커널 메모리를 손상시킬 수 있습니다.
서버가 대기 중인 연결 요청을 소켓 간에 마이그레이션할 때(net.ipv4.tcp_migrate_req=1 또는 BPF_SK_REUSEPORT_SELECT_OR_MIGRATE 프로그램) 두 번째 트리거가 존재합니다. 이 설정은 기본적으로 꺼져 있습니다.
| Ubuntu 우선순위 | 높음 |
| CVSS, 커널 CNA | 9.8 치명적: 네트워크, 인증 없음, 사용자 상호작용 없음 |
| CVSS, Red Hat | 8.1, Red Hat은 이 경쟁 조건이 더 맞추기 어렵다고 판단하기 때문 |
| 영향받는 버전 | 4.4 이후 커널 |
| IPv6 | 주요 문제의 영향을 받지 않음 |
| 악용 | 실제 환경에서 보고된 사례 없음, CISA KEV 목록에도 없음. 멀티패스 TCP(MPTCP) 리스너가 있는 서버를 대상으로 한 원격 루트 익스플로잇이 보고되었으나 공개되지는 않음. |
노출 대상: IPv4를 통해 접근 가능한 TCP 포트가 있는 모든 서버. SSH, HTTP, HTTPS 등 무엇이든 해당됩니다.
| 배포판 | 상태 | 수정된 버전 |
|---|---|---|
| 업스트림 커널 | ✅ 수정됨 | 5.10.272, 5.15.223, 6.1.190, 6.6.159, 6.12.113, 6.18.56, 7.2.10, 7.3 |
| Debian 12 / 13 | ✅ 수정됨 | 6.1.190-1 (또는 linux-6.12 6.12.113-1~deb12u1) / 6.12.113-1 |
| Ubuntu 26.10 / 26.04 / 24.04 / 22.04 | ❌ 수정 진행 중, 미출시 | 예정: 7.3.0-10.10 / 7.0.0-43.43 / 6.8.0-149.149 / 5.15.0-203.213 |
| Ubuntu 20.04 / 18.04 / 16.04 | ❌ 취약함 | Ubuntu Pro(ESM)를 통해서만, 그것도 가능할 경우에만 |
| RHEL 8 / 9 / 10 | ❌ "수정 연기"로 보고됨 | 없음 |
| Oracle Linux (UEK) | ✅ 수정됨 | ELSA-2026-500397 / 500398 / 500399 |
| Amazon Linux 2023 | ⚠️ 부분 수정 | kernel6.18 및 kernel6.12 수정됨; 기본 커널 및 AL2 대기 중 |
| SUSE | ⚠️ 부분 수정 | openSUSE Leap 16.0 수정됨; SLES 진행 중 |
Ubuntu 클라우드 커널(-aws, -azure, -gcp, -oracle)은 자체 버전 번호를 사용합니다. 배포판 커널은 수정 사항을 백포트하므로, 5.15.0-xxx 같은 배포판 버전을 업스트림 번호와 비교하지 마세요.
이 작업은 읽고 보고만 합니다. 아무것도 설치, 변경, 재시작하지 않습니다. 서버의 터미널에 붙여넣으세요:
sudo bash -s <<'EOF'
CVE=CVE-2026-98432; FIX="free inet_opt and ireq_opt"; KR=$(uname -r)
. /etc/os-release
echo "== $PRETTY_NAME | running kernel: $KR"; echo " build: $(uname -v)"
echo "== Installed kernels (if one is newer than the running kernel, you need a reboot)"
ls -1v /boot/vmlinuz-* 2>/dev/null | sed 's|/boot/vmlinuz-| |'
[ -f /var/run/reboot-required ] && echo " !! reboot required"
echo "== Is the fix in the RUNNING kernel's changelog?"
if command -v dpkg >/dev/null; then
dpkg-query -W -f=' package version: ${Version}\n' "linux-image-$KR" 2>/dev/null
zgrep -Eqs "$CVE|$FIX" /usr/share/doc/linux-*"$KR"*/changelog.Debian.gz \
&& echo " PATCHED" || echo " NOT FOUND -> likely VULNERABLE"
command -v pro >/dev/null && pro fix "$CVE" --dry-run </dev/null
elif command -v rpm >/dev/null; then
PKG=$(rpm -qf "/lib/modules/$KR/vmlinuz" "/usr/lib/modules/$KR/vmlinuz" "/boot/vmlinuz-$KR" 2>/dev/null | grep -v 'not owned' | head -1)
echo " package: ${PKG:-unknown}"
rpm -q --changelog "$PKG" 2>/dev/null | grep -Eq "$CVE|$FIX" \
&& echo " PATCHED" || echo " NOT FOUND -> likely VULNERABLE"
if command -v zypper >/dev/null; then zypper -n -q lp -a --cve="$CVE" </dev/null
elif command -v dnf >/dev/null; then dnf -q updateinfo list --all --cve="$CVE" </dev/null
elif command -v yum >/dev/null; then yum -q updateinfo list --cve="$CVE" </dev/null; fi
fi
echo "== Exposure"
sysctl net.mptcp.enabled net.ipv4.tcp_migrate_req 2>/dev/null | sed 's/^/ /'
M=$(ss -lnMH 2>/dev/null); echo " MPTCP listeners (reported root-exploit path): ${M:-none}"
echo " TCP listeners not on loopback (attack surface):"
ss -ltnH | awk '$4 !~ /^(127\.|\[::1\])/ {print " "$4}' | sort -u
EOF
전체를 그대로 붙여넣으세요. 마지막 EOF는 앞에 공백 없이 단독 줄에 있어야 합니다.
출력 읽는 방법:
| 표시되는 내용 | 의미 | 다음 단계 |
|---|---|---|
PATCHED | 실행 중인 커널에 이미 수정 사항이 있음 | 완료 |
NOT FOUND -> likely VULNERABLE | 실행 중인 커널에 수정 사항이 없음 | 2단계 |
!! reboot required, 또는 실행 중인 커널보다 최신 커널이 나열됨 | 최신 커널이 설치되었지만 아직 실행되지 않음 | 3단계 |
A fix is coming soon (Ubuntu) | Ubuntu가 아직 수정 사항을 배포하지 않음 | 지금 2단계, 나중에 5단계 |
MPTCP listeners: none | 보고된 루트 익스플로잇 경로가 현재 적용되지 않음 | — |
*:3306, 0.0.0.0:6379 또는 0.0.0.0:11211 같은 데이터베이스 또는 캐시 포트 | 모든 인터페이스에서 수신 대기 중 | 방화벽이 이를 차단하는지 확인 (4단계 끝부분 참조) |
아래 규칙은 IP 옵션을 포함한 IPv4 TCP 패킷을 드롭하며, 공격자가 버그를 트리거하는 데 필요한 것이 바로 이것입니다. 일반 클라이언트(브라우저, SSH, 휴대폰, API, 로드 밸런서)는 IP 옵션을 전송하지 않으므로 실제 트래픽에는 영향을 주지 않습니다.
먼저 서버가 어떤 방화벽 도구를 사용하는지 확인하세요:
systemctl is-active ufw nftables firewalld
nftables 또는 firewalld가 active 상태라면, 해당 방화벽을 다시 로드할 때 이 규칙이 삭제될 수 있습니다. 이 단계 끝부분에 있는 nftables 변형을 사용하거나, 사용 환경에 맞게 수정하세요.
임시 방편을 설치하세요. 작은 systemd 유닛이므로, 재부팅할 때마다 규칙이 복원됩니다:
sudo tee /etc/systemd/system/cve-2026-98432.service >/dev/null <<'EOF'
[Unit]
Description=Stopgap for CVE-2026-98432: drop IPv4 TCP packets carrying IP options
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/iptables -t raw -I PREROUTING -p tcp -m u32 --u32 "0>>24&0xF=6:15" -m comment --comment CVE-2026-98432 -j DROP
ExecStop=/usr/sbin/iptables -t raw -D PREROUTING -p tcp -m u32 --u32 "0>>24&0xF=6:15" -m comment --comment CVE-2026-98432 -j DROP
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload && sudo systemctl enable --now cve-2026-98432
sudo iptables -t raw -L PREROUTING -v -n
마지막 명령은 CVE-2026-98432라는 주석이 달린 DROP 규칙을 나열해야 합니다. pkts 열은 해당 규칙이 차단한 패킷 수를 나타내며, 0 또는 그에 가까운 값이어야 합니다.
u32 테스트 0>>24&0xF=6:15는 IPv4 헤더 길이 필드를 읽습니다. 정상 헤더는 5 × 4 = 20바이트입니다. 그보다 길면 옵션이 붙어 있다는 뜻이며, 해당 패킷은 드롭됩니다. 이 규칙은 ufw가 관리하지 않는 raw 테이블에 위치하므로 기존 방화벽 규칙은 그대로 유지됩니다.
계속 진행하기 전에 SSH를 확인하세요: 현재 세션을 열어 둔 채 두 번째 터미널에서 로그인하세요. 그런 다음 웹사이트를 로드하세요.
즉시 되돌리려면:
sudo systemctl stop cve-2026-98432
모든 패킷에는 출발지와 목적지 IP를 담는 헤더가 있으며, 연결은 이 헤더를 통해 이루어집니다. 이 규칙은 주소를 무시합니다. 대신 헤더 내부의 거의 사용되지 않는 옵션 확장만 찾으며, 이 확장은 헤더를 20바이트보다 길게 만듭니다. ssh [email protected] 또는 https://1.2.3.4로 연결하는 것은 이전과 정확히 동일하게 작동합니다.
1단계에서 MPTCP listeners: none이 표시되었다면 MPTCP를 꺼도 됩니다. 아무것도 사용하지 않을 때는 무해합니다:
echo 'net.mptcp.enabled = 0' | sudo tee /etc/sysctl.d/99-disable-mptcp.conf
sudo sysctl -p /etc/sysctl.d/99-disable-mptcp.conf
sudo nft add table ip cve98432
sudo nft add chain ip cve98432 pre '{ type filter hook prerouting priority -300; policy accept; }'
sudo nft add rule ip cve98432 pre ip protocol tcp ip hdrlength gt 5 counter drop
# undo: sudo nft delete table ip cve98432
이 규칙은 재부팅 후에도 유지되지 않습니다. 필요하다면 영구 nftables 설정에 추가하세요.
Ubuntu에서는 아직 이 CVE를 해결하는 수정 커널이 없기 때문에 재부팅으로 이 CVE가 해결되지는 않습니다. 다만 이미 설치된 최신 커널이 로드되며, 이 커널에는 보통 수개월 분량의 다른 보안 수정 사항이 포함되어 있습니다.
재부팅 전 확인 사항:
uptime -s; screen -ls; tmux ls
systemctl list-units --type=service --state=running --no-legend | awk '{print $1}' | sort > /root/services-before.txt
그런 다음:
sudo reboot