RSS
보안

보안 업데이트는 켜 두었는데, 왜 서버는 1년 전 커널로 돌고 있었을까?

작성자
듀오랩스 대표·10분 읽기

리눅스 서버에 자동 보안 업데이트를 켜 두면 한시름 놓게 됩니다. 매일 새벽 패치가 내려오고, 로그에는 「설치 완료」가 쌓입니다. 그런데 커널만큼은 이야기가 다릅니다. 설치와 적용 사이에 재부팅이 있고, 그 재부팅은 아무도 대신 해 주지 않습니다.

이 글은 최근 한 고객사 서버에서 실제로 본 일에서 시작합니다. 그리고 그 일이 왜 예전보다 지금 더 위험한지, 그 이유가 AI에 있다는 이야기를 합니다.

388일 동안 꺼지지 않은 서버

고객사 사내망 점검 중에 리눅스 서버 한 대의 가동 시간이 눈에 띄었습니다.

$ uptime
up 388 days

1년 넘게 한 번도 재부팅하지 않은 서버였습니다. 안정적으로 돌았다는 뜻이기도 하지만, 커널 입장에서는 다른 뜻입니다.

$ uname -r                       # 지금 돌고 있는 커널
6.8.0-83-generic

$ ls /boot/vmlinuz-*             # 디스크에 설치돼 있는 커널
6.8.0-83-generic
6.8.0-146-generic

$ cat /var/run/reboot-required
*** System restart required ***

자동 업데이트는 성실하게 일하고 있었습니다. 최신 커널(146)이 이미 설치돼 있었고, 시스템은 「재부팅이 필요하다」는 표시까지 남겨 두었습니다. 그런데 메모리에서 실제로 돌고 있는 것은 1년 전 커널(83)이었습니다. 그 사이에 나온 커널 보안 수정은 디스크에만 있고 실행되지는 않은 상태였습니다.

재부팅에 걸린 시간은 55초였습니다. 컨테이너 22개가 모두 재시작 정책을 갖고 있어서 저절로 다시 떴고, 서비스가 멈춘 시간은 몇 분이었습니다. 1년 동안 미뤄 온 일의 비용이 그 정도였습니다.

설치와 적용은 다르다

패키지를 업데이트하면 디스크의 파일이 바뀝니다. 대부분의 프로그램은 다음에 실행할 때 새 파일을 읽으니, 설치가 곧 적용처럼 느껴집니다.

커널은 다릅니다. 부팅할 때 한 번 메모리에 올라가고, 그 뒤로는 디스크의 파일을 다시 보지 않습니다. 새 커널 패키지를 아무리 설치해도 재부팅 전까지는 옛 커널이 그대로 돕니다. libc 같은 핵심 라이브러리도 비슷합니다. 이미 떠 있는 프로세스는 옛 파일을 메모리에 붙든 채로 계속 돕니다.

그래서 Ubuntu의 자동 업데이트(unattended-upgrades)는 기본 설정으로 설치까지만 합니다. 서비스를 마음대로 내리지 않으려는 합리적인 기본값입니다. 다만 그 결과 「업데이트는 켜 두었으니 안전하다」는 믿음과 실제 상태 사이에 틈이 생깁니다.

확인은 어렵지 않습니다.

확인 명령
지금 도는 커널 uname -r
설치된 커널 ls /boot/vmlinuz-*
재부팅이 필요한가 cat /var/run/reboot-required
무엇 때문에 필요한가 cat /var/run/reboot-required.pkgs

커널 취약점은 얼마나 나오나

리눅스 커널 프로젝트는 2024년 2월부터 스스로 CVE를 발급하는 기관(CNA)이 되었습니다. 그 뒤로 발급 건수가 크게 늘었고, 커널 유지보수자 Greg Kroah-Hartman은 커널 CNA가 1만 번째 CVE를 발급했다고 밝혔습니다. 그가 공개한 표에서 2024년에 고쳐진 버그의 CVE는 3,171건, 2025년은 2,533건입니다. (여기서 연도는 CVE를 발급한 해가 아니라 커널에서 버그를 고친 해입니다.)

이 숫자가 곧 「원격에서 서버를 장악할 수 있는 구멍 수천 개」라는 뜻은 아닙니다. 커널 팀은 보안 영향이 있을 수 있는 수정을 넓게 CVE로 등록하고, 그중 상당수는 특정 하드웨어나 설정에서만 의미가 있습니다. 하지만 로컬 권한 상승, 즉 서버 안에서 평범한 권한으로 무언가를 실행할 수 있는 공격자가 root가 되는 종류의 버그는 꾸준히 나옵니다.

이게 왜 중요하냐면, 요즘 공격은 대개 한 번에 root를 얻지 않기 때문입니다. 웹 앱 하나의 취약점이나 유출된 비밀번호로 낮은 권한을 먼저 얻고, 그다음에 커널 버그로 권한을 올립니다. 1년 전 커널은 그 두 번째 계단을 1년 치 열어 두고 있는 셈입니다.

AI가 바꾼 것: 패치가 곧 공격 설명서가 되는 시간

보안 패치는 늘 양날의 칼이었습니다. 패치를 보면 무엇이 고쳐졌는지 알 수 있고, 고쳐진 곳을 보면 고치기 전 버전을 어떻게 공격할지 짐작할 수 있습니다. 이렇게 패치에서 거꾸로 공격법을 찾는 것을 패치 디핑(patch diffing)이라고 부릅니다.

다만 예전에는 이 과정에 숙련된 사람의 시간이 들었습니다. 그래서 패치가 나오고 실제 공격이 퍼지기까지 보통 몇 주의 여유가 있었습니다. 2017년 WannaCry는 관련 패치(MS17-010)가 나오고 59일 뒤에 퍼졌습니다.

그 여유가 줄어들고 있습니다. Anthropic의 레드팀이 2026년 6월에 발표한 N-day 익스플로잇 연구는 이 질문을 직접 쟀습니다. 모델에게 패치가 나온 날 공격자가 구할 수 있는 것, 즉 패치 전후의 바이너리, 함수 단위 차이(diff), 공개된 보안 권고문만 주었습니다.

  • 2026년 1~2월에 나온 윈도우 커널 패치 21건에서, 가장 강한 모델은 낮은 권한 사용자를 시스템 최고 권한(SYSTEM)까지 끌어올리는 완전한 공격 사슬 8개를 만들었습니다.
  • 첫 번째 PoC(동작을 증명하는 코드)는 31분 만에 나왔습니다.
  • 공격 사슬 하나에 든 API 비용은 평균 약 2,000달러였습니다.
  • 마이크로소프트가 「악용 가능성 낮음」으로 분류한 14건 중 13건에서 PoC가 나왔습니다.

연구진의 결론은 이렇습니다. "한 사람이 한 달 치 패치를 오후 한나절 만에 동작하는 익스플로잇으로 바꿀 수 있다." 그리고 「패치 후 며칠(N-day)」이라는 말 자체가 위험할 만큼 낡았고, 이제는 「N-hour」가 현실에 더 가깝다고 썼습니다.

이 실험의 대상은 리눅스가 아니라 윈도우 커널이었고, 소스 코드 없이 바이너리만으로 해낸 결과입니다. 리눅스 커널은 수정이 소스 코드 그대로 공개됩니다. 공격자에게 주어지는 재료가 오히려 더 많다는 뜻입니다.

그래서 1년의 의미가 달라졌다

예전에는 커널을 몇 달 늦게 올려도, 그 사이에 실제로 쓸 수 있는 공격 코드가 나와 퍼지기까지 시간이 걸렸습니다. 늦게 패치하는 비용이 「운이 나쁘면」의 영역에 있었습니다.

이제는 패치가 공개되는 순간이 곧 공격 설명서가 공개되는 순간에 가깝습니다. 숙련된 사람이 몇 주 걸리던 일을 AI가 몇 시간, 몇 천 달러로 해냅니다. 공격에 필요한 것이 실력이 아니라 API 키와 약간의 돈이 되면, 공격자의 수는 늘고 공격 대상의 규모는 작아집니다. 작은 회사의 사내 서버도 굳이 피해 갈 이유가 없어집니다.

388일 동안 재부팅하지 않은 서버는 그런 공격 설명서를 1년 치 쌓아 두고 있었던 셈입니다.

무엇을 하면 되나

거창한 일은 아닙니다. 고객사 서버에서는 아래 세 가지로 정리했습니다.

1. 재부팅이 필요할 때만, 정해진 시간에 자동으로

Ubuntu의 자동 업데이트에는 재부팅 설정이 이미 있습니다. 커널처럼 재부팅이 필요한 업데이트가 설치됐을 때만, 사람이 적은 시간에 재부팅합니다.

# /etc/apt/apt.conf.d/52-auto-reboot
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:30";

시간은 서버의 로컬 시간 기준입니다. 서버 시간대가 UTC면 한국 시간 오후에 재부팅될 수 있으니 시간대부터 확인합니다(timedatectl).

2. 재부팅해도 저절로 돌아오게

자동 재부팅이 두려운 이유는 대개 「다시 안 뜨면 어떡하지」입니다. 그 두려움은 재부팅을 미루는 쪽이 아니라 다시 뜨게 만드는 쪽으로 푸는 것이 맞습니다.

  • 도커 컨테이너는 재시작 정책을 둡니다(restart: unless-stopped).
  • 사용자 단위로 띄운 서비스(systemd --user)는 로그아웃 상태에서도 돌도록 loginctl enable-linger를 켭니다.
  • 한 번은 사람이 지켜보는 가운데 직접 재부팅해 봅니다. 그때 안 뜨는 것이 있으면 새벽 4시 반이 아니라 지금 알게 됩니다.

3. 「재부팅 필요」를 보이는 곳에 두기

/var/run/reboot-required 파일이 며칠째 있는지를 모니터링이나 점검 목록에 넣습니다. 자동 재부팅을 켤 수 없는 서버라면 이것이 최소한의 안전장치입니다.

재부팅 없이 커널을 고치는 라이브 패치(Canonical Livepatch, kpatch 같은 것)도 있습니다. 다만 모든 수정이 라이브 패치로 나오지는 않고, 결국 어느 시점에는 재부팅해야 합니다. 재부팅을 대신하는 것이 아니라 그 간격을 늘려 주는 도구로 보는 편이 정확합니다.

확실하지 않은 부분

Anthropic의 실험은 윈도우 커널과 Firefox를 대상으로 했고, 가장 성능이 좋은 비공개 모델의 결과입니다. 공개된 모델은 그보다 적게 성공했다고 연구진도 밝혔습니다. 같은 결과가 리눅스 커널 패치에서 그대로 나온다고 단정할 수는 없습니다. 커널 CVE 수도 집계 기준(고친 해와 발급한 해)에 따라 달라집니다.

그래도 방향은 분명하다고 봅니다. 패치에서 공격까지의 거리가 짧아지고 있고, 그 거리를 줄이는 비용이 계속 내려가고 있습니다. 그렇다면 방어하는 쪽이 할 일도 하나입니다. 설치에서 적용까지의 거리를 줄이는 것. 커널에서 그 거리는 재부팅 한 번입니다.

이 게시글 공유하기

마지막 수정:

공유하실 때는 출처(Duolabs)와 원문 주소를 표시해 주세요.