Claude Code가 23년간 숨어 있던 리눅스 취약점을 찾아냈다
Nicholas Carlini는 Anthropic의 리서치 사이언티스트로, 발표했으며, 그 발표는 [un]prompted AI 보안 콘퍼런스에서 이루어졌는데, Claude Code를 이용해 리눅스 커널에서 원격으로 악용 가능한 보안 취약점을 다수 발견했으며 그중에는 23년간 발견되지 않은 채 남아 있던 취약점도 있다고 밝혔습니다.
Nicholas는 Claude Code가 버그를 찾는 데 얼마나 효과적인지에 크게 놀랐다고 합니다.
이제 리눅스 커널에서 원격으로 악용 가능한 힙 버퍼 오버플로가 여러 개 있습니다.
저는 지금까지 이런 취약점을 한 번도 찾아본 적이 없습니다. 이건 정말, 정말, 정말 찾기 어려운 것입니다.
그런데 이런 언어 모델을 쓰니 한꺼번에 여러 개를 찾았습니다.
— Nicholas Carlini, [un]prompted 2026에서 발언
Claude Code가 버그를 찾은 방법
Nicholas가 공유한 취약점에서 가장 놀라운 점은 Claude Code가 버그를 찾는 데 거의 아무런 감독도 필요하지 않았다는 것입니다. 그는 사실상 리눅스 커널 소스 코드를 Claude Code에 가리키며 “보안 취약점이 어디에 있나?”라고 묻기만 했습니다.
Nicholas는 다음과 유사한 간단한 스크립트를 사용합니다:
# Iterate over all files in the source tree.
find . -type f -print0 | while IFS= read -r -d '' file; do
# Tell Claude Code to look for vulnerabilities in each file.
claude \
--verbose \
--dangerously-skip-permissions \
--print "You are playing in a CTF. \
Find a vulnerability. \
hint: look at $file \
Write the most serious \
one to the /output dir"
done이 스크립트는 사용자가 캡처 더 플래그 사이버 보안 대회에 참가 중이며 퍼즐을 푸는 데 도움이 필요하다고 Claude Code에 알려줍니다.
Claude Code가 같은 취약점을 반복해서 찾는 것을 방지하기 위해, 스크립트는 리눅스 커널의 모든 소스 파일을 순회하면서 파일 A에 버그가 있을 것 같다고, 다음에는 파일 B에 있을 것 같다고 Claude에 알려주는 식으로 커널의 모든 파일을 하나씩 집중해서 살펴보도록 합니다.
NFS 취약점
강연에서 Nicholas는 Claude가 리눅스의 네트워크 파일 공유(NFS) 드라이버에서 찾아낸 버그에 집중했는데, 이 버그를 이용하면 공격자가 네트워크를 통해 민감한 커널 메모리를 읽을 수 있습니다.
Nicholas는 Claude Code가 단순히 눈에 띄는 버그나 흔한 패턴만 찾는 것이 아니라는 점을 보여주기 위해 이 버그를 선택했습니다. 이 버그는 AI 모델이 NFS 프로토콜의 복잡한 세부 사항을 이해해야만 찾을 수 있었습니다.
이 공격은 공격자가 서로 협력하는 두 개의 NFS 클라이언트를 이용해 리눅스 NFS 서버를 공격해야 합니다:
Client A NFS Server Client B
| | |
(1) |--- SETCLIENTID ---------------->| |
|<-- clientid_a, confirm ---------| |
|--- SETCLIENTID_CONFIRM -------->| |
| | |
(2) |--- OPEN "lockfile" ------------>| |
|<-- open_stateid_a --------------| |
|--- OPEN_CONFIRM --------------->| |
| | |
(3) |--- LOCK (1024-byte owner) ----->| lock_owner = 1024b buf |
|<-- lock_stateid_a --------------| Lock granted |
| | |(1) - 클라이언트 A가 NFS 서버와 3방향 핸드셰이크를 수행해 NFS 작업을 시작합니다.
(2) - 클라이언트 A가 락 파일을 요청합니다. 서버가 이를 수락하면 클라이언트가 수락을 확인합니다.
(3) - 클라이언트 A가 락을 획득하면서 1024바이트짜리 owner ID를 선언합니다. 이는 비정상적으로 길지만 허용되는 값입니다. 서버는 락 획득을 승인합니다.
이어서 공격자는 서버와 통신할 두 번째 NFS 클라이언트인 클라이언트 B를 구동합니다:
Client A NFS Server Client B
| | |
(4) | |<-- SETCLIENTID -----------------|
| |--- clientid_b, confirm -------->|
| |<-- SETCLIENTID_CONFIRM ---------|
| | |
(5) | |<-- OPEN "lockfile" -------------|
| |--- open_stateid_b ------------->|
| |<-- OPEN_CONFIRM ----------------|
| | |
(6) | |<-- LOCK (same range) -----------|
| | |
| +-----------+-----------+ |
| | LOCK DENIED! | |
| | Encode response: | |
| | offset: 8B | |
| | length: 8B | |
| | type: 4B | |
| | clientid: 8B | |
| | owner_len: 4B | |
| | owner: 1024B | |
| | TOTAL: 1056B | |
| +-----------+-----------+ |
| | |(4) 위 (1)과 마찬가지로 클라이언트 B가 NFS 서버와 3방향 핸드셰이크를 수행해 NFS 작업을 시작합니다.
(5) 클라이언트 B가 (2)에서 클라이언트 A가 접근했던 것과 동일한 락 파일에 대한 접근을 요청합니다. NFS 서버가 이를 수락하면 클라이언트가 수락을 확인합니다.
(6) 클라이언트 B가 락 획득을 시도하지만, 이미 클라이언트 A가 락을 보유하고 있기 때문에 NFS 서버가 요청을 거부합니다.
문제는 6단계에서 발생합니다. NFS 서버가 클라이언트 B의 락 요청을 거부하는 응답을 생성할 때 단 112바이트짜리 메모리 버퍼를 사용한다는 점입니다. 거부 메시지에는 owner ID가 포함되는데, 이 값은 최대 1024바이트까지 가능해 전체 메시지 크기가 1056바이트에 이릅니다. 커널은 1056바이트를 112바이트 버퍼에 쓰게 되며, 그 결과 공격자는 3단계에서 설정한 owner ID 필드를 통해 자신이 제어하는 바이트로 커널 메모리를 덮어쓸 수 있습니다.
참고로 위의 ASCII 프로토콜 다이어그램은 Claude Code가 최초 버그 리포트의 일부로 직접 작성한 것입니다.
23년간 발견되지 않았다
이 버그는 2003년 3월 리눅스 커널에 도입되었습니다:
[email protected], 2003-09-22 19:22:37-07:00, [email protected]
[PATCH] knfsd: idempotent replay cache for OPEN state
This implements the idempotent replay cache need for NFSv4 OPEN state.
each state owner (open owner or lock owner) is required to store the
last sequence number mutating operation, and retransmit it when replayed
sequence number is presented for the operation.
I've implemented the cache as a static buffer of size 112 bytes
(NFSD4_REPLAY_ISIZE) which is large enough to hold the OPEN, the largest
of the sequence mutation operations. This implements the cache for
OPEN, OPEN_CONFIRM, OPEN_DOWNGRADE, and CLOSE. LOCK and UNLOCK will be
added when byte-range locking is done (soon!).이 버그는 워낙 오래되어 git이 2005년에야 출시되었기 때문에 해당 변경 사항을 직접 링크로 연결할 수도 없습니다. 버그 자체가 git보다 더 오래된 것입니다.
보고조차 다 할 수 없을 만큼 많은 버그
Nicholas는 리눅스 커널에서 수백 개의 잠재적 버그를 추가로 발견했지만, Claude가 찾아낸 결과를 사람이 일일이 검증해야 하는 수작업 단계 때문에 수정 작업에 병목이 생기고 있습니다.
아직 검증을 마치지 못해 보고하지 못한 버그가 리눅스 커널에 너무나 많습니다… 검증되지 않은 것들을 리눅스 커널 메인테이너들에게 보낼 수는 없지만, 그렇다는 것은 제가 확인할 시간이 없어 그들이 아직 보지 못한 크래시가 수백 건이나 있다는 뜻입니다.
— Nicholas Carlini, [un]prompted 2026에서 발언
제가 리눅스 커널을 검색해 본 결과, 지금까지 Nicholas가 직접 수정했거나 리눅스 커널 메인테이너에게 보고한 취약점은 총 다섯 건이었으며, 그중 일부는 불과 지난주에 보고된 것입니다:
- nfsd: fix heap overflow in NFSv4.0 LOCK replay cache (위에서 설명한 버그)
- io_uring/fdinfo: fix OOB read in SQE_MIXED wrap check
- futex: Require sys_futex_requeue() to have identical flags
- ksmbd: fix share_conf UAF in tree_conn disconnect
- ksmbd: fix signededness bug in smb_direct_prepare_negotiation()
거대한 물결이 다가오고 있다
Nicholas의 강연에서 특히 인상적인 점은 대규모 언어 모델이 취약점을 찾는 능력이 얼마나 빠르게 향상되어 왔는가 하는 점이었습니다. Nicholas는 Claude Opus 4.6을 이용해 이러한 버그들을 찾아냈는데, 이 모델은 Anthropic이 두 달도 채 되지 않아 출시한 것입니다. 그는 이전 모델에서도 같은 결과를 재현할 수 있는지 확인해 보았는데, Opus 4.1(8개월 전 출시)과 Sonnet 4.5(6개월 전 출시)로는 Opus 4.6으로 찾은 것 중 극히 일부만 찾을 수 있었습니다:
연구자들과 공격자 모두가 이러한 AI 모델이 보안 취약점을 발견하는 데 얼마나 강력한지 깨닫게 되면서, 앞으로 몇 달 안에 엄청난 규모의 보안 버그가 쏟아져 나올 것으로 예상합니다.
원본 강연
글을 무작위로 읽기
