FlawOpen

flawopen.com/Teardowns/cve-2025-39682-linux-ktls-zero-length-record-mishandling

● CVE-2025-39682 · CVSS 9.8 · 심각
보안 연구 · FlawOpen

Linux CVE-2025-39682: kTLS 제로 길이 레코드 처리 결함

Linux kTLS 수신 대기열의 길이 0인 non-DATA TLS 레코드가 recvmsg별 레코드 유형 검사를 우회할 수 있었다. 수정은 복사된 바이트가 0이어도 처리된 레코드 유형을 확인한다. Linux CVSS 평가에는 커널 힙 정보의 사용자 공간 노출, 메모리 손상, 원격 커널 충돌 가능성이 기재되어 있다. 이는 평가된 영향이며 모든 취약 시스템에서 각각 발생한다는 뜻은 아니다.

CVSS 벡터CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
💡 알기 쉬운 설명 (ELI5)

각 칸에는 한 종류의 편지만 넣을 수 있는 우편 분류대를 떠올려 보자. 빈 봉투에도 종류가 있지만, 이전 분류기는 편지 개수를 세어 칸을 바꿀지 결정했다. 편지가 0개면 봉투의 종류를 무시하고 다음 유형까지 같은 칸에 섞었다. 커널 수정은 봉투에 데이터가 없어도 종류 표식을 확인한다.

핵심 개념 및 용어

kTLS
커널 TLS: Linux가 연결된 TCP 소켓의 TLS 레코드를 커널에서 처리할 수 있다.
recvmsg()
애플리케이션과 kTLS 수신 경로가 사용하는 소켓 수신 시스템 호출.
TLS content type
애플리케이션 데이터나 제어 레코드 등 레코드 유형을 분류하는 필드.
rx_list
후속 recvmsg 호출에서 처리되는 대기 중 수신 레코드 큐.
CWE-754
비정상 또는 예외 조건에 대한 부적절한 검사. NVD는 CWE-754를 CISA-ADP 출처로 표시하며 Linux CVE 레코드 자체는 CWE를 지정하지 않는다.

프레임워크 매핑

근본 원인 분석 (Root Cause)

Linux kTLS 수신 처리는 한 번의 recvmsg() 호출에서 연속된 DATA 레코드 또는 단 하나의 non-DATA 레코드만 반환해야 한다. process_rx_list()가 처음에 길이 0인 non-DATA 레코드를 처리하면 TLS 유형을 설정하면서 err == 0을 반환할 수 있었다. tls_sw_recvmsg()는 이 0을 copied에 저장하고 중지 조건의 일부로 (copied && control != TLS_RECORD_TYPE_DATA)를 사용했다. copied가 0이므로 이미 처리된 레코드 유형 검사가 생략되고 다음 데이터 처리가 계속됐다. upstream 수정은 control을 직접 확인한다. 유형이 보고되었고 DATA가 아니면 중지하며, 0은 “아직 유형이 보고되지 않음”을 뜻한다. Linux 커널 TLS 수신 경로(kTLS)가 활성화되어 사용되는 경우에만 해당하며 모든 userspace TLS 라이브러리 파서의 결함은 아니다. Linux가 공개한 CVSS 3.1 벡터는 9.8 Critical (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)이다. 실제 kTLS 사용 여부와 공급업체 커널 상태로 노출을 판단한다.

단계별 공격 실행 흐름

단계 1

kTLS가 레코드를 받는다

애플리케이션은 커널 TLS 수신이 활성화된 TCP 소켓을 사용한다.

단계 2

대기열의 길이 0 non-DATA 레코드가 처리된다

rx_list 첫 레코드에 payload가 없을 때 발생한다. 처리는 유형을 보고하면서 복사 바이트 수 0을 반환할 수 있다.

단계 3

이전 조건은 복사 바이트 수에 의존했다

copied가 0이면 처리된 유형이 non-DATA인지 확인하지 않았다.

단계 4

수신 루프가 유형 경계를 넘는다

다음 데이터가 같은 recvmsg 호출에서 처리되어 단일 유형 규칙을 위반할 수 있다. Linux CVSS 평가에는 커널 힙 정보의 사용자 공간 노출, 메모리 손상, 원격 커널 충돌 가능성이 기재되어 있다. 이는 평가된 영향이며 모든 취약 시스템에서 각각 발생한다는 뜻은 아니다.

단계 5

수정은 의미 표식을 검사한다

새 조건은 복사 바이트 수와 관계없이 control이 설정된 non-DATA 유형을 나타내면 중지한다.

소스 코드 비교: 취약한 구현 vs 보안 패치

net/tls/tls_sw.c의 일부 코드이며 전체 함수는 아니다. upstream 수정은 복사한 바이트 수 대신 보고된 콘텐츠 유형 표식을 중지 조건에서 확인한다. control == 0은 유형이 보고되지 않았다는 뜻이며, 설정된 non-DATA 유형이면 해당 recvmsg 호출을 중단한다. upstream 패치의 정확한 논리 변경이다.

소스 코드 발췌: 소스 코드: net/tls/tls_sw.c

취약한 구현
copied = err;
if (len <= copied ||
    (copied && control != TLS_RECORD_TYPE_DATA) || rx_more)
    goto end;
보안 강화 패치
copied = err;
if (len <= copied || rx_more ||
    (control && control != TLS_RECORD_TYPE_DATA))
    goto end;

엔지니어링 및 시스템 보안 강화 체크리스트

출처