Security

    LLVM Sanitizer 작성하는 법

    전체 컴파일 파이프라인핵심은 컴파일러 드라이버가 모든것을 연결한다는 점이다. 1. 프론트엔드 호출 (소스 → AST → IR)2. 패스 스케줄링 (어떤 패스를 어떤 순서로 실행할지)3. 런타임 라이브러리 링킹 (compiler-rt 연결) Clang Frontend: 소스코드 → AST → LLVM IR 생성LLVM: IR에 패스 적용 후 백엔드에서 기계어 생성Compiler-rt: 런타임 라이브러리 링킹Sanitizer pass는 항상 마지막에 실행다른 최적화 패스가 sanitizer가 삽입한 코드를 변경하거나 제거할 수 있기 때문 CodeGen 타입 변환int x = 42;C/C++ 타입이 LLVM 타입으로 어떻게 변환되는지 C 타입LLVM 타입크기inti3232비트chari88비트booli88비트..

    Linux KCOV(Kernel Coverage)

    KCOV란커널 코드에 컴파일 시점에 계측(instrumentation)을 삽입해서, 테스트 케이스가 어떤 코드 경로를 실행했는지 알려주는 도구이다.Syzkaller 같은 커버리지 기반 퍼저가 "흥미로운" 테스트 케이스(새로운 코드 경로를 발견한 케이스)를 판별하는 데 주로 사용된다. 1. 컴파일 시점 계측KCOV는 컴파일러가 자동으로 커널 코드에 추적 함수를 삽입하는 방식이다. 개발자가 직접 코드를 수정할 필요가 없다. GCC/Clang의 -fsanitize-coverage=trace-pc 플래그를 사용하면 컴파일러가 각 기본 블록(basic block) 시작점에 __sanitizer_cov_trace_pc() 함수 호출을 삽입한다.이 함수가 호출되면 해당 위치의 주소(PC)를 공유 메모리에 기록한다. ..

    CVE-2019-13288 - Infinite Recursion 취약점

    취약점 개요CVE-2019-13288 은 xpdf 3.02 버전에서 Parser::getObj()함수 (Parser.cc) 에서 발생하는 무한 재귀 취약점으로조작된 PDF 파일이 Parser::getObj() 함수의 무한 재귀를 유발하여 스택 메모리 고갈 → 프로그램 크래시 (DoS) 를 일으키는 취약점이다. 환경 구성먼저 퍼징 타겟인 xpdf를 빌드한다.wget https://dl.xpdfreader.com/old/xpdf-3.02.tar.gztar -xvzf xpdf-3.02.tar.gzcd xpdf-3.02make clean# 디버그 + 최적화 비활성화CFLAGS="-g -O0" CXXFLAGS="-g -O0" ./configure --prefix="$(pwd)/install/"makemake in..

    syzbot, qemu, gdb를 사용하여 linux kernel의 버그 수정

    공개된 Syzbot 버그를 통해 보고서부터 시작하여 제공된 환경을 사용하여 원래 충돌을 확인하고 영향을 받는 커널 버전을 로컬에서 다시 빌드한 다음, 상위 버전 수정 사항을 적용한 후 문제가 해결되었는지 확인하는 절차를 알아보자.목표는 근본 원인을 추적하거나 패치하는 것이 아니다. 버그를 로컬 환경에서 실행하여 수정 전후의 상태를 확인하는 것이다. Linux Kernel 공개 버그리눅스 커널에서 공개된 버그를 찾는 방법은 여러가지 이다.BugZillaSyzbotSyzkaller-bugsChangelogsGit log BugZillaBugZilla는 리눅스 커널의 버그를 보고하는 표준적인 방법이다. subsystem 별로 정리된 흥미로운 취약점(예: IPv4 및 IPv6 네트워킹, ext* 파일 시스템 등..

    syzkaller를 이용한 커널 퍼징 #4 실제 커널 퍼징

    Google은 무제한 서버로 syzkaller를 돌리지만, local에서 작업하기에는 자원이 제한되어있다. syzkaller dashboard는 현재 퍼징 상태, 결과 그리고 linux subsystem에 대한 적용 범위를 표시한다. 타겟 선정 전략Coverage 섹션의 Subsystems Heatmap 분석을 확인하면 각 subsystem의 블록 수와 커버리지 비율을 확인할 수 있다.블록 수가 많으면서 커버리지 비율이 적은 subsystem을 테스트하여 아직 탐색되지 않은 버그를 찾아보기로 했다. 후보 목록퍼징 타겟으로 괜찮아 보이는 것subsystem이유dsa (3%, 3257 블록)코드량 많은데 커버리지 매우 낮음ncsi (5%, 1329 블록)적당한 크기, 낮은 커버리지6lowpan (3%, 46..

    syzkaller를 이용한 커널 퍼징 #3 syz-manager 설정 및 syz-executor 실행

    syz-manager란syz-manager는 syzkaller 의 메인 프론트엔드 프로그램이다. 전체 퍼징 인프라를 관리하는 중앙 컨트롤러 역할을 한다.syz-manager는 다음과 같은 주요 역할을 한다.VM 인스턴스 관리시작시 다음과 같은 절차를 거친다.설정 파일 읽기VM 템플릿 이미지의 스냅샷 생성 (bhyve + ZFS 사용 시)설정된 수만큼 VM 생성각 VM에 SSH로 접속하여 syz-fuzzer 설치 및 시작Crash 감지 및 처리vm console 을 모니터링하여 crash 감지 시 다음과 같은 절차를 거친다.Crash DB에 추가패닉 메시지로 분류일부 VM을 재현 시도에 할당최소 재현 프로그램 찾기 시도C 프로그램으로 변환VM 재생성Corpus RotationVM을 주기적으로 재시작 (cr..

    syzkaller를 이용한 커널 퍼징 #2 Syzkaller의 동작 구조

    커널 퍼징Linux에는 약 450개의 시스템 호출이 있는데 언뜻 보기에 퍼징할 공격 표면이 많지 않아 보일 수 있다. 하지만 실제 공격 표면은 매우 넓은데 이러한 시스템 콜이 수많은 커널 하위 시스템과의 통신 채널을 제공하기 때문이다. 가장 간단한 시스템 콜 open() 조차도 파일 시스템 드라이버(ext4, btrfs) 마다 /dev 하위의 노드 (/dev/null, /dev/sda...) 마다 각각 다른 구현을 가지고 있다. 또 네트워크 패킷 처리, 파일시스템 마운트 (USB 등 외부 미디어), 하드웨어 장치와 직접 통신까지 생각하면 커널은 훨씬 많은 공격 표면을 가지고 있다.따라서 syzlang 정의가 아무리 많아도 모든 케이스를 커버하기 어려워 여전히 모든 공격 표면을 완전히 커버하지는 못한다. ..

    syzkaller를 이용한 커널 퍼징 #1 Fuzzing 이란

    Fuzzing이란퍼징은 프로그램에 무작위 입력을 넣어서 크래시나 버그를 자동으로 찾아내는 소프트웨어 테스팅 기법으로 1980년대부터 있었지만, 최근 보안 연구에서 다시 각광받고 있다.핵심 구성 요소는 다음과 같다.1. 입력 생성 (Input Generation)모델 기반: 입력 형식(문법)을 알고 유효한 테스트 케이스 생성뮤테이션 기반: 기존 시드 입력을 무작위로 변형 → AFL, honggfuzz 같은 도구가 사용2. 실행 엔진 (Execution Engine)생성된 입력으로 프로그램을 실행하고 크래시 감지Sanitizer(ASan, UBSan 등)를 사용해 메모리 오류나 정의되지 않은 동작을 더 잘 탐지Fork 서버, 퍼시스턴트 퍼징 등으로 실행 속도 최적화 실제 예시 - pdf reader 퍼징P..

    Writing Simple Fuzzer

    퍼저의 주요 구성요소 퍼징의 전제는 속일 정도로 단순하다. 프로그램에 무작위 데이터를 넣고 크래시가 나는지 본다. 그 다음 데이터를 조금 바꿔서 프로그램에 다시 넣는다. 그리고 또. 그리고 또. 본질적으로 다른 결과를 기대하면서 똑같은 일을 반복하는 것이다. 모든 퍼저는 최소 두 가지 주요 구성 요소를 가진다변이(mutation) 엔진실행(execution) 엔진 def main(): if len(sys.argv) '.format(sys.argv[0])) else: filename = sys.argv[1] orig_data = get_bytes(filename) # 원본 파일 읽기 dbg = debugger.PtraceDebugger() # 디버거 초기화 ..