연재 순서
Creative Commons License

첫번째 글: PDF 파일 구조 분석

두번째 글: PDF 취약점과 진단 방안

세번째 글: 악성 PDF 파일 진단

1. 들어가며

취약점과 진단 방안을 통해 PDF파일에서 공격에 활용될 수 있는 취약점과 악성 여부 진단 방안을 알아보았다. 이를 바탕으로 실제 악성파일의 동작방식과 사용된 취약점을 확인하고 진단과정을 적용해본다.

2. 악성 PDF 파일 진단

(1) CVE-2017-8759

CVE-2017-8759은 Microsoft .Net Framework 코드 실행 취약점으로 2017년 9월 12일에 발표되었다. 해당 취약점은은 WSDL의 부적절한 xml처리 때문에 발생한다. 공격자는 WSDL 메시지 구조 안의 address이하 부분을 Parsing하는 과정에서 발생하는 결함을 통해 사용자의 시스템에 임의의 코드를 주입할 수 있다. 주로 Microsoft Office .RTF, .Doc, .ppt 문서형태로 배포되며, 문서가 열리는 동시에 매크로 및 링크에 대한 확인 없이 공격자가 원하는 코드가 수행될 수 있는 공격이다. PDF에서는 EmbeddedFiles 작업을 통한 드롭퍼 형태의 exploit이 확인되었다.

(1)-1. 동작 방식

MD5 Hash 값이 f4a689ca564df7dce73a682047691449인 PDF파일은 취약점 CVE-2017-8759로 exploit하는 악성 PDF이다.

<그림 2-1> Object 구성과 tree구조

해당 PDF파일은 총 9개의 Object를 가지고 있으며, Root Object (Catalog Dictionary MD5 Hash 값이 f4a689ca564df7dce73a682047691449인 PDF파일은 취약점 CVE-2017-8759로 exploit하는 악성 PDF이다. data type)는 Page, Action, Filespec, Outlines Object를 참조한다.

이를 통해 Page에서 This PDF document embeds file Achi1.doc이라는 문자열이 출력되도록 하고, Action에서 PDF파일이 열렸을 때 embed되어있던 Achi1.doc악성파일이 사용자 컴퓨터로 저장되고 실행되도록 하는 JavaScript코드를 실행시킨다. Filespec에서는 Achi1.doc파일에 대해 정의하며 파일의 내용은 8 0 obj에 저장되어 있음을 알린다. 따라서 PDF파일의 역할은 embed되어있는 악성파일 Achi1.doc이 사용자 컴퓨터에 저장, 실행되도록 하는 것이다.

해당 PDF에 embed되어있던 Achi1.doc은 파일 시그니쳐 7B 5C 72 74 66({rft)를 갖는 RTF파일 이였으며, OLE control objects를 포함하고 있다.

<그림 2-2> Achi1.doc(.rtf)파일 구조

위 <그림 2-2>는 Achi1.doc파일 구조의 일부이다.

해당 부분을 통해 object type이 objocx임을 확인할 수 있다. objocx는 OLE control objects를 embed하기 위해 악성 RTF파일에서 가장 일반적인 사용되는 유형이다.

objdata부분에는 객체에 대한 데이터가 포함되어 있는데, 이 부분은 OLESaveToStream함수에 의해 구조가 생성되기 때문에 OLE포맷과 동일한 구조를 가지게 된다.

<그림 2-3> Achi1.doc(.rtf)파일 object data부분

object data 안의 문자열 중에는 wsdl=https://a.doko.moe/qvomoe/qvomoa을 확인 할 수 있다. wsdl은 웹 서비스와 웹 접근 방법에 대해 기술하는 xml 기반으로 정의된 파일이며, soap이라는 xml기반의 프로토콜을 통해 통신 된다.

위 그림의 경우 http://a.doko.moe/qvome/qvomoa에 접근하게 된다.

외부 통신이 수행되면 프로세스의 흐름상 접근된 qvomoa는 WSDL로서 기술된 XML파일일 것이며 아래 <그림 2-4>과 같은 구문을 사용하여 공격이 수행될 것이다.

<그림 2-4> Exploit WSDL 파일 예시

Microsoft의 .Net Framework에서는 XML파일의 soap:address 문자열 이후의 url정보를 parsing하여 System.Runtime.Remoting.metadata.wsdlparser.cs에 정의된 PrintClientProxy 함수 안에서 사용하게 되는데, parsing 과정에서 CRLF문자 ;을 필터링 하지 못해 함수 내의 주석처리를 우회하게 되며 이 후 등장하는 C#코드가 정상 수행되도록 만든다. 공격자가 이 부분에 악성 코드를 주입하면 해당 코드는 .Net Framework의 csc.exe에 의해 컴파일 되고 생성된 파일은 은 Office에 의해 DLL로 호출되어 실행된다.

(1)-2. 진단 과정

PDF파일에서는 악성 행위 수행을 위해 위험한 작업(Action) 중 하나인 EmbeddedFiles가 수행되었으며, 파일의 실행 방법으로 JavaScript문이 이용되었다.

작업을 호출한 경로는, EmbeddedFiles의 경우 Root object의 Dictionary Key인 Names의 Value값으로써 호출되었고, JavaScript의 경우 Root object의 Dictionary Key인 Action(OpenAction)의 Value값으로 호출되었다.

<그림 2-5> EmbeddedFiles, JavaScript 호출 Object

취약한 작업의 호출이 확인되었기 때문에 작업에 포함된 내용을 확인하여 악성 여부를 진단해야 한다. JavaScript의 내용을 확인하기 위해서 Object 9번으로 이동하면 <그림 2-5>와 같은 내용을 볼 수 있는데, 주의해서 봐야 할 부분은 함수 명 exportDataObject와 그 파라미터 값인 nLaunch이다. exportDataObject함수는 지정된 데이터를 외부파일로 추출하는 역할을 한다. 이때 주어지는 nLaunch에 값에 따라 추출 후 수행할 작업이 달라진다.

<표 2-1> exportDataObject함수의 nLaunch 파라미터

공격자들은 nLaunch의 파라미터 값으로 2번을 주로 사용하는데, 이유는 파일을 사용자가 알지 못하는 경로에 은밀하게 저장할 수 있기 때문이다.

그 다음으로는 추출되는 파일의 악성여부를 확인해야 한다.

EmbeddedFiles의 내용을 확인하기 위해 Object 1번으로 이동하면 <그림 2-5>와 같은 내용을 볼 수 있다. 이를 통해 PDF에 포함되어 있는 문서가 Achi1.doc이라는 것과 Achi1.doc에 대한 내용은 Objcet 7번을 참조한다는 것을 알 수 있다. <표 2-1>의 tree구조를 통해 알 수 있듯이, Object 7번은 Object 8번을 참조함으로써 파일의 Stream정보를 나타낸다. 따라서 Object 8번의 Stream을 Dump하면 악성 파일이 나올 것이라 예상할 수 있다.

<그림 2-6> Object 8번의 Stream

Object 8번에 포함된 Stream은 FlateDecode 필터로 압축 되어있으며 8346바이트 길이를 갖는다. HxD프로그램을 통해 Stream 부분만 Dump하여 파일로 만든 다음, FlateDecode 필터 압축에 대한 uncompress를 수행하면 embed 되어있던 파일을 얻을 수 있다. 찾은 파일을 virustotal과 같은 바이러스 검색 엔진에 업로드 함으로써 악성여부를 1차 판단한다.

우선 uncompress되지 않은 파일을 Virustotal에서 검사해본 결과 <그림 2-6>의 왼쪽 그림과 같이 낮은 탐지율을 보인다. 그러나 파일을 uncompress하여 다시 검사하면 <그림 2-6>의 오른쪽 결과와 같이 탐지된다.

<그림 2-7> export될 파일의 Virustotal 검사 결과 (압축 / 비압축)

이를 통해 악성 파일인 Achi1.doc은 압축되어 PDF에 embed되는 과정에서 많은 바이러스 검사 엔진들로부터 탐지를 회피할 수 있었으나, 단순히 원문형태로 변환하는 과정을 통해서도 진단이 가능함을 확인할 수 있다.

PDF가 embed하고 있는 파일을 추출하였다면, 파일 시그니쳐를 확인하여 포맷을 확인해야 하고 문자열 soap:wsdl=(url)의 유무를 확인 해야한다.

공격자는 XML언어로 기술된 WSDL메시지 구조를 soap프로토콜로 통신할 것이기 때문이다.

접근하려는 서버와 통신할 메시지를 확인하면 sandbox환경에서 서버와 통신하여 파일에 접근한 후 문서 내의 soap:address location =”; 문자열의 등장 여부를 확인하여 악성여부를 판단한다.

(2) DB0C822D49A1DBFF0E760D6E7E111370

(2)-1. 동작 방식

MD5 Hash 값이 db0c822d49a1dbff0e760d6e7e111370인 악성 PDF이다.

파일을 HxD나 vim에디터로 열어보면 구조가 손상되어 있는 것을 확인할 수 있다.

<그림 2-8> db0c822d49a1dbff0e760d6e7e111370 손상된 파일 구조

위 <그림 2-8>은 Offset 00000000 ~ 0000026까지 나타낸 것이다.

xref table을 통해 확인되는 Object의 offset주소는 실제와 달랐으며, 증분 업데이트 이전의 내용 또한 xref table에서 확인할 수 있는 Object들이 실제 Body부분에 포함되지 않아 손상된 구조임을 확인할 수 있었다.

Root Object(15 0 obj)의 참조 Object 중, 주의해서 봐야 할 Object로는 /AA (12 0 object), /AcroForm (16 0 object), /Names (17 0 object), /Pages (4 0 object), /Metadata(10 0 object)가 있으며 이중 취약점은 /Names에서 찾을 수 있었다.

/Names는 객체가 아닌 이름을 통한 참조 시 이름과 객체간의 대응(mapping)에 사용되는 Object이다. Dictionary를 이루는 Key들은 특정 범주의 개체에 대한 이름을 정의하는 name tree의 루트를 지정한다. 해당 파일에서 Names Object는 IDS(5 0 object)와 JavaScript(18 0 object), URLS(6 0 object)라는 이름의 Key를 가지고 있으며 파일이 열리면 해당 root name tree부터(Key) 모든 작업이 실행된다.

<그림 2-9> Names

IDS는 디지털 식별자와 Web Capture Content Set을 Mapping하는 name tree이고, URLS는 Web Capture Content Set와 URL을 Mapping하는 name tree이며 JavaScript는 이름(문자열)과 문서 수준의 JavaScript를 Mapping하기 위한 name tree이다. Web Capture Content Set이란 동일 Source Data로부터 생성된 Object의 세트를 말하며 여기에는 세트 자체 혹은 Object 들의 공통된 정보를 포함한다. Web Capture Contest에는 2가지 Subtype이 있는데 Page유형과 Image유형이다. Page유형의 경우 SPS (Spider Page Set)로 표현되고 Image유형의 경우 SIS (Spider Image Set)로 표현된다. 분석중인 PDF는 SPS유형의 Web Capture Content Set로 URLS(6 0 object)를 통해 Web Capture Content Set(8 0 object)와 url정보를(7 0 object)를 Mapping하고, IDS를 통해 Web Capture Content Set와 디지털 식별자를(27 0 object) Mapping하여 Page Set이룬다. 해당 Page Set 참조하여 Page(20 0)가 작성된다.

<그림 2-10> Web Capture File 구조 (SPS)

JavaScript name tree는 18 0 object, 19 0 object를 참조하여 정의된다.

stream은 19 0 object에서 참조함으로 해당 object의 Dictionary Key인 JS의 value값을 Dump하여 확인할 수 있다.

아래 <그림 2-11>는 Dump된 JavaScript 코드를 재정렬 한 것이다.

<그림 2-11> JavaScript

악성코드는 변수 a에 encoding되어 있다. decoding 알고리즘은 다음과 같다.

1)	변수 a 중간에 들어가는 변수 zxc에 대해 문자 a로 대체한다.
2)	변수 a의 문자열을 2자리씩 끊고, 31진수 숫자로 읽는다.
3)	31진수를 10진수로 변환한다. <br>
4)	변환한 값을 Ascii코드 번호로 읽는다.

decoding된 알고리즘은 <그림 2-12>와 같다.

<그림 2-12> eval()함수에 들어가는 문자열

해당 코드는 CVE-2009-0927, CVE-2007-5659, CVE-2008-2992 취약점 공격코드를 포함하고 있으며 heap spray공격을 수행한 후 Reader의 버전을 체크하고 버전별로 exploit코드를 다르게 실행한다. CVE-2009-0927취약점 공격코드는 Collab.getIcon() 함수를 이용하며, 해당 함수는 N.다음으로 등장하는 문자열(확장자)를 strcat을 통해 복사하는데 이때 strcat함수가 문자열의 끝을 계산하지 않고 넘어온 값을 다 전달하기 때문에 overflow를 발생시키고 결과적으로 eip값이 변경되어 공격이 수행된다.

CVE-2007-5659 취약점 코드는 Collab.collectEmailInfo() 함수를 이용한 공격으로, 공격자가 해당 함수의 두 번째 인자로써 대량의 0x0c0c0c0c 값을 갖는 msg를 넣는다. 함수는 이 인자의 boundary를 확인하지 않고 받아들인 뒤 해당 인자가 담긴 메모리 주소 범위에서 일정크기의 값을 가져와 비교하는 알고리즘을 수행한다. 참 인 결과 또는 끝나는 조건을 만족하지 못한 비교 알고리즘은 계속 반복되며 0x0c0c값을 스택에 채우게 되고 overflow를 발생시킨다.

CVE-2008-2992 취약점 코드는 util.prinf() 함수에서 부동 소수점 지정자를 포함하는 포맷 스트링을 파싱할 때 boundary error가 발생할 수 있다는 점을 이용하며, 이를 통해 버퍼 overflow를 발생시킨다.

(2)-2. 동작 방식

악성파일 db0c822d49a1dbff0e760d6e7e111370의 경우 Root Object의 Entry인 Names Object로부터 문서 수준의 JavaScript를 참조하여 실행 시킴으로써 악성행위를 수행하였다. Names Object의 Entry로부터 JavaScript 이름을 갖는 root name tree를 찾았고(18 0 object), 그 아래의 19 0 object name tree를 찾아 코드를 확인하였다.

코드는 19 0 object에서 Dictionary Key인 JS의 Value값으로 들어있기 때문에 해당 영역을 dump하였으며. 그 내용은 <그림 2-11>와 같다.

실질적인 악성코드 부분은 변수 a에 encoding되어 decoding하기 이전 까지는 내용확인이 어렵기 때문에 진단은 <그림 2-11>에 해당하는 코드에서 수행되어야 한다.

하지만 취약점이 동작하는 부분을 직접 확인할 수 없는 상태에서 진단이 수행되어야 하며, 확실한 악성 탐지는 수행되기 어렵다.

때문에 악성 의심 수준으로 진단될 수 있으며, JavaScript코드 진단 결과가 악성을 의심할 수 있는 조건을 연속적으로 부합할 경우 사용자에게 악성 의심 경고를 알리도록 한다. 악성의심으로 판단할 조건은 다음과 같다.

1)	변수가 비정상적인 크기의 문자열을 가질 경우
2)	반복문안에 fromCharCode등 문자, 문자열 생성이나 Decoding 관련 함수가 등장할 경우
3)	eval함수가 사용되는 경우

다음 조건이 2개이상 일치 될 경우 높은 확률로 악성코드로 의심할 수 있다.

위와 같은 조건을 둔 이유는 정상 PDF내 JavaScript의 용도상 encoding 난독화를 수행할 필요성이 적고 decoding 된 문자열이 eval함수를 통해 JavaScript로써 실행되는 경우가 거의 없기 때문이다.

3. 마무리

지금까지 2종류의 악성 PDF 파일의 동작 방식과 진단하는 방법에 대해 살펴보았다. PDF 파일은 포맷 구조가 복잡하고 다양한 encoding으로 구성되어 있어 탐지 로직을 개발하는 것은 매우 까다롭다. 하지만, PDF 파일 포맷 파서와 다양한 encoding을 decoding하는 로직만 갖출 수만 있다면 악성 PDF 파일에 대한 탐지는 가능하다. 이는 향후 누리랩에서 개발하는 PDFScan을 통해 그 유용성 및 사용법에 대해서도 블로그에 새롭게 정리하도록 하겠다.

크리에이티브 커먼즈 라이선스
Creative Commons License
이 저작물은 크리에이티브 커먼즈 저작자표시-비영리-변경금지 4.0 국제 라이선스에 따라 이용할 수 있습니다.
Hyeok-Jae Lee's profile image

Hyeok-Jae Lee

2021-05-31 09:00

Read more posts by this author