Fuzzing이란?
fuzzing이란 fuzz input을 사용해 PUT(Program Under Test)를 실행하는 것이고, fuzz input 이란 PUT가 예상하지 못할 input을 뜻한다. PUT이 잘못 처리하는 input 혹은 개발 의도와는 다른 행동을 보이는 input을 넣어 PUT을 실행하는 것이라고 볼 수 있다. 즉 fuzzing이란,
자동화 테스트로 기형/반기형적 데이터를 주입하여 소프트웨어 버그를 찾는 블랙박스 테스팅 기술이다.
PUT은 테스트 실행중인 프로그램이라고 해석하자
Fuzzing을 왜 쓰나?
결론적으로는 fuzzing을 통해 버그를 자동으로 찾을 수 있다는 것이다. 일반적인 정적분석으로도 버그를 찾을 수 있지만 많은 시간과 노력이 들며 자신의 실력에 따라 버그를 찾을 수도, 못 찾을 수 도 있다.
그렇다고 fuzzing이 만능은 아니다. crash가 터져도 오탐일 가능성도 있고 익스가 불가능한 crash일 수도 있다.
Fuzzing의 한계
정확한 분석보다는 무작위성에 의존한다.
메모리 손상같은 단순한 결함들은 쉽게 찾아내지만 로직 버그는 감지하기 매우 어렵다고 한다.
Code Coverage
code coverage는 Fuzzing을 진행할 때 테스트가 얼마나 충분한가를 나타내는 지표이다.
즉 테스트시 코드 자체가 얼마나 실행이 되었는지를 나타낸다.
코드의 구조를 이루는 것은 크게 구문(Statement), 조건(Condition), 결정(Desision)이다.
- Statement / Line Coverage예를 들어서위 코드에서 func(2)가 실행 될 경우 (1),(2),(4) 는 실행되지만 (3)은 실행이 되지 않는다. 이럴 경우 Statement Coverage는 75%가 된다.
- void func(int a) { printf("START!"); // (1) if(a > 3) // (2) printf("a > 3\\n"); // (3) printf("END"); // (4) }
- 코드가 한번 이상 실행되면 충족된다.
- Condition예를 들어서위 코드의 조건식에서 Condition Coverage를 모두 만족하는 입력값은 func(1, 1)와 func(-1, -1) 이 존재한다.조건식은 무조건 false를 반환한다. 즉 조건의 실행여부를 측정한다고 보면 된다.
- x > 0 의 조건식에서 true/false 를 모두 만족하고 y < 0 의 조건식에서 true/false 를 모두 만족한다.
- void func(int a, int b) { printf("START!"); if(a > 0 && b < 0) printf("good"); printf("END"); }
- 각 분기문들에 대한 Coverage 이다.
- Desision / Branch Coverage예를 들어위 코드의 조건식에서 true/false 를 모두 가질 수 있는 입력값은 func(1, 1)와 func(0, 0) 이 있다. 첫 번째는 x > 0과 y > 0 을 모두 만족해 true를 반환, 두 번째는 x ≤ 0, y ≤ 0 을 만족해 false를 반환한다. 모든 조건식을 만족하니 Desision Coverage를 만족한다.
- void func(int a, int b) { printf("START"); if( (a > 0) && (b > 0)) printf("great"); printf("END"); }
- 모든 조건식이 true/false를 가지면 충족된다.
Fuzzing의 구현
Fuzzer는 반무작위 데이터를 주입하고 버그를 탐지한다.
데이터 생성은 생성기로, 취약점 탐지는 디버깅 도구에 의존한다. 생성기는 일반적인 퍼징 벡터(위험한 것으로 알려진 값 목록) 또는 완전 무작위의 데이터 조합을 사용한다.
공격 유형
Fuzzer는 아래와 같은 공격조합을 시도한다.
- numbers (signed/unsigned integers/ float …)
- chars
- metadata (사용자 입력)
- pure binary sequences (이진 수열)
이들을 재조합하여 주입한다.
Fuzzing의 종류
- Blackbox Fuzzing입력 값은 무작위적이며 단순하다.단순하지만 취약점 발견확률이 낮다.
- 어플리케이션의 실행이 멈추거나(crash) 실행이 일시적으로 보류(hang)되면 테스트에서 실패한것으로 간주되고, 그렇지 않다면 테스트 통과이다.
- 소스코드를 가지고 있지 않고 Binary 만을 이용하여 test한다.
- Whitebox FuzzingBlackbox Fuzzing과 다른 종류의 취약점을 찾을 수 있다.
- 소스코드가 필요하며 분석이 복잡하다.
- Graybox Fuzzing
- 내부 프로그램의 구조를 부분적으로 알고있다.(데이터 구조체, 알고리즘 등)
crash와 hang의 차이점
crash : 프로그램이 예기치 않게 완전히 중단되는 것을 의미한다.( 터짐 )
hang : 프로그램이 응답을 멈추고 사용자의 입력이나 다른 프로세스에 대해 반응하지 않는 상태이다.( 무한 로딩 )
Fuzzer의 구성요소
fuzzer는 크게 3가지 부분으로 나뉜다.
- TestCase Generator
- Smart Fuzzer
- 프로그램의 입력 데이터 구조를 파악하여 해당 구조에 맞게 Mutation을 진행한다.
- Dumb Fuzzer
- 랜덤한 데이터를 생성하여 Mutation을 진행한다.
- 테스트 케이스 생성을 담당한다. 즉 타겟 프로그램에 삽입할 입력을 만든다.
- Logger
- 발견된 crash와 test case를 기록한다. coverage 기반 fuzzing일 경우 새롭게 찾은 코드 corverage도 저장을 한다. 이를 통해 crash가 발생한 로그를 확인하여 분석을 진행한다.
- Worker
- 테스트케이스를 실행하는 주체이다. 또한 예상치 못한 동작을 파악해야한다. ASAN같은 도구를 이용해서 버그를 찾을 수 있다.
- Server/Master
- 1,2,3을 컨트롤하고 상호작용을 관리한다.
ASAN이란?
Address Sanitizer이란 잘못된 메모리 주소로의 접근 및 쓰기를 검출하는 것을 도와주는 도구이다. 이 도구는 런타임에 binding하는 도구와는 달리 컴파일 타임에 붙어 추가적인 코드를 삽입해주는 도구이다.
gcc에서는 -fsanitizer=address 옵션을 주어서 쉽게 사용할 수 있다.
기본적으로 stack에서 메모리 침범을 했을 때 갚을 덮어씌우는 시점에서 프로그램이 멈추지는 않는다. stack rewinding 도중에서야 값이 잘못 덮어씌워진 것을 확인하고 프로그램이 멈추게 된다.
하지만 address sanitizer을 사용하면 잘못된 지역에 값을 덮어씌우는 시점에 바로 프로그램이 멈추면서 추가로 디버그 정보까지 보여준다.
아무튼 runtime error을 탐지해주는 도구라고 볼 수 있다.
Fuzzing 방법
- Guided Fuzzing
Test Case의 생성을 Code Coverage를 넓히기 위해서 사용하는 방법이며, Test case에서 변경할 데이터를 정하고 그 부분의 데이터만 변경하는 것이다.
- Dumb Fuzzing
랜덤한 데이터를 생성하여 대상 소프트웨어에 전달하는 방식으로 프로그램에 대한 이해도 없이도 진행할 수 있다.
- Mutation Based Fuzzing
- 알려진 test case를 변경하여 새로운 test case를 만든다. mutation의 방법으로는 비트플립, 랜덤화 등이 있다. dumb fuzzing의 일종이다.
- Smart Fuzzing
입력에 대한 구조를 미리 파악하고 그것에 맞춰 적절한 테스트 케이스(받아들일 수 있는 입력)를 생성한다.
- Generation Based FuzzingPUT의 입력 형태를 고려한 model이 있다.
- 입력가능한 공간에 대한 모델을 기반으로 test case를 만든다.
더 높은 Code Coverage를 가진다.
Fuzzing Tools
- Sanitizer
- C, C++로 작성된 프로그램에서 발생하는 취약점에 대한 정보를 로그에 저장하고 보여주는 기능을 한다.
- Radamsa
- Radamsa는 Sample File을 기반으로 자동으로 Mutation을 진행한다. Mutation-Based Fuzzer로 분류되고 있다.
- AFL ** 내가 사용할 것!!
- Code Coverage-Based, Mutation-Based, Dumb Fuzzer 이다. 입력에 대한 구조를 알 필요가 없지만 해당 Fuzzer 에서 자동으로 데이터 구조를 파악해 Mutation을 진행하는 특징을 가지고 있다.
- Peach Fuzzer
- 데이터 구조와 변경할 데이터를 지정해 Fuzzing을 진행하는 Smart Fuzzer 이다.
<틀린 부분이 있다면 비난과 욕설을 해주세요>
'Fuzzing' 카테고리의 다른 글
Fuzzing101 Exercise6 (0) | 2024.07.07 |
---|---|
AddressSanitizer (0) | 2024.04.22 |
AFL++ download (1) | 2023.10.04 |
AFL++ (0) | 2023.10.04 |
FUZZING의 과정 (0) | 2023.09.29 |