소개

https://github.com/google/graphicsfuzz

이 문서는 VMware에서 glsl 퍼저를 돌리는 방법을 설명한다. Vulkan 드라이버가 작동하지 않을 때 어떻게 작동할 수 있을지에 대해 이야기한다.

본론

퍼저 구조

퍼저는 전체적으로 서버와 클라이언트 구조로 되어 있다. 서버의 경우 클라이언트들을 웹 환경으로 관리할 수 있으며 클라이언트는 서버로부터 파일을 받아 이를 구동시키는 역할을 한다. 클라이언트의 경우 worker로 불리며 서버 웹 페이지를 이용하여 worker에 일을 할당할 수 있다.

https://github.com/google/graphicsfuzz/releases/tag/v1.3

서버의 경우 prebuilt binary (위 링크의 graphicsfuzz.zip)를 통해 구동할 수 있다. 압축을 풀고난 뒤 python/drivers에 가면 glsl-server가 있다. 해당 서버를 구동하면 된다.

예시 : glsl-server --port 31337 (pwd는 작업할 위치로 바이너리 위치와 상관 없이 따로 생성해야 한다)

클라이언트의 경우 마찬가지로 prebuilt binary (위 링크의 gles-worker-desktop.jar)가 있으며 이를 다운로드 받아서 실행시켜주어야 한다. VM guest 안에서 실행시켜주면 되며 마찬가지로 폴더를 하나 생성해서 그 안에서 실행시켜주면 된다.

예시 : java -ea -jar gles-worker-desktop.jar --server http://localhost:31337

자세한 퍼저 작동은 링크에 있다. 해당 문서의 Running the servergles-desktop-worker 파트를 보면 된다.

준비물

준비물은 간단하다. Release에 동봉되어 있는 (graphicsfuzz.zip) 셰이더 파일들을 준비해주면 된다. 해당 파일들을 통해 이후 단계에서 variant를 생성할 것이기 때문에 이를 미리 준비해놓자.

퍼저 구동

퍼저를 구동하기 위해서 3가지 단계를 거쳐야 한다.

  1. glsl-generate 실행
  2. glsl-server 실행, worker 실행
  3. worker에 job 할당

glsl-generate

glsl-generate의 경우 shader family를 생성하는데 사용된다. 지금 단계에서 생성하는 shader family는 퍼징을 수행할 때 worker가 실행하는 입력으로 들어가게 된다. 아래 명령어를 통해 실행할 수 있다.

glsl-generate ../prebuilt/shaders/samples/100 ../prebuilt/shaders/samples/100 100 family_100 shaderfamilies

첫째로 reference와 donor를 요구하는데 둘 모두 같은 위치로 shader 파일들이 들어있는 폴더를 지정하면 된다.
둘째로 variant를 몇개 생성할 것인지 요구한다. 위 예시에서는 100을 주었다.
셋째로 variant 이름을 지정한다. 위에서는 family_100으로 주었다.
넷째로 variant를 만들 대상 폴더를 지정한다. 위에서는 shaderfamilies 폴더로 지정했으며, 해당 이름은 고정으로 필수로 shaderfamilies로 주어야 한다. (다른 이름을 사용할 경우 서버 실행에 옵션으로 주어야 한다)

glsl-server 실행

shaderfamilies가 있는 곳에 pwd를 옮기고 glsl-server를 실행한다. --port 옵션으로 포트를 지정할 수 있다.

서버를 실행하고 나면 http://<ip address>:<port>/webui로 웹 인터페이스를 볼 수 있다.

job 할당

Job 할당의 경우 Run shader families on workers를 선택한 후 worker와 shader families를 지정해주면 된다. 이 이전에 worker가 실행되어야 worker 목록에 나오게 된다.

Worker를 실행하는 방법은 매우 간단히 주어진 gles-worker-desktop.jar 를 실행하면 된다.

예시 : java -ea -jar gles-worker-desktop.jar

--server 옵션으로 서버를 지정할 수도 있다. webui가 열려있는 서버를 지정해주면 된다.

예시 : java -ea -jar gles-worker-desktop.jar --server http://localhost:31337

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

AFLNET: A Greybox Fuzzer for Network Protocols  (0) 2021.01.19

https://www.comp.nus.edu.sg/~abhik/pdf/AFLNet-ICST20.pdf
https://github.com/aflnet/aflnet

주의

지극히 개인적인 의견만 들어가 있습니다. (본인도 뭘 썼는지 모르겠음)

선정 이유

이번에 공격 벡터로 네트워크를 선택하면서 네트워크 프로토콜에 대한 퍼징 방법을 공부할 필요가 있었다. BOOFuzz와 같은 퍼저도 있었지만 그 중에서 그나마 친숙한 AFL에서 어떻게 네트워크 퍼징을 수행하였는지 알아보기 위해 해당 논문을 선택하였다.

요약

문제 특성

네트워크 프로토콜에서 퍼징을 진행하기 쉽지 않다. CGF (Coverage-based Greybox Fuzzing)이나 SBF (Stateful Blackbox Fuzzing)과 같은 여러 시도가 있었지만 네트워크 프로토콜의 특성에 따라 한계가 존재한다.

  1. 서버는 stateful하고 message-driven이다.
  2. 서버는 state에 의해 응답이 결정되기 때문에 CGF로써는 이런 특성을 잡아내는게 쉽지 않다. (State를 tracking하는 기능이 없기 때문이다)

CGF with Concatenated Files

CGF를 통해 concatenated file들을 만들어 테스트 입력으로 넣어보는 시도가 있었다. 하지만 이는 매우 비효율적인 방법이다.

  1. 각 iteration마다 전체 시드 파일에 대해 mutation을 진행해야 한다. 만약에 $m_0 \thicksim m_k$의 message sequence가 있다면 전체를 mutate하는 것보다 가장 가능성 있는 $m_i$만 mutate 하는 것이 효율적이다.
  2. 프로그램 상태에 대한 정보가 없다면 많은 message sequence들이 거절당할 수 있다.

위의 한계점들로 인해 stateful program을 퍼징하는데 가장 많이 사용되는 기술은 SBF이다.

SBF

앞에서 언급한 CGF의 한계들 때문에 SBF를 사용하여 네트워크를 퍼징하는 것을 시도하는 연구가 많았다. 이는 프로토콜 모델을 돌면서 FSM이나 그래프 형태로 메세지의 데이터 모델이나 문법을 정보를 얻고 이를 토대로 메세지 시퀀스를 생성하는데 여러 문제가 존재한다.

  • 하지만 이는 개발자가 프로토콜에 대해 얼마나 잘 이해했고 잘 구현했는지, 또 클라이언트와 서버 간의 샘플 패킷들에 의존적이다.
  • 또한 SUT에 구현되어 있는 프로토콜에 대한 정보를 정확하게 추출하지 못하는 경우가 많다.
  • 다른 여타 블랙박스 퍼징과 동일하게 인상깊은 테스트 케이스들을 보유하지 못한다. (Coverage와 같은 정보가 없기 때문)
  • 또한, 런타임에 상태 정보를 업데이트 하지 않는다.

AFLNet

위의 문제들을 보완할 수 있도록 stateful CGF 툴을 만들었다. AFLNet은 자동으로 상태 모델을 유도하고 coverage guided fuzzing을 사용하여 새로운 상태들을 찾고 상태 모델을 개선한다. 또한, 그동안 동적으로 만들어진 상태 모델은 state coverage와 code coverage에 대한 정보를 제공하여 퍼징이 더 잘 일어날 수 있도록 한다.

용어들

  • 서버 : 원격으로 접근 가능한 소프트웨어 시스템
  • 클라이언트 : 서버에서 제공하는 서비스를 사용하는 소프트웨어 시스템
  • 메세지 시퀀스 : 메세지 벡터
  • 요청 : 클라이언트로부터의 메세지
  • 응답 : 서버로부터의 메세지
  • 서버 상태 : 클라이언트와의 통신 중 서버의 특정 상태

퍼저의 경우 클라이언트로 작동하며 서버의 경우 서버로써 작동한다.

디자인 및 구성

AFLNet은 AFL의 확장 버전이라고 생각하면 된다. AFLNet은 두 채널을 제공하는데, 하나는 메세지를 서버에 보내기 위한 채널, 다른 하나는 서버에서 응답을 받기 위한 채널이다. 서버에서 응답을 받기 위한 채널은 state feedback을 받거나 code coverage를 받는데 사용한다. AFLNet은 기본적인 C 소켓 라이브러리를 사용하며, 적절한 동기화를 위해 요청 간 딜레이가 포함되어 있다.

AFLNet의 입력으로는 네트워크 트래픽을 포함한 pcap 파일을 넣어주면 된다. 넣어준 파일은 AFLNet의 Request Sequence Parser에 의해 파싱되어 초기 메세지 시퀀스를 생성하는데 사용된다.

이후 State Machine Learner가 서버 응답들을 가지고 state machine을 업데이트 한다. 그 후 업데이트 된 state machine을 Target State Selector가 참조하여 다음으로 탐색할 state를 지정한다. 각종 휴리스틱 알고리즘을 적용하여 퍼저가 어떤 state에 집중해야 할 지 지정한다. 이후 지정된 state에 도달하기 위해 Sequence Selector가 message sequence를 선택한다. 이때 AFL이 관리하는 seed corpus와 유사하게 AFLNet은 state corpus를 추가로 관리하여 state에 대한 정보들을 저장한다. 저장된 정보는 Sequence Selector가 참조하여 message sequence를 랜덤으로 선택하는데 사용된다.

Sequence Mutator는 선택된 sequence에 대한 mutation을 진행한다. 이는 generation-based approach에 비해 장점이 있는데, (1) 비교적 유효한 message sequence를 생성할 수 있고, (2) 특정 중요한 message sequence에 변형을 가해 corpus를 더 발전시킬 수 있다.

Mutation 과정은 아래와 같다.

Algorithm : State $s$와 message sequence $M$이 주어졌을 때 해당 알고리즘은 새로운 message sequence $M'$를 생성한다.

  1. Original sequence $M$을 3 파트로 나눈다.
    1. Prefix $M_1$ : state $s$에 도달하기 위한 sequence
    2. Candidate subsequence $M_2$ : state $s$에 남아 있을 수 있으면서 실행 가능한 message subsequence
    3. Suffix $M_3$ : 나머지 sequence 부분 ($<M_1, M_2, M_3> = M$)
  2. 새로운 sequence $M'$를 $M'=<M_1, mutate(M_2), M_3>$로 생성한다.
    • Protocol-aware mutation operator $mutate$를 사용한다. 주어진 corpus $C$에서 (Message Pool) message를 가져와 이와 기존 message와 replacement, insertion, duplication, deletion 등의 작업을 수행한다. 또한, 기존 mutation 방법인 bit flipping, substition, insertion, deletion of blocks 등의 작업도 수행한다.
  3. 새롭게 생성된 $M'$를 중요하다고 판단하고 이를 corpus $C$에 추가한다. 또한, sequence에 의해 새로운 state나 state transition이 발견될 경우 해당 sequence를 중요하다고 판단한다.

총평

정확한 알고리즘이나 방법에 대해서는 서술이 되어 있지 않지만 소스코드가 주어져 있으며 case study가 나름 잘 되어 있어서 더 깊게 이해하는데 어려움이 없을 것으로 생각된다. 또한, 아키텍쳐가 상당히 명확해서 이해하기가 쉬웠다.
다만 아쉬운 점은 IP와 같은 프로토콜의 경우 체크섬이 있는데 해당 체크섬을 어떻게 통과할 수 있는지에 대한 서술이 없다는 것이다. 또한, IPSM을 어떻게 생성해 나가는지에 대한 설명도 없어 아쉽다.

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

Running glsl fuzzer in VM (graphicsfuzz from Google)  (0) 2021.01.19

+ Recent posts