Cyber Grand Challenge by DARPA

1. Overview

2014년 여름, 미 국방성 연구부문을 담당하고 있는 DARPA (Defense Advanced Research Projects Agency)에서 매우 흥미로운 competition event를 진행한다. 이름하여 Cyber Grand Challenge – 자동화된 공격방어 시스템 (automated cyber reasoning system) 하에 상호 간의 공격과 방어를 모두 기계가 실시간으로 담당하게 해 경쟁하는 대회다.

많은 CTF Challenge 대회가 있지만, 사람의 개입없이 순수히 기계만을 이용해 취약점을 찾고, 공격과 방어를 하는 경우는 세계적으로 처음이었다. 게다가 상당히 큰 금액의 상금은 보안인의 관심을 끌기에 충분했다. 

대표링크는 여기 https://cgc.darpa.mil 로 각종 문서와 대회결과를 확인할 수 있다. 대회는 3년간 예선(2014년)과 최종후보 결선전(2015년)을 거쳐 2016년 8월 4일 DEF CON에서 Final 결승전을 치룬다. Final은 7개의 팀이 겨룰 예정이며, 우승자는 무려 20만불의 상금을 거머쥘 수 있다.

작년 USENIX technical session에서 Invite Talk으로 DARPA의 Mike가 두번의 대회를 치르면서 있었던 과정과 결과를 발표했다. 발표자료는 여기를 참고하기 바란다. 

UPDATED  (As of Aug. 8, 2016) 
a. Mayhem declared the final winner of historic Cyber Grand Challenge.
b. Mayhem has been developed as a cyber reasoning system since 2012 by Sang Kil Cha et al., see the paper, Unleashing MAYHEM on Binary Code, for more details)
c. CFE File Archive is available now.

 

2. DECREE 

무엇보다도 DARPA는 취약점 자체에 초점을 맞출 수 있도록 기존 리눅스 환경을 변형한 DECREE라는 운영제체를 개발했다. DECREE는 수백 개의 system call이 존재하는 리눅스와는 다르게 실행파일이 다음과 같이 단 7개의 system call만을 이용하도록 설계했다. (Header 파일 참조)

  • int transmit(int fd, const void *buf, size_t count, size_t *tx_bytes);
  • int receive(int fd, void *buf, size_t count, size_t *rx_bytes);
  • int fdwait(int nfds, fd_set *readfds, fd_set *writefds);
  • int allocate(size_t length, int is_X, void **addr);
  • int deallocate(void *addr, size_t length);
  • int random(void *buf, size_t count, size_t *rnd_bytes);

새로운 운영체제에서 작동할 수 있는 실행파일을 컴파일할 수 있도록 gcc를 수정하고, 실행파일포맷 또한 기존의 ELF를 기반으로 한 cgc 포맷을 새로 정의했다. 이는 기존의 어떤 운영체제에서도 파일의 실행은 물론 대회에서 발견한 취약점과 exploit 모두 무미의함을 의미한다. 그리고 IPC (Inter-Process Communication) 도 무척 제한적이다. 공유 메모리를 지원하지 않으며, 단순한 양방향 통신만을 지원한다.

CyberGrandChallenge Github에 있는 walk-through 문서를 따라 VirtualBox와 vagrant를 설치하고 vbox를 추가한 후 다음과 같이 5개의 VM을 차례로 부팅할 수 있다.

다음은 default로 설정되어 있는 CRS서버에 ssh로 연결한 모습이다. 게스트 운영체에제서 /vagrant로 이동하면 자동으로 Vagrant 스크립트에 의해 호스트 운영체제의 현재 디렉토리를 공유하고 있음을 알 수 있다.

 

3. Challenge Binaries and Utilities

2015년 Grand Challenge에서 DARPA는 대회용으로 131개의 Compile된 Binary만을 공개했다. 하지만, 현재 Github Repository에서 모든 바이너리의 소스코드와 취약점, PoV (Proof of Vulnerability), 그리고 상세한 설명 (Service Description)을 제공하고 있다. 

131개의 바이너리는 단순하게 만든 운영체제에서 실제 서비스와 유사할 만큼의 복잡도를 가진 서비스를 제공할 수 있다. 72개의 CC 파일 (7000 LOC), 1236개의 헤더 (19만 LOC), 1996개의 C 파일 (20만 LOC), 6000여 개의 함수와 590개의 PoV가 이를 대변한다. 

(1) CGC Executable Format (CGCEF)

CGC 실행 포맷은 처음 15바이트의 헤더가 ELF와 다르다. \x7fCGC로 시작함을 알 수 있다. 

CGC 실행포맷은 cgcef-verify라는 도구로 정상여부를 확인할 수 있으며, readelf와 같이 readcgcef로 읽을 수 있다.  PATH 환경변수를 살짝 조정해서 기존의 bintools을 편하게 대체할 수도 있다.

 

(2) CGCEF Program Headers

CGCEF는 섹션유형이(section type) 4개밖에 없다. 모든 바이너리는 정적으로 연결(Statically Linked)되어 있으며, 동적링킹 (Dynamic Linked)과 thread를 사용하지 않는다. 따라서 TLS (Thread Local Storage) 섹션도 존재하지 않는다.

 

(3) CGCEF Section Headers

섹션헤더는 디버깅할 때 정보 제공용으로만 사용하며, Loader는 이 섹션을 무시하고 로딩한다. 배포용(release)으로 제공하는 바이너리는 보통 이 섹션이 제거되고(stripped) 없다고 보면 된다.

(4) IDA Pro modules for CGC

Reversing을 할 때 표준도구처럼 많은 사람들이 애용하는 IDA Pro에서도 Loading할 수 있도 Module을 제공한다. 여기서 (http://idabook.com/cgc/) 버전에 맞는 모듈을 다운받아 설치하면 CGC 바이너리를 로딩할 때 자동으로 Loader를 선택해 준다.

(5) How to run CGC binary as a service

일일히 실행하기 번거로우면, 다음과 같이 임의로 서버와 클라이언트를 실행해 확인해 볼 수 있다. 다음과 같이 cqe 바이너리의 poller directory 내에 for-testing과 for-release 두 가지 형태의 많은 sample data로 테스트해 볼 수 있다.

또한 pov 디렉토리에는 실제 취약점을 trigger하는 입력값(input)을 가지고 있어 실제 취약한 코드가 어디인지 살펴보기에 안성맞춤이다. 아래 예제는 client와 통신한 후 exit code가 0이 아닌 상태로 종결되었기에 서버 측에서 실제 register status를 보여주고 있다.

 

4. CWE Distribution for CGC Binaries

CWE는 MITRE (https://cwe.mitre.org/)에서 제공하는 일종의 취약점 분류(Common Weakness Enumeration)라고 볼 수 있다.  Semi-Final에서 제공한 131개의 바이너리 Description을 기반으로 살펴본 결과 다음 표와 같이 대략 60여개의 분류와 300개 이상의 취약점을 가지고 있음을 알 수 있다.

CWE NoCWE DescriptionTotal
CWE-20Improper Input Validation9
CWE-22Improper limitation of a pathname to a restricted directory1
CWE-59Improper link resolution before file access1
CWE-61UNIX symbolic link following1
CWE-119Improper Restriction of Operations within the Bounds of a Memory Buffer6
CWE-120Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')22
CWE-121Stack-based buffer overflow24
CWE-122Heap-Based Buffer Overflow29
CWE-123Write-what-where Condition1
CWE-125Out-of-bounds read13
CWE-127Buffer Under-read1
CWE-128Wrap-around Error1
CWE-129Improper Validation of Array Index14
CWE-131Improper Calculation of Buffer Size11
CWE-134Uncontrolled Format Sting7
CWE-170Improper Null Termination1
CWE-176Improper handling of unicode encoding1
CWE-190Integer overflow or wraparound16
CWE-191Integer underflow (Wrap or Wraparound)3
CWE-193Off-by-one error11
CWE-195Signed to Unsigned Conversion Error5
CWE-196Unsigned to Signed Conversion Error1
CWE-200Information Exposure1
CWE-201Information Exposure Through Sent Data1
CWE-252Unchecked Return Value1
CWE-275Permission issues1
CWE-326Inadequate Encryption Strength1
CWE-327Use of a Broken or Risky Cryptographic Function1
CWE-328Reversible One-Way Hash1
CWE-367TOCTOU Error2
CWE-369Divide by zero1
CWE-400Uncontrolled Resource Consumption1
CWE-415Double Free1
CWE-416Use After Free8
CWE-434Unrestricted upload of file with dangerous type1
CWE-457Use of uninitialized variable5
CWE-467Use of sizeof() on a Pointer Type2
CWE-469Use of Pointer Subtraction to Determine Size1
CWE-471Modification if Assumed-Immutable Data1
CWE-476Null Pointer Dereference24
CWE-665Improper Initialization1
CWE-674Uncontrolled recursion5
CWE-680Integer Overflow to Buffer Overflow2
CWE-682Incorrect calculation1
CWE-690Unchecked Return Value1
CWE-704Incorrect type conversion or cast3
CWE-755Improper Handling of Exceptional Conditions1
CWE-763Release of Invalid Pointer or Reference1
CWE-783Operator Precedence Logic Error1
CWE-785Use of Path Manipulation Function without Maximum-sized Buffer1
CWE-787Out-of-bounds Write22
CWE-788Access of Memory Location After End of Buffer6
CWE-798Use of Hard-coded Credentials1
CWE-805Buffer Access with Incorrect Length Value2
CWE-822Untrusted Pointer Dereference4
CWE-823Use of Out-of-range Pointer Offset2
CWE-824Access of Uninitialized Pointer5
CWE-825Expired Pointer Dereference1
CWE-839Numeric Range Comparison Without Minimum Check4
CWE-843Access of Resource Using Incompatible Type 'Type Confusion'5
CWE-908Use of Uninitialized Resource3

TOP 5는 짐작할 수 있듯이 Classic Buffer Overflow, Stack-based Overflow, Heap-based Overflow, Out-of-Bounds Write, Null Pointer Dereferencing이다.


cgc