← 개발 기록

Fragnesia CVE-2026-46300 대응: Linux 커널 패치와 실행 반영 확인

이 글의 목차

Fragnesia(CVE-2026-46300)는 Linux 커널의 로컬 권한 상승 취약점입니다. 대응의 핵심은 배포판·커널 계열에 맞는 수정 패키지를 적용하고, 실제 실행 중인 커널에 수정이 반영됐는지 확인하는 것입니다. Ubuntu의 공식 설명은 조건에 따라 컨테이너 탈출 가능성도 언급합니다. Linux를 사용한다는 이유만으로 모든 시스템이 같은 영향을 받는 것은 아닙니다.

인터넷에서 바로 root가 되는 취약점인가요?

이 CVE 자체는 로컬 권한 상승입니다. 공격자가 서버에서 코드를 실행할 수 있는 상태와 커널 취약 경로에 도달하는 조건이 필요합니다. 웹 애플리케이션의 원격 코드 실행과 구분해야 합니다. CISA KEV 공식 데이터는 PHP2Shell의 CVE-2026-109618·109619와 연결될 수 있는 위험을 기록합니다. 따라서 PHP 런타임 패치와 호스트 커널 패치는 각각 확인해야 합니다.

CVE 원본 기록에 따르면 문제는 소켓 버퍼 병합 중 공유된 페이지 조각의 표시가 보존되지 않는 데 있습니다. 이후 ESP 처리가 공유 페이지를 전용 페이지로 잘못 취급해 제자리에서 수정할 수 있습니다. 공개 날짜는 2026년 5월 23일이고, CISA KEV 등재일은 10월 28일입니다. 10월에 새로 생긴 결함으로 읽지 않습니다. KEV의 10월 31일 기한은 해당 지침의 적용 범위와 함께 해석해야 하며 모든 서비스의 공통 변경 일정으로 적용하지 않습니다.

어떤 커널을 업데이트해야 하나요?

Fragnesia의 수정 범위를 CVE 하나만 보고 좁히지 않습니다. Ubuntu의 보안팀 메모는 CVE-2026-43284 수정과 함께 관련 수정들을 반영하도록 안내하며, 다른 조각 전달 경로의 수정은 CVE-2026-43503으로도 추적합니다. CVE-2026-43284는 Dirty Frag 계열의 별도 항목입니다. 공급자의 전체 수정 패키지를 우선하고 특정 커밋 하나만 골라 적용한 상태를 완료로 취급하지 않습니다.

다음은 2026년 10월 31일 확인한 Ubuntu의 linux 소스 패키지 수정 기준 일부입니다. 설치된 바이너리 패키지와 소스 패키지·커널 계열의 대응을 먼저 확인해야 합니다.

Ubuntu 릴리스 linux 수정 기준
22.04 LTS 5.15.0-181.191
24.04 LTS 6.8.0-124.124
26.04 LTS 7.0.0-22.22

이 표를 AWS·Azure·HWE·OEM·실시간 커널에 그대로 적용하지 않습니다. 패키지 이름·지원 계열·공급자 백포트가 다르기 때문입니다. RHEL은 Red Hat 공지의 제품별 상태와 RHSA를 따릅니다. AWS도 자체 공지에서 Amazon Linux와 Bottlerocket의 espintcp 구성에 따른 비영향 상태를 설명합니다. 이를 임의 커스텀 커널이나 EC2에서 실행하는 다른 배포판까지 확대하지 않습니다.

실행 중인 커널의 증거부터 수집하기

Linux 여부 확인 후 실행 커널과 운영체제 정보를 읽고 dpkg-query 유무에 따라 패키지 조회를 수행하며 오류를 구분한 뒤 패치 미판정 상태로 증거를 출력하는 흐름

그림은 아래 수집기의 흐름입니다. Python 3.10 이상이 필요하며, dpkg-query가 있는 Linux에서 현재 실행 커널 이름에 대응하는 두 패키지 이름만 조회합니다. 네트워크·관리자 권한·모듈 로드·시스템 변경은 사용하지 않습니다. 취약점 탐지기나 패치 완료 판정기가 아닙니다. 조회 정보가 없어도 안전하다고 출력하지 않습니다.

kernel-evidence.py

import json
import platform
import shutil
import subprocess


def collect():
    result = {"patch_status": "not-assessed", "scope": "current-execution-context"}
    if platform.system() != "Linux":
        return {**result, "error": "linux-required"}, 2
    try:
        release = platform.release()
        distro = platform.freedesktop_os_release()
    except OSError:
        return {**result, "error": "os-evidence-unavailable"}, 2
    result.update(running_kernel=release,
                  os={key: distro.get(key) for key in ("ID", "VERSION_ID")}, queries=[])
    command = shutil.which("dpkg-query")
    if not command:
        return {**result, "package_query": "dpkg-query-unavailable"}, 0
    result["package_query"] = "dpkg-query"
    for name in ("linux-image-" + release, "linux-image-unsigned-" + release):
        row = {"package": name}
        try:
            answer = subprocess.run(
                [command, "-W", "-f=${Package}\t${Version}\t${db:Status-Status}\n", name],
                capture_output=True, text=True, timeout=5, check=False)
        except (OSError, subprocess.TimeoutExpired):
            row["state"] = "query-error"
        else:
            fields = answer.stdout.rstrip("\n").split("\t")
            if answer.returncode == 1:
                row["state"] = "not-found"
            elif answer.returncode != 0:
                row["state"] = "query-error"
            elif len(fields) != 3 or fields[0] != name or not fields[1]:
                row["state"] = "unexpected-output"
            elif fields[2] != "installed":
                row["state"] = "not-installed"
            else:
                row.update(state="installed", version=fields[1])
        result["queries"].append(row)
    return result, 0


if __name__ == "__main__":
    evidence, status = collect()
    print(json.dumps(evidence, ensure_ascii=False, indent=2, sort_keys=True))
    raise SystemExit(status)
python3 kernel-evidence.py

Linux 외 환경이나 OS 증거를 읽을 수 없는 경우 종료 코드 2를 반환합니다. Linux에서 수집을 마쳤더라도 개별 패키지 조회는 실패할 수 있으므로 package_query와 각 state를 읽어야 합니다. 종료 코드 0은 패치 완료를 뜻하지 않습니다. RPM·커스텀 커널은 이 두 패키지 조회만으로 소유 패키지를 찾을 수 없습니다.

다음은 Ubuntu 24.04·실행 커널 6.8.0-124-generic·첫 패키지 설치·두 번째 패키지 없음이라는 합성 입력으로 실행해 확인한 출력입니다. 실제 Ubuntu 운영 호스트에서 수집한 값이 아닙니다. 실행 검사는 이 출력과 조회 실패 분기를 재현하며, 실제 커널 취약성·패치 적용·공격 성공을 시험하지 않습니다.

{
  "os": {
    "ID": "ubuntu",
    "VERSION_ID": "24.04"
  },
  "package_query": "dpkg-query",
  "patch_status": "not-assessed",
  "queries": [
    {
      "package": "linux-image-6.8.0-124-generic",
      "state": "installed",
      "version": "6.8.0-124.124"
    },
    {
      "package": "linux-image-unsigned-6.8.0-124-generic",
      "state": "not-found"
    }
  ],
  "running_kernel": "6.8.0-124-generic",
  "scope": "current-execution-context"
}

컨테이너에서 실행하면 OS·패키지 DB는 컨테이너의 것이고 커널은 공유 호스트의 것일 수 있습니다. 호스트나 VM의 관리 경로에서 다시 수집하세요. 설치한 새 커널 패키지와 지금 실행 중인 커널도 다를 수 있습니다. 이 수집기는 현재 릴리스와 연결한 이름만 조회하며 설치된 모든 커널을 나열하지 않습니다. 패키지 서명·무결성·라이브패치 상태도 확인하지 않습니다.

패치 후 무엇을 확인하나요?

  1. 자산의 배포판·실행 커널·패키지 계열을 공급자 CVE/보안 공지와 연결합니다. 단순 문자열 비교로 서로 다른 계열의 버전을 비교하지 않습니다.
  2. 지원되는 저장소·이미지로 수정 패키지를 적용하고 노드를 순차적으로 교체하거나 재부팅합니다. Ubuntu USN-8388-1은 표준 업데이트 후 재부팅과 제3자 커널 모듈의 ABI 대응을 안내합니다. 라이브패치만 사용할 경우에는 해당 CVE·실행 커널의 지원 및 실제 적용 상태를 별도로 확인합니다.
  3. 재시작 후 같은 증거를 다시 수집해 실제 실행 커널과 공급자의 수정 근거를 대조하고, 서비스 상태·스토리지·네트워크 동작을 확인합니다. Kubernetes에서는 파드 재시작만으로 노드 커널이 교체되지 않습니다.
  4. 초기 침입 가능성과 지속성도 조사합니다. 패치 성공은 이미 설치된 웹셸이나 자격 증명 유출이 없다는 증거가 아닙니다.

즉시 업데이트할 수 없다면 Ubuntu의 임시 완화 안내와 자사 공급자 지침을 확인합니다. 커널 모듈 제한은 VPN/IPsec 등 사용 기능과 충돌할 수 있고, 이미 로드되거나 내장된 경로는 별도 판단이 필요합니다. 모듈 목록에 보이지 않는다는 이유만으로 비영향 판정을 내리지 마세요. 노출 축소·비신뢰 코드 실행 제한은 임시 대응이며 수정 패키지 반영을 대신하지 않습니다.

댓글