ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OSS-fuzz 구동 과정에서 적용 예시
    IT/Open-Source 2024. 2. 21. 05:25

    OSS-Fuzz는 Google에서 개발한 오픈 소스 소프트웨어를 위한 지속적인 퍼징(fuzzing) 서비스입니다. 퍼징은 소프트웨어의 보안 취약점이나 버그를 찾기 위해 임의의 데이터를 자동으로 생성하여 프로그램에 입력하는 기법입니다. OSS-Fuzz는 특히 C/C++과 같은 메모리 안전성이 보장되지 않는 언어로 작성된 오픈 소스 프로젝트를 대상으로 합니다.

    OSS-Fuzz 구동 과정과 적용 예시

    OSS-Fuzz 구동 과정에서 적용되는 예시는 다음과 같습니다:

    • 프로젝트 통합
      • 오픈 소스 프로젝트가 OSS-Fuzz에 통합되기 위해서는 프로젝트 소스 코드에 퍼징 대상이 될 함수들을 정의해야 합니다. 이 함수들은 보통 '퍼징 타겟'이라고 불리며, 퍼저(fuzzer)가 생성한 입력 데이터를 처리합니다.
    • 퍼즈 타겟 작성
      • 퍼즈 타겟은 프로젝트의 API를 호출하고,
      • 퍼저가 생성한 임의의 입력 데이터를 이 API에 전달하는 간단한 프로그램입니다.
      • 이 타겟은 프로그램의 버그를 드러낼 수 있는 코드 경로를 실행해야 합니다.
    • 자동화된 퍼징
      • OSS-Fuzz는 통합된 프로젝트에 대해 지속적으로 퍼징을 수행합니다.
      • 퍼저는 임의의 입력 데이터를 생성하고, 이를 퍼즈 타겟에 전달하여 프로그램의 반응을 관찰합니다.
      • 이 과정에서 발생하는 모든 예외, 충돌, 메모리 누수 등은 자동으로 기록됩니다.
    • 결과 분석 및 버그 보고
      • 퍼징 중에 발견된 문제점은 OSS-Fuzz 시스템에 의해 자동으로 분석되고,
      • 관련 정보와 함께 버그 트래커에 기록됩니다.
      • 이 정보에는 충돌을 재현할 수 있는 입력 데이터, 스택 트레이스, 메모리 덤프 등이 포함될 수 있습니다.
    • 개발자 피드백
      • 프로젝트 개발자는 OSS-Fuzz로부터 버그 보고를 받고,
      • 이를 바탕으로 코드를 수정하여 보안 취약점이나 버그를 해결합니다.
      • 수정 사항이 프로젝트의 메인 리포지토리에 반영되면, OSS-Fuzz는 변경 사항을 자동으로 감지하고
      • 다시 퍼징을 수행하여 수정이 문제를 해결했는지 확인합니다.

    OSS-Fuzz는 특히 보안 관련 취약점을 찾는데 매우 효과적이며, 많은 오픈 소스 프로젝트들이 이를 통해 소프트웨어의 안정성과 보안성을 향상시켰습니다.

    예를 들어, OpenSSL, systemd, Chrome 등 많은 유명한 프로젝트들이 OSS-Fuzz를 사용하여 버그를 찾고 수정했습니다.

     

    활용 코드

    OSS-Fuzz를 활용하는 과정에서의 예시 코드는 다음과 같습니다. 여기서는 간단한 C++ 프로그램을 대상으로 한 퍼즈 타겟의 작성 방법을 설명하겠습니다. 이 예시에서는 가상의 문자열 파싱 함수를 퍼징 대상으로 가정합니다.

     

    프로젝트 코드 예시

    가정: 우리가 퍼징할 대상은 ParseMyData라는 함수이며, 이 함수는 문자열을 입력받아 어떤 처리를 수행합니다.

    // parse_my_data.cpp
    #include <string>
    #include <iostream>
    
    
    void ParseMyData(const std::string &data) {
        // 가정: 여기서 문자열 'data'를 파싱하는 복잡한 로직이 수행됩니다.
        // 예를 들어, 특정 패턴을 찾거나, 변환을 수행합니다.
        // 여기서는 단순화를 위해 입력된 데이터의 길이를 출력합니다.
        std::cout << "Processing data of length: " << data.length() << std::endl;
    }

    퍼즈 타겟 작성

    ParseMyData 함수를 테스트하기 위한 퍼즈 타겟을 작성합니다. 이 코드는 OSS-Fuzz에 의해 자동으로 호출되며, 퍼저가 생성한 임의의 입력 데이터로 ParseMyData 함수를 실행합니다.

    // fuzz_parse_my_data.cpp
    #include <stdint.h>
    #include <stddef.h>
    #include <string>
    
    
    extern "C" void ParseMyData(const std::string&);
    
    
    // 퍼즈 타겟 함수
    extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
        // 퍼저가 생성한 데이터를 std::string으로 변환합니다.
        std::string str_data(reinterpret_cast<const char*>(data), size);
    
    
        // 변환된 데이터로 'ParseMyData' 함수를 호출합니다.
        ParseMyData(str_data);
    
    
        // 정상 종료를 나타내는 0을 반환합니다.
        return 0;
    }

    이 코드에서 LLVMFuzzerTestOneInput 함수는 퍼즈 타겟의 진입점입니다. OSS-Fuzz는 이 함수에 임의의 바이트 배열(data)과 그 크기(size)를 전달합니다. 이 데이터는 std::string으로 변환되어 ParseMyData 함수에 전달됩니다. 이 과정에서 발생할 수 있는 모든 예외, 충돌, 메모리 누수 등을 OSS-Fuzz가 자동으로 감지하고 기록합니다.

     

    빌드 파일 작성

    OSS-Fuzz 통합을 위해서는 프로젝트에 퍼즈 타겟을 빌드하기 위한 빌드 파일(Dockerfile 및 build.sh)이 필요합니다. 이 파일들은 OSS-Fuzz가 퍼즈 타겟을 컴파일하고 실행하는 방법을 정의합니다.

    이러한 단계를 거쳐 프로젝트를 OSS-Fuzz에 통합하면, OSS-Fuzz는 지속적으로 퍼즈 타겟을 실행하면서 새로운 입력 데이터를 생성하고, 발견된 버그를 자동으로 추적합니다. 개발자는 OSS-Fuzz로부터의 피드백을 바탕으로 코드를 개선할 수 있습니다.

     

    프로젝트를 OSS-Fuzz에 통합하기 위해 필요한 Dockerfile과 build.sh 예시

    Dockerfile 작성

    Dockerfile은 OSS-Fuzz가 퍼즈 타겟을 빌드할 환경을 설정합니다. 아래는 간단한 예시입니다:

    # 기본 OSS-Fuzz 기반 이미지를 사용
    FROM gcr.io/oss-fuzz-base/base-builder
    
    
    # 필요한 의존성 설치
    RUN apt-get update && apt-get install -y make autoconf automake libtool
    
    
    # 프로젝트 소스 코드 복사
    COPY . $SRC/<프로젝트_이름>
    
    
    # 작업 디렉토리 설정
    WORKDIR $SRC/<프로젝트_이름>
    
    
    # 퍼즈 타겟 빌드를 위한 환경 변수 등 설정 가능
    
    
    # OSS-Fuzz가 프로젝트를 빌드할 때 실행할 빌드 스크립트 경로 지정
    CMD ["./build.sh"]

    이 Dockerfile은 OSS-Fuzz의 빌드 인프라에서 사용됩니다. 여기서 $SRC는 소스 코드가 위치하는 디렉토리를 나타내며, <프로젝트_이름>은 실제 프로젝트 이름으로 대체해야 합니다.

     

    build.sh 작성

    build.sh 스크립트는 퍼즈 타겟을 실제로 빌드하는 명령을 포함합니다. 아래는 간단한 예시입니다:

    #!/bin/bash -eu
    
    
    # 프로젝트 빌드 도구를 사용하여 프로젝트 빌드 (예: make, cmake 등)
    # make, cmake 등 프로젝트에 맞는 빌드 명령을 사용
    make -j$(nproc)
    
    
    # 퍼즈 타겟을 $OUT 디렉토리에 복사
    # $OUT은 OSS-Fuzz가 퍼즈 타겟 실행 파일을 기대하는 위치
    cp $SRC/<프로젝트_이름>/fuzz_parse_my_data $OUT/

    이 스크립트는 OSS-Fuzz가 퍼즈 타겟을 빌드할 때 실행됩니다. $SRC는 소스 코드가 위치하는 디렉토리, $OUT은 빌드된 실행 파일을 출력할 디렉토리를 나타냅니다. <프로젝트_이름>과 fuzz_parse_my_data는 각각 실제 프로젝트 이름과 퍼즈 타겟 실행 파일 이름으로 대체해야 합니다.

     

    이러한 파일들을 프로젝트에 추가하고 OSS-Fuzz에 통합 요청을 하면, OSS-Fuzz는 제공된 Dockerfile과 build.sh를 사용하여 퍼즈 타겟을 빌드하고 실행합니다. 이후 OSS-Fuzz는 지속적으로 퍼즈 타겟을 실행하며 새로운 버그를 자동으로 탐지하고, 발견된 버그에 대한 상세 정보를 프로젝트 개발자에게 제공합니다. 이를 통해 개발자는 소프트웨어의 안정성과 보안을 향상시킬 수 있습니다.

     

Copyright 2024