ABC 미래내일 프로젝트

[2026 ABC 프로젝트 멘토링 3기] 프로젝트 1주차

mysticprayer 2026. 4. 6. 13:21

[미래내일 일경험] 테크노트 - 1주차

사전 조사 및 기술 스택 선정 | 2026.04.01 ~ 04.05

프로젝트명 AI 기반 퍼징을 활용한 취약점 탐지 및 검증 자동화 시스템
팀명 The First 작성자 이우곤
담당 역할 하네스 개발, 퍼징 파이프라인 구축, 포맷 연동 구현

📌 1. 금주 학습 목표

  • 퍼징(Fuzzing)의 개념과 원리 이해
  • AI 모델 파일(GGUF, ONNX) 대상 퍼징의 필요성 조사
  • 하네스 개발 및 퍼징 파이프라인 구축을 위한 기술 스택 조사 및 선정
  • 프로젝트 개발 환경 구성 및 팀 협업 체계 수립

📖 2. 학습 및 조사 내용

2-1. 퍼징(Fuzzing)이란?

퍼징(Fuzzing)이란 소프트웨어의 입력값에 무작위 또는 변형된 데이터를 대량으로 주입하여 프로그램의 예기치 않은 동작(크래시, 메모리 오류 등)을 유발하는 자동화된 보안 테스팅 기법이다. 1988년 위스콘신대학교 Barton Miller 교수의 연구에서 유래하였으며, 현재는 구글, 마이크로소프트 등 주요 기업에서 소프트웨어 품질 보증의 핵심 도구로 활용되고 있다.

퍼징은 크게 세 가지 유형으로 분류된다.

① 블랙박스 퍼징 (Black-box Fuzzing)
프로그램의 내부 구조를 모른 채 무작위 입력을 생성하는 방식. 구현이 간단하지만 코드 커버리지가 낮다.

② 화이트박스 퍼징 (White-box Fuzzing)
소스코드 분석 및 심볼릭 실행을 통해 입력을 생성. 정밀하지만 비용이 높다.

③ 그레이박스 퍼징 (Grey-box Fuzzing)
코드 커버리지 피드백을 활용해 입력을 진화시키는 방식. 효율성과 정밀성의 균형을 갖추며,

본 프로젝트에서 채택하는 방식이다.

퍼징의 핵심 구성요소는 다음과 같다.

  • 시드 코퍼스(Seed Corpus) — 초기 입력 데이터 집합
  • 뮤테이터(Mutator) — 입력을 변형하는 엔진
  • 하네스(Harness) — 타깃 프로그램을 퍼저에 연결하는 래퍼 코드
  • 크래시 트리아지(Crash Triage) — 발견된 크래시를 분류하고 중복을 제거하는 과정

2-2. AI 모델 대상 퍼징의 필요성

최근 대규모 언어 모델(LLM)의 확산으로 GGUF, ONNX, SafeTensors 등 AI 모델 파일 포맷의 사용이 급증하고 있다. 이러한 파일들은 복잡한 바이너리 구조를 가지며, 파서(Parser) 단계에서의 메모리 안전성 문제가 심각한 보안 위협으로 대두되고 있다.

⚠️ AI 모델 파일 퍼징이 필요한 이유

  • 파서 취약점의 위험성: llama.cpp, onnxruntime 등 주요 추론 엔진이 C/C++로 작성되어 있어 버퍼 오버플로우, Use-After-Free 등 메모리 커럽션 취약점에 노출됨
  • 공급망 공격 가능성: 악의적으로 조작된 모델 파일이 Hugging Face 등 모델 허브를 통해 유포될 경우, 이를 로드하는 시스템에서 원격 코드 실행(RCE)이 발생할 수 있음
  • 기존 도구의 한계: 현재 공개된 퍼저들은 단순 크래시 탐지에 그치며, 실제 악용 가능한 취약점인지 검증하는 기능이 부재
  • 구조 인식의 필요: AI 모델 파일은 텐서 데이터, 메타데이터, 정렬 패딩 등 복잡한 구조를 가지므로 단순 바이트 뮤테이션으로는 파서 깊숙한 로직까지 도달하기 어려움

2-3. 하네스 개발 기술 조사

하네스(Harness)는 퍼징 대상 프로그램의 특정 함수를 직접 호출하여 퍼저와 연결하는 역할을 한다. 본 프로젝트에서는 llama.cpp와 onnxruntime의 모델 로딩 함수를 대상으로 하네스를 작성할 계획이다.

  • LibFuzzer 하네스 구조: LLVMFuzzerTestOneInput 함수를 진입점으로 사용하며, 퍼저가 생성한 데이터를 타깃 함수에 전달한다.
  • ASan(AddressSanitizer) 연동: 컴파일 시 -fsanitize=address 플래그를 적용하여 힙 버퍼 오버플로우, 스택 버퍼 오버플로우, Use-After-Free, 이중 해제 등 메모리 오류를 정밀하게 탐지한다.
  • FFI(Foreign Function Interface) 연동: Rust에서 C/C++ 함수를 호출하기 위해 extern "C" 블록과 bindgen 크레이트를 활용하며, Rust 기반 플랫폼 코어에서 C/C++ 하네스를 제어한다.

2-4. 퍼징 파이프라인 아키텍처 조사

퍼징 파이프라인은 시드 입력 생성부터 크래시 분석까지의 전체 워크플로우를 의미한다. 본 프로젝트에서 구축할 파이프라인의 주요 단계는 다음과 같다.

1️⃣ 시드 수집 → 공개 GGUF/ONNX 모델에서 최소 유효 시드를 추출하고 포맷별 시드 코퍼스 구성

2️⃣ 뮤테이션 → 구조 인식 뮤테이터가 헤더, 텐서 메타데이터, 정렬 패딩 등을 인식하여 유효한 변형 생성

3️⃣ 실행 및 모니터링 → LibFuzzer 기반 커버리지 피드백 수집 + ASan을 통한 메모리 오류 실시간 감지

4️⃣ 크래시 수집 → 스택 트레이스 기반 자동 분류(디듀플리케이션), 고유 크래시만 저장

5️⃣ 검증 → 격리된 Docker 컨테이너에서 3회 반복 재현 수행, 안정 재현 크래시만 유효 취약점으로 확정

2-5. 기술 스택 선정 결과

1주차 조사를 바탕으로 다음과 같이 기술 스택을 선정하였다.

분류 기술 선정 사유
코어 언어 Rust 메모리 안전성 보장으로 플랫폼 자체의 안정성 확보, 고성능 비동기 처리(tokio)로 다수의 퍼징 Job 효율적 스케줄링
하네스 언어 C/C++ llama.cpp, onnxruntime 등 타깃 바이너리가 C/C++로 작성되어 네이티브 호출 필수, LibFuzzer와 직접 연동 용이
퍼징 엔진 LibFuzzer LLVM 기반 커버리지 유도 퍼저, 인프로세스 실행으로 속도가 빠르고 ASan과 통합이 매끄러움
메모리 탐지 ASan 컴파일 타임 계측으로 힙/스택 오버플로우, UAF 등 메모리 커럽션 정밀 탐지
스크립팅 Python 리포트 생성, 크래시 로그 파싱, 시드 관리 등 보조 스크립트 작성
컨테이너 Docker 격리 환경에서 크래시 재현의 일관성 보장, 호스트 시스템 보호 및 이식성 확보
형상 관리 Git / GitHub 팀 협업, 코드 리뷰, 이슈 트래킹 및 CI/CD 파이프라인 기반
빌드 도구 Cargo / CMake Rust는 Cargo, C/C++ 하네스는 CMake로 관리, FFI 연동 시 build.rs로 통합 빌드

🛠️ 3. 수행 활동

3-1. 개인 학습 및 조사 활동

  • 퍼징 관련 자료 학습: 구글 OSS-Fuzz 프로젝트 문서, LLVM LibFuzzer 공식 문서, 「The Fuzzing Book」 온라인 교재를 통해 퍼징의 이론적 기반을 학습
  • AI 모델 파일 포맷 분석: GGUF 포맷 명세(llama.cpp 공식 문서)와 ONNX 공식 스펙을 읽고, 각 포맷의 헤더 구조, 텐서 배치 방식, 메타데이터 영역을 파악
  • 기존 퍼징 사례 조사: llama.cpp에 대한 기존 퍼징 하네스(fuzzer 디렉토리)를 분석하여 하네스 구조와 퍼징 진입점 설계 방식을 파악
  • Rust-C FFI 연동 방식 조사: bindgen 크레이트를 활용한 C 헤더 자동 바인딩 생성 방법과, Rust에서 unsafe 블록을 통해 C 함수를 호출하는 패턴을 학습

3-2. 팀 활동

  • 킥오프 미팅 참석 (04.02): 프로젝트 목표, 일정, 역할 분담을 확정하고 팀 규칙(코드 컨벤션, 커밋 메시지 규칙 등)을 수립
  • 온라인 정기 미팅 참석 (04.05, Discord): 각자 1주차 조사 내용을 공유하고, 기술 스택 선정에 대한 논의를 진행
  • 협업 환경 구축: GitHub 레포지토리 생성, Notion 프로젝트 페이지 구성, Discord 채널 설정 완료
  • 개발 환경 통일: 팀원 전원 Ubuntu 24.04 LTS, Rust 1.77+, Clang 17+ 기반으로 통일 합의

📋 4. 다음 주 계획 (2주차)

  • 시스템 아키텍처 설계서 작성 (전체 모듈 구조도, 데이터 흐름도)
  • GGUF 포맷 대상 최초 퍼징 하네스 프로토타입 작성 (C/C++)
  • LibFuzzer 기반 퍼징 실행 환경 구축 및 시드 코퍼스 수집
  • Rust 프로젝트 스캐폴딩 및 Cargo workspace 구성
  • FFI 연동 테스트 (Rust에서 C 하네스 호출 검증)

💬 5. 느낀점 및 회고

프로젝트 1주차에는 퍼징의 기본 개념부터 AI 모델 파일 포맷의 구조, 그리고 실제 개발에 사용할 기술 스택까지 폭넓게 조사를 진행하였다. 퍼징이라는 기법 자체는 이전에 개념적으로만 알고 있었으나, 실제로 LibFuzzer의 동작 방식과 하네스 구조를 상세히 살펴보니 단순히 랜덤 데이터를 넣는 것이 아니라 커버리지 피드백 기반의 정교한 메커니즘이라는 점을 새롭게 이해하게 되었다.

특히 AI 모델 파일을 퍼징 대상으로 삼는다는 점이 흥미로웠다. GGUF나 ONNX 파일의 구조를 분석하면서, 복잡한 바이너리 포맷의 파서가 얼마나 많은 잠재적 취약점을 가질 수 있는지 실감하게 되었다. 단순 바이트 뮤테이션으로는 파서의 깊은 로직에 도달하기 어렵다는 점에서 구조 인식 뮤테이터의 필요성을 체감하였다.

Rust와 C/C++를 함께 사용하는 기술 스택 구성이 다소 복잡할 수 있지만, 플랫폼의 안정성(Rust)과 타깃 호환성(C/C++)을 모두 확보할 수 있다는 점에서 합리적인 선택이라고 판단하였다. 다음 주부터 본격적인 하네스 개발에 착수할 예정이며, 실제 코드를 작성하면서 이론과 실무 사이의 간극을 좁혀 나가고자 한다.

📚 6. 참고 자료