두 줄로 고친 리눅스 원격 root 구멍, 우분투는 아직

리눅스 서버를 하나라도 돌리고 있다면 오늘 확인할 일이 하나 있다. 서버가 쓰는 커널(운영체제의 핵심 부분)에 이 구멍의 수정이 들어갔는지 보는 것이다. 인터넷에서 접속만 받아도 닿는 곳에 구멍이 있었고, 점수는 10점 만점에 9.8이다.
이 리눅스 원격 root 구멍의 수정 자체는 놀랄 만큼 작다. 커널 코드 두 줄이다. 그런데 11월 1일 아침 우분투의 보안 추적 페이지에는 지원 중인 LTS 22.04·24.04·26.04가 전부 ’취약, 작업 중’으로 적혀 있다. 레드햇은 10월 30일 공지에서 임시 방벽을 내놓으면서 수정은 “서두르고 있다”고 적었다.
이 글은 세 부류를 위해 쓴다. 우분투나 레드햇 계열 VPS·클라우드 서버를 직접 관리하는 사람, 도커나 쿠버네티스 노드의 호스트를 맡은 사람, 그리고 Go 언어로 서버를 만들어 배포하는 개발자다. 앤트로픽의 발표, 레드햇 공지, Go 보안팀 공지, 커널 수정 커밋, 알마리눅스·데비안·우분투 추적 페이지를 직접 열어 맞췄다.
먼저 낱말을 풀어 둔다.
커널은 운영체제의 심장부다. 프로그램이 네트워크로 데이터를 받을 때도 먼저 커널을 거친다. 해제 후 사용(use-after-free)은 이미 반납한 메모리를 다시 읽거나 쓰는 버그다. 반납한 책상 서랍을 열었더니 누가 그 자리에 다른 물건을 넣어 둔 상황과 비슷하다.
경합 상태(race condition)는 두 작업이 거의 동시에 같은 것을 만질 때 순서에 따라 결과가 달라지는 문제다. SYN은 TCP 연결을 시작하는 첫 신호이고, SYN-ACK는 서버가 보내는 응답이다. MPTCP(멀티패스 TCP)는 하나의 연결을 여러 네트워크 경로로 나눠 태우는 TCP 확장이다.
CVSS는 취약점 심각도를 0~10으로 매기는 점수다. 9.0 이상이 ’심각’이다.
11월 1일 아침의 배포판 현황: 고친 곳과 못 고친 곳
먼저 지금 상황부터 표로 놓는다. 아래는 이 글을 쓰던 11월 1일 오전(한국 시간)에 각 배포판의 추적 페이지를 직접 열어 읽은 값이다. 배포판 페이지는 수시로 바뀌니 적용하기 전에 다시 확인하자.
| 배포판 | 상태 | 읽은 곳 |
|---|---|---|
| 우분투 22.04 · 24.04 · 26.04 · 26.10 | 취약, 작업 중 (각각 5.15.0-203.213, 6.8.0-149.149, 7.0.0-43.43, 7.3.0-10.10 에서 작업) | 우분투 보안 추적 페이지 |
| 우분투 20.04 · 18.04 · 16.04 | 취약 | 같은 페이지 |
| 우분투 14.04 | 영향 없음 | 같은 페이지 |
| 레드햇 RHEL 8 · 9 · 10, 오픈시프트 | 영향받음, 공지는 “수정을 서두르는 중”이고 상태는 ‘진행 중’ | 레드햇 보안 공지 RHSB-2026-016 |
| 알마리눅스 8 · 9 · 10 | 수정 커널이 테스트 저장소에 있음 (10월 30일) | 알마리눅스 블로그 |
| 데비안 12 bookworm | 수정됨 (보안 저장소 6.1.190-1) | 데비안 보안 추적 페이지 |
| 데비안 13 trixie | 수정됨 (보안 저장소 6.12.113-1) | 같은 페이지 |
우분투 페이지는 CVSS 3 점수 9.8(심각)과 우선순위 ’높음(High)’을 표시한다. 이 페이지는 10월 15일에 공개돼 10월 30일에 마지막으로 고쳐졌다.
레드햇은 자기 CVE 페이지에서도 이 구멍을 ’심각(Critical)’으로 매겼다. 설명에 적힌 이유는, 인증 없는 원격 공격자가 평범한 IPv4 TCP 통신만으로 커널 메모리 손상이나 즉시 충돌을 일으킬 수 있고 권한이나 사용자 동작이 필요 없다는 점이다.
표에서 읽을 건 하나다. 업스트림(커널 원본) 수정은 10월 초에 나왔는데, 많은 서버가 쓰는 우분투와 레드햇은 11월 1일 아침 내가 본 페이지에 수정 커널이 나왔다는 표시가 없었다. 직접 커널을 빌드하지 않는 사람은 배포판이 낼 때까지 아래 임시 방벽으로 버텨야 한다.
구멍은 연결 요청에 붙은 옵션 한 줄에서 시작한다
수정 커밋의 설명문과 알마리눅스의 풀이를 합치면 구멍의 구조는 이렇다. 누군가 서버에 TCP 연결을 요청하면(SYN) 커널은 이 요청을 ’임시 접수대’에 올려 둔다. 요청에 IPv4 옵션이 붙어 있으면 커널은 그 옵션을 보관해 뒀다가 응답(SYN-ACK)에 되돌려 보낸다.
연결이 완성되면 이 보관분이 새 소켓(연결 하나를 대표하는 커널 객체)으로 넘어간다. 문제는 넘길 때 복사하지 않고 소유권만 넘긴다는 점이다. 이 순간 다른 CPU가 같은 요청의 재전송분을 처리하며 보관된 옵션을 읽고 있을 수 있다.
그사이 새 소켓이 닫히고 옵션이 바로 해제되면, 다른 CPU는 이미 반납된 메모리를 읽는다. 이것이 ’해제 후 사용’이다. 커밋 설명은 원인을 이렇게 짚는다. ‘tcp/dccp: install syn_recv requests into ehash table’ 이후로 요청이 리스너 잠금 없이 처리되기 때문에, 응답을 만드는 동안 자식 소켓이 해제될 수 있다. 커밋 아래 Fixes 줄에는 이 커밋과, 요청 이동을 다루는 다른 커밋 하나가 같이 적혀 있다.
알마리눅스는 이 버그가 Linux 4.4(2016년 1월에 나온 버전)까지 거슬러 올라간다고 적었다. 커밋에는 두 번째 경로도 있다. 요청 이동(net.ipv4.tcp_migrate_req=1이거나 BPF 프로그램이 요청을 옮기는 설정)을 쓰면 같은 문제가 생기는데, 알마리눅스는 이 설정이 기본 꺼짐이라고 밝혔다.
IPv6는 첫 번째 문제의 영향을 받지 않는다. IPv6 쪽 소켓은 옵션을 복사해 넘기기 때문이다. 다만 커밋은 IPv6의 요청 이동 경로에 같은 종류의 문제가 있고 “별도 패치에서 다룰 것”이라고 적었다.
리눅스 원격 root 구멍, 고친 곳은 두 줄이다
수정은 에릭 두마제(Eric Dumazet)가 10월 1일(UTC)에 올렸다. 한국 시간으로는 10월 2일 오전 7시 12분이다. 이 커밋은 kfree()를 kfree_rcu()로 바꾼다. 풀어 말하면 “바로 반납”을 “다른 CPU들이 다 읽고 나간 뒤에 반납”으로 바꾸는 것이다.
커밋의 실제 변경은 이렇다(앞뒤 문맥은 줄였다).
--- a/net/ipv4/af_inet.c
- kfree(rcu_dereference_protected(inet->inet_opt, 1));
+ kfree_rcu(rcu_dereference_protected(inet->inet_opt, 1), rcu);
--- a/net/ipv4/tcp_ipv4.c
- kfree(rcu_dereference_protected(inet_rsk(req)->ireq_opt, 1));
+ kfree_rcu(rcu_dereference_protected(inet_rsk(req)->ireq_opt, 1), rcu);
두 파일, 두 줄이다. 커밋 설명에 따르면 읽는 쪽은 이미 RCU로 보호되고, 옵션을 교체하는 다른 경로들(do_ip_setsockopt() 등)도 이미 kfree_rcu()를 쓰고 있었다. 이 두 곳에도 같은 방식을 쓰도록 맞춘 것이다.
커밋의 Reported-by 줄에는 anthropic.com 주소의 Xinyang Ge가, Reviewed-by 줄에는 Kuniyuki Iwashima(구글 주소)가 적혀 있다.
앤트로픽이 이은 두 단계: 포인터 48분, 셸 5분
이 리눅스 원격 root 구멍이 요 며칠 화제가 된 이유는 수정이 작아서가 아니다. 앤트로픽이 10월 27일 올린 연구 글에서 Claude가 이 구멍으로 원격 root 권한을 얻는 코드를 작성했다고 밝혔기 때문이다.
글의 첫머리에 따르면 앤트로픽은 지난 몇 달 동안 아직 공개하지 않은 내부 연구용 모델로 브라우저와 운영체제의 심각한 취약점을 찾았다. 글에는 다섯 건의 공격 사슬이 나온다. 크롬 원클릭 원격 코드 실행, 사파리 원클릭 사슬, 안드로이드 잠금 화면 우회, 윈도우 원격 서비스 거부, 그리고 다섯 번째가 이 리눅스 건이다.
앤트로픽은 이 글에서 Claude가 “초기 프롬프트 이후” 익스플로잇을 썼다고 적었다. MPTCP 리스너(멀티패스 TCP로 접속을 받는 서버 프로그램)가 열려 있는 리눅스 서버에서 원격 공격자가 자격 증명이나 사용자 동작 없이 root 권한으로 임의 명령을 실행하는 코드다. 두 단계로 나뉜다고 한다.
첫째 단계는 커널 주소 배치를 알아내는 일이다. 경합을 일으켜 커널이 공격자가 정한 길이만큼 여분의 바이트를 복사해 응답에 실어 보내게 하고, 그 안에 커널 포인터가 한 번이라도 섞이면 주소 배치를 안다. 둘째 단계는 같은 버그로 버퍼를 넘치게 해 콜백 포인터를 덮어쓰고, 미리 올려 둔 페이로드가 기존 커널 함수들을 이어 불러 공격자가 고른 셸 명령을 root로 실행하게 하는 일이다.
수치는 이렇다. 앤트로픽의 개념 증명(PoC)에서 커널 포인터를 알아내는 데 48분, 거기서 셸 명령 실행까지 5분이 걸렸다. 앤트로픽은 이 경합에서 지면 핸드셰이크만 실패하고 시스템 전체가 죽지는 않아서, 공격자가 성공할 때까지 계속 재시도할 수 있다고 설명했다.
글에는 익스플로잇 코드가 실려 있지 않다. 앤트로픽은 이 취약점이 업스트림에서 이미 고쳐졌고 유지보수 중인 모든 안정 커널 가지에 반영됐다고 적었다. 공개 원칙도 글에 있다. 개발사에 90일의 패치 시간을 주고, 그 뒤 45일이 더 지나기 전에는 공개된 보안 권고 이상의 세부를 말하지 않는다.
비슷한 흐름을 다룬 제미나이 4 카본 글에서도 보안 능력이 높은 모델을 누구에게 열어 주느냐가 쟁점이었다. 이번 앤트로픽 글도 방어하는 쪽을 위한 접근 확대(사이버 검증 프로그램)를 함께 언급한다. 권고는 하나로 모인다. 내 코드를 먼저 스캔하라는 것이다. 앤트로픽은 풀 리퀘스트 단계에서 스캔하는 방식을 추천하고, 이를 위한 Claude Code 플러그인을 공개했다고 밝혔다.
왜 하필 MPTCP인가, 그리고 Go 서버는 왜 거론되나
앤트로픽의 시연 조건은 MPTCP 리스너다. 여기서 평범한 서버 관리자가 놓치기 쉬운 점이 나온다. 직접 MPTCP를 켠 적이 없어도 MPTCP 리스너를 열고 있을 수 있다.
Go 보안팀이 10월 29일(미국 서부 시간) 공지에서 이렇게 밝혔다. Go 1.24부터 Go 프로그램은 리눅스에서 리스닝 소켓에 MPTCP를 기본으로 켠다. Go 공식 godebug 문서에도 같은 내용이 있다. Go 1.24에서 multipathtcp 기본값이 “2”, 곧 리스너에만 켜짐이 됐다.
다만 배포판마다 커널 설정이 다르다. 알마리눅스는 자기 배포판이 MPTCP를 기본 꺼짐으로 출하해서, 관리자가 켜지 않는 한 애플리케이션이 MPTCP 리스너를 열 수 없다고 밝혔다. 우분투나 다른 배포판의 기본값은 이 글에서 확인하지 못했으니 아래 명령으로 직접 본다.
Go 보안팀이 가장 강조한 문장은 따로 있다. 시연된 익스플로잇이 MPTCP 리스너를 요구해도 “근본 버그는 MPTCP에 한정되지 않으며”, MPTCP 리스너가 없는 시스템도 비슷한 공격에 취약할 가능성이 있다는 것이다. 그래서 Go팀은 프로그램마다 MPTCP를 끄는 방식을 “깨지기 쉬운 완화책”이라 부르며, 가장 좋은 해법은 패치된 커널로 올리는 것이라고 거듭 적었다.
Go팀은 같은 공지에서 지금 Go의 기본값을 바꾸는 것은 시기상조라고 밝혔고, 논의는 go.dev/issue/82717에서 이어진다고 했다.
같은 회사 두 페이지가 다르게 말하는 것
읽다가 눈에 걸린 대목이 있다. 레드햇의 보안 공지(RHSB-2026-016)는 “인증 없는 원격 공격자가 경합 상태를 이용해 원격 코드 실행을 일으킬 수 있다”고 쓴다. 같은 회사의 CVE 페이지는 설명란에서 “주로 시스템 충돌에 따른 서비스 거부 또는 메모리 손상 가능성”이라고 쓴다.
두 문장은 모순이 아니라 강조점이 다르다. CVE 페이지의 설명(Statement) 항목은 이렇게 이어진다. 이 타이밍 의존적 해제 후 사용으로 코드를 안정적으로 실행하려면 정밀한 힙 제어가 필요하지만, 네트워크 선행 조건이 없고 심각한 시스템 불안정이 가능해서 등급을 ’중요’보다 높였다.
여기서 읽을 점은 두 가지다. 레드햇은 원격 코드 실행이 쉽다고 말하지 않았다. 반대로 앤트로픽은 시연 환경에서 실제로 해냈다고 밝혔고, 그 코드는 공개하지 않았다. 둘 다 문서에 적힌 사실이다. 이 둘을 합친 내 해석은 이렇다. 서버를 멈추게 하는 쪽이 훨씬 쉽고, root까지 가는 쪽은 어렵지만 가능하다는 것이 한 번 시연됐다.
오늘 확인할 세 가지
여기서부터는 서버에 직접 들어가서 한다. 아래 명령은 읽기만 하거나, 알마리눅스 공지가 안내한 절차 그대로다. 윈도우 노트북만 있는 사람은 건너뛰어도 된다.
1) 돌고 있는 커널 버전. uname -r로 지금 부팅된 커널을 본다. 레드햇 계열이면 rpm -q kernel로 설치된 커널 목록을 본다. 설치된 커널이 새것이어도 재부팅 전에는 옛 커널이 돈다. 알마리눅스 공지가 확인 방법으로 uname -r 또는 rpm -q kernel을 안내한다.
2) MPTCP가 켜져 있는지. sysctl net.mptcp.enabled를 실행한다. 0이면 새 MPTCP 소켓이 만들어지지 않는다. 1이면 MPTCP 소켓이 가능하다.
3) 이미 열린 MPTCP 리스너. sudo ss -lnMp로 MPTCP로 열린 리스닝 소켓과 그 프로세스를 본다. 알마리눅스 공지가 쓴 명령 그대로다. 출력이 비어 있으면 MPTCP 리스너는 없다.
기억할 것: 도커 컨테이너는 호스트의 커널을 쓴다. 그러니 컨테이너 안에서 uname -r을 쳐도 호스트 커널이 나온다. 새 이미지를 받아도 커널은 바뀌지 않는다. 호스트를 올려야 한다.
못 고칠 때: 레드햇과 알마리눅스가 낸 임시 방벽
원인이 ’IPv4 옵션이 붙은 TCP 연결 요청’이므로, 임시 방벽도 그것을 막는 방식이다. 일반 TCP 트래픽에는 IPv4 옵션이 거의 붙지 않는다. 레드햇은 공지에서 이 규칙이 노출을 줄이지만 완전히 막지는 못한다고 못 박았다.
레드햇의 규칙은 아래와 같다. 파일 cve-2026-98432.nft에 저장해서 쓴다.
table inet cve_2026_98432 {
chain input {
type filter hook input priority -310; policy accept;
ip protocol tcp ip hdrlength > 5 counter drop
}
}
ip hdrlength > 5는 IP 헤더 길이가 기본(20바이트, 값으로는 5)보다 길다는 뜻이다. 옵션이 붙으면 그만큼 길어진다. 적용은 sudo nft --check --file cve-2026-98432.nft로 문법을 확인하고 sudo nft --file cve-2026-98432.nft로 올린다. 커널을 고친 뒤에는 sudo nft delete table inet cve_2026_98432로 지운다.
알마리눅스는 비슷하지만 다른 위치(prerouting, 우선순위 -300)에 규칙을 건다. 이 위치는 컨테이너로 전달되는 트래픽까지 걸러내지만, 같은 호스트 안의 컨테이너끼리 주고받는 트래픽은 규칙을 우회할 수 있다고 알마리눅스는 경고한다. 네트워크가 IPv4 옵션에 담긴 CIPSO 보안 레이블(NetLabel)에 기대고 있다면 이 규칙을 쓰면 안 된다는 경고도 있다.
알마리눅스 공지는 자기 규칙이 재부팅하면 사라지니 다시 실행하라고 적었다. 레드햇 공지에는 이 부분이 없으니 저장 방법은 자기 환경에서 확인해야 한다. 운영 환경에 올리기 전에 자기 트래픽으로 먼저 시험하라고 레드햇은 경고한다.
MPTCP가 필요 없다면 끄는 방법도 알마리눅스가 안내한다. echo 'net.mptcp.enabled = 0' | sudo tee /etc/sysctl.d/90-disable-mptcp.conf로 부팅 후에도 유지되게 하고, sudo sysctl -w net.mptcp.enabled=0으로 바로 적용한다. 이미 열린 MPTCP 리스너는 그대로이니 sudo ss -lnMp로 찾아서 그 서비스를 재시작한다. 알마리눅스 스스로 이 두 단계는 해결책이 아니니 패치된 커널을 올리고 재부팅하라고 적었다.
Go로 서버를 만든다면
Go 보안팀 공지가 알려 준 끄는 법은 세 가지다. 환경 변수 GODEBUG=multipathtcp=0을 주면 실행 때 기본값이 꺼진다. 메인 모듈의 go.mod에 godebug multipathtcp=0 줄을 넣으면 빌드 때 기본값이 꺼진다. 코드에서 net.ListenConfig.SetMultipathTCP나 net.Dialer.SetMultipathTCP로 소켓마다 켜고 끌 수도 있고, 이 함수들은 GODEBUG보다 우선한다.
이것은 앞서 말한 대로 깨지기 쉬운 임시 조치다. 리스너 하나가 어디선가 켜진 채로 남으면 구멍이 열려 있다. MPTCP를 쓰지 않는다면 서버 쪽에서 net.mptcp.enabled=0으로 한 번에 끄는 편이 낫다.
이미 배포한 Go 바이너리가 MPTCP를 켜고 나가는지는 go.mod가 가른다. Go 문서에 따르면 GODEBUG 기본값은 빌드한 툴체인의 기본값을 바탕으로 하되 go.mod에 적힌 Go 버전에 맞춰 조정된다. go.mod의 go 줄이 1.24 미만이면 1.24에서 바뀐 이 기본값은 켜지지 않는다. godebug 줄은 Go 1.23부터 go.mod에 쓸 수 있다. 배포 중인 서비스의 go.mod부터 열어 보는 것이 첫걸음이다.
이 글의 숫자와 날짜는 어디서 왔나
| 항목 | 값 | 출처 |
|---|---|---|
| 수정 커밋 | e3f33b0a1d89, 2026-10-01 22:12:53 UTC | 커널 커밋(.patch) |
| CVE 공개일 | 2026-10-15 | 우분투 추적 페이지 |
| 심각도 | CVSS 3.1 9.8 (네트워크·낮은 난이도·권한 없음·사용자 동작 없음) | 레드햇 CVE 페이지의 cve.org 열 |
| 앤트로픽 글 | 2026-10-27, Frontier Red Team | 앤트로픽 연구 글 |
| PoC 시간 | 포인터 유출 48분 + 셸 실행 5분 | 같은 글 |
| 영향 범위 시작 | Linux 4.4 | 알마리눅스 블로그 |
| Go 공지 | 2026-10-29 16:34 PDT (한국 10월 30일 08:34) | oss-security 전달본 |
| 레드햇 공지 | 2026-10-30 (RHSB-2026-016) | 레드햇 |
| 알마리눅스 테스트 커널 | 2026-10-30 | 알마리눅스 블로그 |
수정이 들어간 안정 커널 버전은 데비안 추적 페이지가 업스트림 7.3-rc7에 반영됐다고 알려 준다. 데비안 보안 저장소의 수정판은 6.1.190-1(bookworm)과 6.12.113-1(trixie)이다. 다른 가지의 수정 버전 목록은 커널 CNA 공지에 있는데, 그 주소는 봇 확인 화면이 떠서 이 글을 쓰며 직접 열지 못했다. 그래서 가지별 정확한 수정 버전은 이 글에서 약속하지 않는다. 자기 배포판의 추적 페이지를 보자.
이 글이 확인하지 못한 것
다섯 가지를 솔직히 적는다.
첫째, 나는 윈도우 PC에서 이 글을 썼다. 그래서 위의 리눅스 명령을 직접 실행해 보지 못했다. 명령은 알마리눅스 공지가 안내한 그대로다.
둘째, 익스플로잇을 돌려 보지 않았다. 앤트로픽도 코드를 공개하지 않았고, 이 글은 앤트로픽이 글로 밝힌 주장을 옮긴 것이다. 48분과 5분은 앤트로픽 환경의 시연 수치이지 내가 재현한 값이 아니다.
셋째, 우분투 같은 배포판이 MPTCP를 기본으로 켜는지는 확인하지 못했다. 알마리눅스가 꺼져 있다는 것만 확인했다.
넷째, WSL2나 도커 데스크톱 같은 윈도우 위 리눅스 가상 환경의 커널이 영향권인지는 확인하지 못했다.
다섯째, 레드햇이 수정 커널을 언제 낼지는 알려진 바 없다. 레드햇 공지는 “진행 중”이라고만 적고 있고, 이 상태는 공지가 갱신되면 바뀐다.
이 리눅스 원격 root 구멍을 둘러싼 이야기는 앞으로도 갱신될 것이다. 우분투 수정 커널이 나오는지, 레드햇 수정 커널이 나오는지, 그리고 다른 공격 경로가 보고되는지가 다음 확인거리다. 내 서버의 커널 버전을 오늘 한 번 보자.
앞서 쓴 클로드 코드 확장 백도어 글과 이 글은 서로 다른 사건이지만 같은 날을 사는 개발자에게 같은 질문을 던진다. 내가 쓰는 도구와 서버가 어떤 경로로 업데이트되는지, 그 길목에서 누가 확인하는지 알고 있는가.
출처 목록
- 앤트로픽 Frontier Red Team, “Discovering and exploiting vulnerabilities in critical, real-world software with Claude” (2026-10-27): https://www.anthropic.com/research/discovering-vulnerabilities-with-claude
- 커널 수정 커밋 e3f33b0a1d89 “ipv4: free inet_opt and ireq_opt after an RCU grace period”: https://github.com/torvalds/linux/commit/e3f33b0a1d89d738e2b913dab519226eaf76e15b
- 레드햇 보안 공지 RHSB-2026-016: https://access.redhat.com/security/vulnerabilities/RHSB-2026-016
- 레드햇 CVE 페이지: https://access.redhat.com/security/cve/CVE-2026-98432
- Go 보안팀 공지 “Protecting against CVE-2026-98432”: https://groups.google.com/g/golang-announce/c/PCoQcdxoScw
- Go 공식 문서 godebug: https://go.dev/doc/godebug
- 알마리눅스 블로그 (2026-10-30): https://almalinux.org/blog/2026-10-30-cve-2026-98432/
- 우분투 보안 추적 페이지: https://ubuntu.com/security/CVE-2026-98432
- 데비안 보안 추적 페이지: https://security-tracker.debian.org/tracker/CVE-2026-98432