블로그 이전했습니다. https://jeongzero.oopy.io/
fuzzing 이란
본문 바로가기
보안/Linux

fuzzing 이란

728x90

퍼징에 대한 전체적인 개념이 잘 설명되어 있는 사이가 있어서 해당 내용을 간략하게 정리해봤다. 

What the Fuzz
This blog post covers the basics of fuzzing, introduces several fuzzing tools and outlines a selection of recent fuzzing research in three sections. The first section explains what fuzzing is on a high level basis and briefly discusses reasons for and against fuzzing.
https://labs.f-secure.com/blog/what-the-fuzz/

 


 

1. fuzzing이란?


fuzzing을 프로그램이 가지고 있는 잠재적인 취약점을 식별하는데 사용되는 소프트웨어 기술이다. fuzzing을 통해 프로그램에 들어가는 입력(표준입력 or 파일)을 변조시켜 정상적인 동작이 아닌, 크래시를 유발시키거나 메모리 corruption을 일으키는 테스트 사례를 기록할 수 있고, 해당 사례를 분석하여 취약점을 트리거 시킬수 있다. 브라우저, 응용프로그램, 커널, 드라이버, 웹 응용 프로그램 등등이 전부 fuzzing의 대상이 될수 있다. 

 

 

 

2. why fuzzing?


결론은 fuzzing을 통해 버그를 자동으로 찾을수 있다는 것이다. fuzzing이 동적 분석이라면, 일반적인 정적 분석을 통해서도 버그를 찾을수 있다. 하지만 해당 방법은 많은 시간과 노력이 드는것은 물론이며, 또한 자신의 실력에 따라서 버그를 찾는게 달라진다. 그렇다고 동적분석이 무조건 좋다 ! 는 아님. 

 

분석하려는 애플리케이션의 구조가 만약 매우 복잡할 수록 그 안에서 터질수 있는 버그가 더 많을 것이고, 이러한 복잡성이 증가하면 attack surface도 당연히 늘어날 것이다. 이렇게 복잡한 애플리케이션을 정적으로 분석한다? ⇒ 실력있는 분석가와 많은 시간이 필요하다. 이런 면에서는 fuzzing이 효율적일수도 있다. 

 

 

3. Common issues with fuzzing


하지만 그렇다고 퍼징이 최고다 ! 퍼저가 분명 좋은 기술인건 확실하지만 그렇다고 만능이 아니기 때문이다. fuzzing을 돌리기 위해 필요한 설정들을 세팅하는데 많은 시간이 걸린다. 물론, 매우 간단한 덤 퍼저 같은 경우는 세팅할 필요가 없지만, 입력되는 파일의 구조를 인식하여 퍼징을 하게 되는 경우, 해당 파일의 구조를 일일이 분석해야하기 때문이다. 

 

또한 퍼저 만으로는 프로그램의 보안성을 보장할수는 없다. 무슨 말이냐면, 퍼저가 모든 취약점을 다 찾을수는 없다는 말이다. 그리고 fuzzing을 돌려서 크래시가 우수수 터진다고 해도, 오탐일 가능성도 있고, 익스가 불가능한 크래시일 수도 있다. 

 

따라서 오탐, 언익스 요런 거를 확인하는 검토 프로세스가 필요하며, 사실 제일 확실한건 수동으로 저런거를 파악하는게 제일 신뢰성이 높다. 따라서 fuzzing에 대해서 많은 연구가 진행되고 있는데 아마 저러한 fuzzing의 단점? 을 보완하고, 효율적인 퍼징을 어떻게 할수 있는가에 대해서 많이 공부할 필요성이 있을것 같다. 

 

 

4. What is needed for fuzzing?


퍼징을 하기 위해선 입력받을 타겟이 필요하다. 당연한 소리인가.. 

 

만약 저런 이미지 뷰어 프로그램에서 취약점을 찾고 싶다면 필요한건 일단 2개다. 저 대상 바이너리와, 시드파일 즉, 이미지 파일들이다. 조질라는 응용 프로그램이 복잡할수록 퍼저를 통해 버그를 찾을 가능성이 더 높다. 

 

 

5. What types of bugs can a fuzzer find?


이론적으로는 퍼징을 통해 모든 버그 유형을 찾을수 있다고 한다. 퍼징의 목적이 프로그램 내의 비정상적인 동작을 찾고, 이를 기록하는 것이기 떄문에, 이를 위한 탐지 메커니즘이 필요하다. 대체적으로 메모리 손상과 관련된 버그는 명확한 결과가 보여지기 때문에 퍼징을 통해 발견하기 쉽다. 하지만 로직버그는 감지하기 매우 어렵다고 한다. 

 

https://www.slideshare.net/CanSecWest/csw2017-geshevmiller-logic-bug-hunting-in-chrome-on-android
  • heap overflow
  • stack overflow
  • interger overflow
  • format string bug

 

요런 memory courruption은 쉽게 발견되지만 로직 버그는 퍼징으로 찾기 힘들다. 저기 참고자료를 보면또 알수 있듯이, logic bug가 아주 좋은 타겟이라고 한다. 여튼 뭐 그렇다고 한다. 저기 보면 잘 나와있다. 

 

 

 

6. Architecture of a typical fuzzer


일반적으로 퍼저는 크게 3가지 부분으로 나뉜다.  

  1. TestCase Generator : 타겟 프로그램에 삽입할 입력을 만듬
  1. Logger : 퍼징을 돌리는 중에 버그 분석에 필요한 정보를 기록함
  1. Worker : 주어진 입력으로 예기치 않은 동작을 인식함
  1. Server/Master : 1,2,3을 컨트롤하고 상호작용 관리

 

TestCase Generator


테스트 케이스 생성을 담당한다. 한마디로 아까 예시로 설명한 이미지 뷰어 프로그램에서 정상적인 이미지 파일을 변조시키는 역할이라고 보면 된다. 이때 변조를 시키는 방법은 크게 2가지이다. 이미지 파일의 구조를 분석하여, 해당 이미지 파일 구조에 맞는 테스트 케이스를 생성하거나, 아니면 그냥 무작위하게 이미지 파일 구조에 상관없이 변조시크는 방법이 있다. 전자를 smart fuzzer, 후자를 dom fuzzer라고 한다. 

 

Worker


테스트 케이스 생성기가 제공하는 테스트케이스를 실행하는 주체이다. 또한 예상치 못한 동작을 파악해야한다. ASAN같은 도구를 이용해서 버그를 찾을수 있다. 

 

Logger


발견된 크래시와, 테스트 사례를 기록한다. 커버리지 기반 퍼징일 경우, 새롭게 찾은 코드 커버리지도 저장을 한다. 이를 통해 크래시가 발생한 로그를 확인하여 분석을 진행하면 된다. 

 

 

7. fuzzing 방법


1) Guided Fuzzing


TestCase Generator가 만들어내는 testcase들은 품질차이가 매우 크다. 따라서 testcase generator가 변경하고나 생성할 testcase를 결정하기 위해 일종의 지침이 필요하고, 그래야지만 의미있는 testcase가 나온다. 즉, testcase generator에서 어떤 값을 변경할지 정하는게 매우 중요하다. 

 

일반적으로 사용하는 지침으로는 코드의 커버리지를 넓히는 방법이 있다. 이론적으로 코드 커버리지가 넓을수록 더 많은 버그를 찾을수 있다. 코드 커버리지가 넓다는 의미는 바이너리 내부의 여러 로직이 존재하는데, 생성되는 testcase를 통해 많은 내부 로직을 거치게 하는것을 뜻한다. 

그렇다면 당연히 코드커버리지를 높이면 많은 분기를 타게 될 것이고, 이를 통해 더 많은 버그가 나올 가능성이 높겠구만 

참고자료 : https://google.github.io/clusterfuzz/reference/coverage-guided-vs-blackbox/ 

 

2) Dumb fuzzing


덤퍼징은 테스트케이스를 생성하기 위해 타겟 프로그램에 대한 이해도가 없어도 된다. 입력에 대한 정보를 몰라도 되기때문에, 간편하긴 하지만, 만약 건드리면 안돼는 헤더나, 체크섬같은 것을 변조시키면, 유효한 입력을 생성하지 못할것이다. 

Mutation based fuzzing

이것도 따지고 보면 덤 퍼징이라고 봐도 무방할꺼 같다. 알려진 테스트 케이스를 변경하여 새로운 테스트 케이스를 만든다고 한다. 내가 이해한 바로는, 알려진 테스트케이스란, 이미 뮤테이션 된 파일을 다시 기준으로 하여 뮤테이션을 시키는것 같다. 뮤테이션 방법으로는 비트플립, 랜덤화 등이 있다.  

 

여기서 가장 중요한 것은 어떠한 알려진 테스트케이스를 선택하느냐이다. 만약 이미지 뷰어 프로그램을 타겟으로 png 파일을 테스트케이스로 생성하고, 이를 기준으로 뮤테이션을 조진다고해도, 해당 파일이 jpg 파일을 처리하는 코드에 도달할 가능성이 없다. 따라서 이런것도 잘 파악해서 테스트케이스를 선택해야한다. 

 

 

3) smart fuzzing


dumb fuzzer와 다른게 smart 퍼저는 입력에 대한 구조를 미리 파악하여 테스트케이스를 만들어야한다. 만약 알집을 퍼징한다! 하면 알집에서 구현되어있는 format 정보를 파악하고 해당 file format에 맞게 testcase를 생성해야한다는 소리이다.  

Generation based fuzzing

이 역시 smart fuzzer라고 보면 된다. 입력에 대한 구조를 파악해야 한다. 이는 뮤테이션 기반 퍼저보다 더 많은 코드 커버리지를 높일수 있다. 당연히 입력 구조를 정해주고 가니까 ㅋ 

 

 

8. 요약


퍼징을 통해 취약점을 찾으려면 일단 타겟을 명확히 해야한다. 심플한 프로그램은 그냥 bff 같은 덤퍼저로도 크래시를 유발시킬수 있지만, 복잡한 프로그램을 조질경우, 이는 매우 오랜 시간이 걸린다. 그래서 수없이 많이 들은소리가 바로 코드 커버리지를 높이는게 중요하다! 이다. 

 

퍼징을 효율적으로 할라면 일단, 타겟을 잘 설정하고, 어떠한 기능을 기준으로 퍼징을 돌릴것인가? 를 잘 선택해야한다. 압축 프로그램이라면 압축을 해제할는 기능을 기준으로 퍼징을 할지, 아니면 압축을 하는 기능으로 퍼징을 돌릴지 말이다. 

 

 

9. Fuzzing Tools


퍼징을 할때 유요한 도구가 있다 

 

1) Sanitizers

트리거된 취약점에 대한 정보를 매우 디테일하게 로그로 보여주는 기능을 한다. 이를 사용하면 성능이 저하가 되긴하지만 쓸만한 가치는 충분히 있다. 새니타이저는 4개의 종류가 있다. 

  • AddressSanizier(ASAN)
  • ThreadSanitzer(Tsan)
  • MemortSanizier(MSan)
  • UndeifnedBehaviourSanitizer(UBSan)

 

2) Radamsa

뮤테이션 기반 덤퍼저 

 

3) AFL

코드 커버리지 기반, 뮤테이션 기반, 덤 퍼져이다. 입력에 대한 구조를 알필요가 없기 때문에 덤퍼저라고 하지만, 해당 퍼저 내부에서 스스로 유효한 입력구조를 파악하고 생성한다는 가장 큰 기능이 있다.  

 

4) peach fuzzer

대표적인 스마트퍼저이다. 입력에 대한 구조를 확실하게 맞춰서 넣어줘야한다. 이 과정이 복잡할순 있지만, 이를 통해 거의 모든것을 퍼징 가능하다. 

 

5) lib-fuzzer, Honggfuzz

6) Domato

HTML, CSS, JS를 생성하는 테스트케이스 생성기라고 함.  

 

728x90

'보안 > Linux' 카테고리의 다른 글

AFL fuzzer 설명 및 사용방법  (2) 2020.08.26
seccomp 간단 정리  (0) 2020.07.08
main 함수가 호출, 종료되는 과정  (0) 2020.05.14
fclose 분석  (0) 2020.05.01
House of Orange 분석  (0) 2020.04.29