seculetter exploitanalysis cve-2018-4878 ver0 · 2020. 7. 7. · microsoft word -...

15
Use-After-Free in Adobe Flash Player CVE-2018-4878 2018. 04. 09 시큐레터 주식회사

Upload: others

Post on 18-Aug-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: SecuLetter ExploitAnalysis CVE-2018-4878 Ver0 · 2020. 7. 7. · Microsoft Word - SecuLetter_ExploitAnalysis_CVE-2018-4878_Ver0.1 Author: jen19 Created Date: 4/9/2018 2:57:06 PM

Use-After-Free in Adobe Flash Player

CVE-2018-4878

2018. 04. 09

시큐레터 주식회사

Page 2: SecuLetter ExploitAnalysis CVE-2018-4878 Ver0 · 2020. 7. 7. · Microsoft Word - SecuLetter_ExploitAnalysis_CVE-2018-4878_Ver0.1 Author: jen19 Created Date: 4/9/2018 2:57:06 PM

01 개요

지난 2018년 1월 31일 KrCERT/CC 는 Adobe 플래시 플레이어의 제로데이 취약점을 악용한 악성코드 유포와 관련

하여 보안 공지를 발표했습니다. 해당 취약점은 플래시 플레이어 28.0.0.161 버전과 이전 버전에 발생하는 Use-

After-Free 취약점으로 Primetime SDK의 미디어 플레이어 DrmManager 관련 메소드가 리스너 객체를 처리하는 과

정에서 Dangling Pointer가 만들어 집니다. 공격자는 Dangling Pointer를 이용하여 임의의 메모리에 접근하여 데이터

를 변조할 수 있습니다.

CVE Reference

CVE-2018-4878

Ref1. https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-4878

취약점 발생 모듈

Flash32_28_0_0_137.ocx (Flash Player Version 28.0.0.137)

취약점 발생 버전

Adobe Systems Flash Player Desktop Runtime 28.0.0.137버전과 이전 버전

Adobe Systems Flash Player for Google Chrome 28.0.0.137버전과 이전 버전

Adobe Systems Flash Player for Microsoft Edge and Internet Explorer 11 28.0.0.137버전과 이전 버전

취약점이 발생하는 메소드

DRM Manager 객체의 acquireLicense(), acquirePreviewLicense(), authenticate(), createMetadataFromBytes(),

initialize(), joinLicenseDomain(), leaveLicenseDomain(), returnLicense(), setAuthenticationToken(), storeLicenseBytes()

메소드

취약점이 발생하는 파라미터

취약점이 발생하는 메소드의 “listener” 파라미터

02 Exploit 동작 원리 상세 분석

분석 환경

Windwos 7 32Bit

Adobe Systems Flash Player Desktop Runtime 28.0.0.137

Page 3: SecuLetter ExploitAnalysis CVE-2018-4878 Ver0 · 2020. 7. 7. · Microsoft Word - SecuLetter_ExploitAnalysis_CVE-2018-4878_Ver0.1 Author: jen19 Created Date: 4/9/2018 2:57:06 PM

취약점 발생 원인

DRM Manager의 취약한 메서드는 리스너로 전달받은 객체를 처리하는 과정에서 전달받은 주소에 대해서 메모리

해제 여부를 검증하지 않고 해당 위치에 있는 다른 객체가 해제(삭제)되며 Danglin Pointer를 만들어 Use-After-Free

취약점을 발생시킵니다.

취약점 상세 분석

그림. 1 분석 샘플 액션 스크립트 구조 및 메인 스크립트

위 그림은 본 문서에 사용한 샘플 PoC 파일입니다. BinaryData에 있는 데이터는 계산기를 실행하기 위한 쉘코드 데

이터를 갖고 있습니다. MainExp는 먼저 실행하는 메인 스크립트로 ByteArray 타입의 변수 data14에 계산기를 실행

하는 ShellcodByte 데이터의 주소를 저장합니다. UAFGenerator 메소드를 실행하여 CVE-2018-4878 취약점을 동작

시킵니다.

Use-After-Free 취약점이 발생하는 과정

Page 4: SecuLetter ExploitAnalysis CVE-2018-4878 Ver0 · 2020. 7. 7. · Microsoft Word - SecuLetter_ExploitAnalysis_CVE-2018-4878_Ver0.1 Author: jen19 Created Date: 4/9/2018 2:57:06 PM

그림. 2 Use-After-Free 취약점 동작 과정

Use-After-Free 취약점이 발생하는 과정의 순서를 살펴보겠습니다. 취약점 동작에 주요한 스크립트 코드의 실행 순

서로 정리했습니다. 분석은 위 흐름으로 진행하도록 하겠습니다.

Page 5: SecuLetter ExploitAnalysis CVE-2018-4878 Ver0 · 2020. 7. 7. · Microsoft Word - SecuLetter_ExploitAnalysis_CVE-2018-4878_Ver0.1 Author: jen19 Created Date: 4/9/2018 2:57:06 PM

그림. 3 UAFGernerator 스크립트 구조

Ues-After-Free 취약점을 발생시키는 UAFGenerator 함수는 크게 세 부분으로 이해할 수 있습니다. UAF 취약점을 일

으키기 위해 DRM Manager의 취약한 메소드를 실행하는 method_2()와 강제적으로 가비지 콜렉터를 실행하고

Dangling Pointer를 만드는 Try Catch 구문 그리고 UAF 취약점이 제대로 동작했는가를 체크하고 Dangling Pointer를

이용해서 데이터를 변조하는 부분입니다.

그림. 4 취약점 동작시키는 method_2 메소드

method_2()의 기능은 리스너 객체를 매개변수로하는 DrmManager의 취약한 함수를 호출하고 리스너로 지정한 객

체를 가리키는 포인터를 해제합니다. 주요 코드는 아래와 같습니다.

55: 리스너로 사용할 DRM_obj() 객체 인스턴스를 만들고 변수로 선언한 var_16에 인스턴스 주소를 저장합니다.

56: MediaPlayer 객체의 drmManager.initialize 메소드를 호출하는데 변수 var_16을 리스너로 지정합니다.

57: var_16(DRM_obj 객체의 주소)을 Null로 저장하면서 var_16을 free (객체 해제)한 효과를 발생합니다.

Page 6: SecuLetter ExploitAnalysis CVE-2018-4878 Ver0 · 2020. 7. 7. · Microsoft Word - SecuLetter_ExploitAnalysis_CVE-2018-4878_Ver0.1 Author: jen19 Created Date: 4/9/2018 2:57:06 PM

그림. 5 DRM_obj 객체 클래스

위 과정에서 변수 var_16에 저장되는 DRM_obj 객체의 클래스는 위 그림과 같이 Unsigned Int 타입의 데이터를 배

열 인덱스에 담고 있습니다.

method_2는 var_16을 drmManager.initialize 메소드의 리스너로 지정하고 다음 명령으로 var_16이 null로 초기화

됩니다. 이때 리스너 객체는 메모리에 남아 있고 리스너 객체를 가리키는 포인터인 var_16만 삭제됩니다.

그림. 6 DRM_obj 객체 인스턴스가 저장 될 주소 지정

this.var_16에 DRM_obj 객체를 저장하기 위해 먼저 DRM_obj() 메소드를 호출하여 객체를 인스턴스화합니다. 이때

스택에 저장된 인자값을 확인하면 인스턴스가 저장될 주소가 저장되어 있는 것을 확인할 수 있습니다.

그림. 7 저장된 DRM_obj 객체 데이터

Page 7: SecuLetter ExploitAnalysis CVE-2018-4878 Ver0 · 2020. 7. 7. · Microsoft Word - SecuLetter_ExploitAnalysis_CVE-2018-4878_Ver0.1 Author: jen19 Created Date: 4/9/2018 2:57:06 PM

지정된 주소를 확인해보면 DRM_obj() 객체의 인스턴스가 위 그림과 같이 메모리에 저장되어 있는 것을 확인할 수

있습니다.

그림. 8 DRM_obj 객체 인스턴스를 가리키는 주소 지정

이후 this .var_16 변수(0x07AC2174 번지)에 DRM_obj객체의 인스턴스 주소(0x07A6E100)를 저장합니다.

그림. 9 var_16에 저장된 DRM_obj 객체 인스턴스 주소

위 그림과 같이 this.var_16 변수에 인스턴스를 가리키는 포인터가 저장되는 것을 확인할 수 있습니다.

그림. 10 DrmManager객체의 취약한 메소드 호출

다음으로 DrmManager의 취약한 매소드(분석 대상 샘플은 initialize 메소드)를 호출하는데 전달되는 매개변수를 살

펴보면 var_16의 주소(객체 인스턴스를 가리키는 포인터)를 전달하는 것이 아닌 인스턴스화 된 객채의 주소를 전달

합니다.

Page 8: SecuLetter ExploitAnalysis CVE-2018-4878 Ver0 · 2020. 7. 7. · Microsoft Word - SecuLetter_ExploitAnalysis_CVE-2018-4878_Ver0.1 Author: jen19 Created Date: 4/9/2018 2:57:06 PM

그림. 11 DRM_obj 객체 인스턴스를 지정하는 리스너와 var_16

위 그림과 같이 하나의 객체를 가리키는 포인터를 매개변수로 하여 리스너 객체가 포인터를 가리키는 것이 아닌 리

스너 객체 자체를 매개변수로하여 취약한 메소드를 실행합니다.

그림. 12 var_16 해제

다음 명령을 통해 var_16변수에 저장된 DRM_obj 인스턴스의 주소를 삭제합니다. 여기서는 객체의 포인터인

var_16만 삭제하기 때문에 인스턴스화 된 객체는 메모리에 남아있습니다.

그림. 13 삭제된 DRM_obj 객체

Page 9: SecuLetter ExploitAnalysis CVE-2018-4878 Ver0 · 2020. 7. 7. · Microsoft Word - SecuLetter_ExploitAnalysis_CVE-2018-4878_Ver0.1 Author: jen19 Created Date: 4/9/2018 2:57:06 PM

사라진 var_16 변수가 가리키는 객체 인스턴스를 삭제하기 위해 강제로 가비지 콜렉터 동작시킵니다. 가비지 콜렉

터는 개발자가 의도해서 실행하는 것이 아닌 메모리 관리를 위해 AVM2(Actionscript Virtual Machine)에서 실행합니

다. 하지만 여기서 사용된 Try Catch 코드는 비공식적으로 가비지 콜렉터를 강제로 동작 시킬 수 있습니다.

강제로 가비지 콜렉터가 동작하면 DM_obj 객체 인스턴스 데이터를 삭제합니다. 이제 DrmManager.initialize() 메소

드의 매개변수로 사용한 리스너가 가리키는 위치는 어떤 데이터도 없는 빈공간을 가리키게 됩니다

그림. 14 새로 생성된 var_13

이후 catch문으로 인해 var_13변수에 DRM_obj()객체의 인스턴스 주소가 저장됩니다. 여기서 인스턴스 주소는 기존

의 var_16과 동일한 주소에 저장됩니다. 여기서 var_16의 위치와 var_13은 다른 위치에 객체 인스턴스의 주소를 저

장합니다. var_16의 위치는 0x07AC2174였고 var_13의 위치는 0x07AC217C입니다.

그림. 15 var_16과 동일한 위치에 생성된 var_13 DRM_obj 객체 인스턴스

위 그림과 같이 DrmManager.Initialize()메소드의 리스너 객체로 지정된 메모리에 동일한 DRM_obj 객체가 저장되어

있습니다.

Page 10: SecuLetter ExploitAnalysis CVE-2018-4878 Ver0 · 2020. 7. 7. · Microsoft Word - SecuLetter_ExploitAnalysis_CVE-2018-4878_Ver0.1 Author: jen19 Created Date: 4/9/2018 2:57:06 PM

그림. 16 onDRMError 메소드 호출

DrmManager.Initialize()메소드의 실행 결과 미디어의 DRM 정보를 확인할 수 없기 때문에 DRMError 이벤트를 처리

하며 DrmManager.Initialize() 메소드에 지정한 리스너 객체를 해제합니다. 위 그림에서 onDRMError 메소드 호출 시

스택에 저장된 인자 값에 리스너로 지정한 주소인 0x07A6E100 번지가 저장되어 있습니다.

그림. 17 onDRMError 메소드 호출 이후 해제(삭제)된 DRM_obj 객체

onDRMError 메소드가 실행되면 var_13이 가리키는 메모리의 객체 데이터가 삭제되는 것을 확인할 수 있습니다. 하

지만 변수 var_13(0x07AC217C)은 아래 그림과 같이 여전히 남아 있는 것을 확인할 수 있습니다.

그림. 18 this 포인터에 남아 있는 var_13 포인터

메모리 관리자는 효율적인 메모리 관리를 위해 이전에 사용했던 메모리 공간 크기와 같거나 조금 작은 데이터를 저

장해야 하는 경우 기존의 메모리를 재 사용하는 경향(메모리 재할당)이 있습니다. 하지만 데이터가 있거나 참조하는

포인터가 있는 경우 다른 메모리 공간을 찾아 데이터를 할당합니다.

이번 취약점은 먼저 생성된 DRM_obj 객체 인스턴스의 포인터를 Null로 지정하여 객체를 해제한 효과를 발생시키고

강제로 가비지콜렉터를 호출하여 해제된 객체를 삭제합니다. 동일한 크기의 객체를 인스턴스화 하는 과정에서 기존

의 메모리 주소에 동일한 주소에 객체 인스턴스가 저장되고 var_13이 이를 가리킵니다. DRMError Event 이후 리스

너로 지정된 메모리 영역을 해제하고 삭제하는 과정에서 Var_13이 가리키는 객체 데이터가 삭제되어 var_13이

Dangling Pointer가 됩니다.

결과적으로 변수 var_13(DRM_obj 객체를 가리키는 주소)은 남아 있지만 해당 위치의 객체는 해제되고 해당 주소에

Page 11: SecuLetter ExploitAnalysis CVE-2018-4878 Ver0 · 2020. 7. 7. · Microsoft Word - SecuLetter_ExploitAnalysis_CVE-2018-4878_Ver0.1 Author: jen19 Created Date: 4/9/2018 2:57:06 PM

는 다른 데이터가 저장될 수 있습니다. 때문에 저장된 데이터를 var_13 포인터로 접근하여 보안 검사를 우회하여 데

이터를 변조할 수 있는 환경이 만들어 집니다.

이후 Timer EventListener 를 이용해서 Tiem Event를 발생시켜 method_1을 호출합니다. method_1은 위 그림과 같

이 Dangling Pointer인 var_13의 첫번째 배열인 a1에 저장된 값을 비교하여 기존의 데이터와 다른 경우 다음 단계로

넘어가도록 설계되있습니다. 다음 단계는 flash25 메소드에서 실행됩니다

그림. 19 메모리 변조를 위한 flash25 메소드

flash25 메소드의 코드는 위와 같습니다. 복잡해 보기는 코드지만 핵심 기능은 ByteArray 타입의 Mem_Arr 객체 인

스턴스를 생성하고 인스턴스의 주소를 var_17에 저장합니다. 이때 Mem_Arr 객체를 지정하는 주소는 기존의

var_13이 가리키는 주소인 0x07A6E100 번지입니다. 때문에 변수 var_13으로 var_17에 저장된 인스턴스 데이터를

변조할 수 있습니다.

정상적인 과정으로 ByteArray의 속성을 변경하는 경우 적절한 검사를 통해서 비 정상적인 값을 필터링하지만 지금

은 Dangling Pointer 인 var_13으로 접근하여 직접적으로 값을 변조할 수 있습니다. ByteArray의 m_buffer 구조체의

의 주소와 배열의 시작주소를 0x00000000으로 배열의 길이를 0xFFFFFFFF 로 변경하여 프로세스 메모리 전체에 접

근할 수 있게 됩니다. 메모리 접근 권한을 변경하면 Primit.flash20() 메소드를 호출하며 다음 단계를 진행합니다.

Page 12: SecuLetter ExploitAnalysis CVE-2018-4878 Ver0 · 2020. 7. 7. · Microsoft Word - SecuLetter_ExploitAnalysis_CVE-2018-4878_Ver0.1 Author: jen19 Created Date: 4/9/2018 2:57:06 PM

그림. 20 변수 var_17에 저장하는 Mem_Arr 객체 인스턴스의 주소

ByteArray 타입의 Mem_Arr 객체를 인스턴스화 하여 메모리에 저장하고 이를 가리키는 포인터를

this .var_17(0x7AC2180) 변수에 저장합니다.

그림. 21 this 포인터에 저장된 var_13과 var_17

this 포인터에 저장된 같은 위치를 가리키는 포인터가 두개 있는 것을 확인할 수 있습니다. 이로 인하여 var_17이 가

리키는 Mem_Arr 객체를 Var_13 포인터로 직접 변조할 수 있습니다.

그림. 22 메모리에 저장된 Mem_Arr 객체 인스턴스

저장된 Mem_Arr 객체 데이터를 살펴보면 위와 같습니다. 이렇게 Mem_Arr 객체를 인스턴스화 하고 나면 var_17

에 Mem_Arr의 인스턴스 주소를 정합니다.

Page 13: SecuLetter ExploitAnalysis CVE-2018-4878 Ver0 · 2020. 7. 7. · Microsoft Word - SecuLetter_ExploitAnalysis_CVE-2018-4878_Ver0.1 Author: jen19 Created Date: 4/9/2018 2:57:06 PM

그림. 23 메모리에 저장되는 Mem_Arr 클래스

실제 Mem_Arr 클래스는 위 그림과 같습니다. ByteArray 타입으로 각 배열 인덱스에 Unsinged int 데이터를 갖고 있

습니다. a1부터 a11 은 뒤에서 사용할 m_buffer 구조체 데이터를 담기 위한 공간을 확보하는 역할을 수행합니다.

그림. 24 var_13을 이용한 Mem_Arr 객체 인스턴스 정보 변경

위 코드에서 var_13.a14 속성의 값을 변경합니다. 변경하는 값은 Mem_Arr 객체의 m_buffer 구조체의 주소를 가리

키고 있습니다. ByteArray 클래스에서 m_buffer는 배열의 시작 주소와 길이와 같은 정보를 갖고 있는 구조체입니다.

그림. 25 Mem_Arr의 m_buffer 포인터가 지정된 위치의 m_buffer 구조체

변경 전의 Mem_Arr 객체의 데이터는 위 그림과 같이 메모리의 어떤 주소를 가리키고 그 곳에 m_buffer 구조체 정

보가 저장되어 있는 것을 확인할 수 있습니다.

Page 14: SecuLetter ExploitAnalysis CVE-2018-4878 Ver0 · 2020. 7. 7. · Microsoft Word - SecuLetter_ExploitAnalysis_CVE-2018-4878_Ver0.1 Author: jen19 Created Date: 4/9/2018 2:57:06 PM

그림. 26 m_buffer 구조체 포인터 변경

변경된 데이터는 m_buffer 구조체에 대한 포인터로 이후 지정한 m_buffer 주소에 구조체 데이터를 저장합니다.

그림. 27 var_13을 이용한 m_buffer 구조체 데이터 변경

var_13 포인터를 이용해 Mem_Arr객체에 접근하여 m_buffer 구조체를 직접 변경합니다. 이때 속성에 값을 대입하

는 과정에서 적절성 여부를 검사하지만 Dangling Pointer를 이용하여 메모리에 직접적으로 값을 대입한는 경우 적절

성 여부에 대한 검사를 하지 않습니다.

그림. 28 변경된 m_buffer 구조체 데이터

외 그림과 같이 Dangling Pointer인 var_13을 이용해 Mem_Arr의 m_buffer 구조체 값을 변경합니다.

Page 15: SecuLetter ExploitAnalysis CVE-2018-4878 Ver0 · 2020. 7. 7. · Microsoft Word - SecuLetter_ExploitAnalysis_CVE-2018-4878_Ver0.1 Author: jen19 Created Date: 4/9/2018 2:57:06 PM

그림. 29 ByteArray 클래스의 m_buffer 구조체

ByteArray의 m_buffer 구조체를 변조하여 배열의 시작 주소를 0x00000000으로 하고 길이를 0xFFFFFFFF로 변조하

여 프로세스의 전체 메모리에 접근가능한 R/W 권한을 얻을 수 있습니다 이를 이용하면 ASLR과 DEP를 우회할 수

있으며 메모리에 로드되어 있는 쉘코드를 찾아 실행시킬 수 있습니다. 분석 샘플은 쉘코드 객체 인스턴스를 찾아 이

를 실행하기 위해 VirtualProtect 함수를 호출하여 메모리에 실행권한을 부여하고 쉘코드를 실행합니다.

03 결론

본 문서의 분석 샘플은 미디어의 저작권 정보 관련해서 사용하는 DrmManager 관련 메소드의 취약점으로 Use-

After-Free 취약점을 동작시켜 Dangling Pointer를 만듭니다. 이를 통해 ByteArray의 m_buffer 구조체의 배열 시작

주소와 길이를 변조하여 프로세스 전체 메모리에 대한 R/W 접근권한을 얻어와 프로세스의 실행 흐름을 제어할 수

있었습니다. 이후 메모리에 로드될 쉘코드 객체를 찾아 객체 메모리에 실행권한을 부여하고 쉘코드를 실행합니다.

공격자는 취약점으로 만들어진 Dangling Pointer를 이용하여 다양한 방식으로 원하는 코드를 실행할 수 있습니다.

브라우저는 보안상의 문제로 인해 애플을 비롯하여 구글, MS IE, Edge에 이르기 까지 기본 설정으로 플래시 플레이

어를 사용하지 않도록 했습니다. 하지만 SWF 파일은 문서 파일에 포함되어 사용자에 의해 실행될 수 있습니다. 문

서 파일은 브라우저에 비해 실행에 제약이 많이 않기 때문에 보다 쉽게 악성코드를 실행시킬 수 있습니다.