본문으로 건너뛰기
피드

Lean이 '이 프로그램은 안전하다'고 증명했는데, 런타임에서 버그가 나왔다

security 약 6분

형식 검증 언어 Lean 4의 런타임에서 힙 버퍼 오버플로우가 발견됐다. lean_alloc_sarray 함수에서 정수 오버플로우가 발생해 156바이트짜리 조작된 ZIP 파일로 트리거 가능하며, lean-zip에서도 별도의 DoS 취약점이 확인됐다.

  • 1

    lean_alloc_sarray에서 capacity가 SIZE_MAX에 가까우면 24+n이 정수 오버플로우 → 23바이트만 할당하고 SIZE_MAX 바이트를 읽음

  • 2

    156바이트 조작 ZIP 파일(ZIP64 compressedSize=0xFFFFFFFFFFFFFFFF)로 트리거 가능

  • 3

    Lean 4 v4.31.0-nightly까지 모든 버전 영향

  • 4

    lean-zip의 readExact도 compressedSize 미검증으로 OOM DoS 가능

  • 형식 검증 언어 Lean 4의 런타임 C 코드에서 힙 버퍼 오버플로우가 발견됨
    • 아이러니하게도 Lean은 "이 프로그램이 정확하다"를 수학적으로 증명하는 언어인데, 정작 자기 런타임이 고전적인 C 버그를 갖고 있었음
  • 취약 함수: lean_alloc_sarray
    • ByteArray capacity n에 대해 할당 크기가 24 + n으로 계산됨
    • nSIZE_MAX(2^64 - 1)에 가까우면 24 + n이 정수 오버플로우로 랩어라운드 → 23바이트짜리 버퍼만 할당
    • 호출자는 그 버퍼에 SIZE_MAX 바이트를 읽어들임 → 힙 버퍼 오버플로우
  • 트리거 방법
    • 156바이트짜리 조작된 ZIP 파일 하나면 충분함
    • ZIP64 compressedSize0xFFFFFFFFFFFFFFFF로 세팅
    • IO.FS.Handle.read가 내부적으로 lean_io_prim_handle_readlean_alloc_sarray를 호출하면서 오버플로우 발생
  • 5줄짜리 최소 재현 코드가 공개됨
    def main : IO Unit := do
      IO.FS.writeFile "test.bin" "hello"
      let h ← IO.FS.Handle.mk "test.bin" .read
      let n : USize := (0 : USize) - (1 : USize) -- SIZE_MAX
      let _ ← h.read n -- lean_alloc_sarray에서 오버플로우
  • lean_io_get_random_bytes에서도 동일한 패턴 존재함
  • 영향 범위: Lean 4 전 버전, v4.31.0-nightly-2026-04-11까지
  • 수정 PR이 제출된 상태임

⚠️주의

> 이 버그는 Lean 언어로 작성된 사용자 코드의 문제가 아님. Lean의 런타임 자체(C로 작성된 메모리 할당 레이어)에서 발생하는 정수 오버플로우임. 형식 검증이 커버하는 순수 함수형 레이어와는 별개의 영역이라 증명으로 잡을 수 없었음.

  • lean-zip에서도 별도의 DoS 취약점 발견
    • readExact 함수가 ZIP 헤더의 compressedSize를 검증 없이 h.read에 그대로 전달함
    • 수 엑사바이트를 주장하는 ZIP 파일을 열면 OOM 패닉 발생
    • 시스템 unzip은 헤더 크기를 실제 파일 크기와 대조하는데, lean-zip은 안 함

기술 맥락

  • 왜 형식 검증 언어에서 이런 버그가 나올 수 있냐면, Lean 4의 증명이 커버하는 범위를 생각해 봐야 해요
    • Lean이 증명하는 건 순수 함수형 레이어에서의 정확성이에요. "이 함수는 이런 입력에 대해 이런 출력을 보장한다" 같은 명제를 수학적으로 증명하는 거죠
    • 그런데 실제 실행은 C로 작성된 런타임이 담당하거든요. lean_alloc_sarray 같은 메모리 할당 함수는 그 증명 범위 밖이에요
  • 정수 오버플로우의 메커니즘을 좀 더 자세히 보면요
    • 64비트 시스템에서 size_t는 최대 2^64 - 1까지 표현해요
    • sizeof(lean_sarray_object)가 24바이트이고, 여기에 capacity를 더하는데요
    • capacitySIZE_MAX(= 2^64 - 1)이면 24 + (2^64 - 1) = 23이 돼요 (모듈러 연산)
    • 결과적으로 23바이트만 malloc하고, fread에는 SIZE_MAX를 넘기는 거예요
  • ZIP64 포맷을 이용한 트리거가 영리한 게, ZIP64 확장 필드는 compressedSize를 64비트로 표현할 수 있어서 0xFFFFFFFFFFFFFFFF를 합법적인 ZIP 구조 안에 넣을 수 있거든요
    • 실제 파일은 156바이트밖에 안 되지만, 헤더가 "이 엔트리의 압축 크기는 18 엑사바이트"라고 주장하는 거예요
  • 이 사례가 보안 커뮤니티에서 주목받는 이유는, 형식 검증의 한계를 구체적으로 보여주기 때문이에요
    • 증명은 모델 안에서만 유효하고, 모델 바깥의 구현(FFI, 런타임, OS 인터페이스)은 별도로 검증해야 한다는 교훈이에요

형식 검증이 증명하는 건 '명세 안에서의 정확성'이지, 런타임 C 코드의 안전성까지 보장하지 않는다는 것을 보여주는 사례다.

댓글

댓글

댓글을 불러오는 중...

security

미국 하원, 기기 켤 때 '나이 인증' 의무화 법안 발의 — 애플·구글이 전국민 신원 검문소 되나

미국 하원의원 Josh Gottheimer가 발의한 H.R. 8250(Parents Decide Act)은 애플, 구글 등 모든 OS 벤더가 기기 설정 시 사용자 나이를 검증하도록 강제한다. 아동 보호를 명분으로 내걸었지만, 성인 예외가 없고 생체 스캔·ID 업로드 등의 인프라가 OS 레벨에 깔리게 되어 사실상 국가 신원 확인 시스템이 된다는 비판이 나온다.

security

5억 대 위치 추적 Webloc부터 Claude로 정부기관 9곳 턴 해커까지 — 이번 주 보안 뉴스

Citizen Lab이 폭로한 미국 애드테크 감시 시스템 Webloc은 전 세계 최대 5억 대의 모바일 기기 위치를 추적 가능하며 미 국토안보부·ICE·외국 정보기관이 고객이다. 같은 주 Gambit 보고서는 단독 해커가 Claude Code와 GPT-4.1로 몇 주 만에 멕시코 정부기관 9곳을 털고 수억 건의 기록을 탈취한 사례를 상세 분석했다. 핵심은 AI가 새로운 기법을 만든 게 아니라 1명이 소규모 팀 속도로 움직이게 만들었다는 점이다.

security

티오리, AI 보안 솔루션 '진트'로 중소기업 클라우드 바우처 공급기업 선정

사이버 보안 기업 티오리가 AI 해커 솔루션 '진트'로 정부 클라우드 바우처 사업 공급기업에 선정됨. 중소기업 60곳에 기업당 최대 6,910만원 지원, 기존 2주 보안 분석을 12시간으로 단축하는 AI 기반 취약점 탐지 제공.

security

이더리움 재단, 웹3에 위장 취업한 북한 IT 인력 100명 적발 — 깃허브 탐지 도구 공개

이더리움 재단의 '켓맨' 프로젝트가 6개월간 웹3 프로젝트에 침투한 북한 IT 인력 100명을 식별하고, 53개 프로젝트에 경고를 발송함. 깃허브 활동 패턴 분석 기반 오픈소스 탐지 도구도 공개.

security

SW 공급망 보안 로드맵 임박 — 2027년 공공 SBOM 제출 의무화 추진

정부가 SW 공급망 보안 강화 로드맵을 이달 말~내달 초 공개 예정. 개발 중 SW의 90%가 오픈소스를 사용하는 가운데, 매년 공급망 공격이 50%+ 증가하는 상황에서 2027년까지 공공 IT 시스템 SBOM 제출 제도화를 추진함.