[1-day] VirtualBox 3D Acceleration 배경지식

2021. 3. 13. 16:360x0F 1-Day

728x90

오늘 살펴 타깃의 버전은 VirtualBox v.6.0.0이다.

연구하게 취약점은 2가지이다. CVE-2019-2525 그리고, CVE-2019-2548이다. VirtualBox 대한 지식이 전무하므로, 연구하며 궁금했던 사항을 공부한 것에 대해서도 간략히 기술되어 있다. 익스플로잇 연구가 아닌 VirtualBox 내부 연구 목적의 경우, github 코드를 이용하였음을 미리 언급한다.

 

바이너리에서 취약점을 찾 때, 진행해야하는 작업 memory leak 과정이다. 이 연구 CVE-2019-2525 이용되었다.

 

그렇다면, 과연 CVE-2019-2525는 어떤 특성을 가지고 있던 취약점이었을까?

우선, 공개 된 정보를 기반으로 어떻게 접근 해야할지 생각해보았다.

하기의 내용에 따르면, VirtualBox 버전 5.2.24 <= x <= 6.0.2까지 해당 벡터가 활성화 되게 되며, 공격에 성공하면, 승인되지 않은 공간으로의 접근이 가능한 취약점이라고 한다. CVSS 점수로 공격을 판단하면 다음과 같다.

 

로컬에서만 공격이 가능한 취약점이며, 공격하기에 비교적 까다로우나, 약간의 권한은 필요한 작업이며, 유저의 별다른 관여가 필요 없는 작업이며, 승인되지 않은 공간으로의 접근이 가능함은 특정 메모리값을 열람가능하다는 말도 성립되므로 scope에서는 점수를 얻을 수 있고, 컴포넌트들에 영향을 미칠 수 있기에 Confidentiality에서는 높은 점수를 얻었다.

Vulnerability in the Oracle VM VirtualBox component of Oracle Virtualization (subcomponent: Core). Supported versions that are affected are prior to 5.2.24 and prior to 6.0.2. Difficult to exploit vulnerability allows low privileged attacker with logon to the infrastructure where Oracle VM VirtualBox executes to compromise Oracle VM VirtualBox. While the vulnerability is in Oracle VM VirtualBox, attacks may significantly impact additional products. Successful attacks of this vulnerability can result in unauthorized access to critical data or complete access to all Oracle VM VirtualBox accessible data. CVSS 3.0 Base Score 5.6 (Confidentiality impacts). CVSS Vector: (CVSS:3.0/AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N).

 

CVE에 대한 간략 정보를 통해 해당 취약점이 의미하는 바는 파악 하였으니, 본격적으로 VirtualBox 어디 부분에서 해당 취약점이 이용 될 수 있는지 살펴보자.

 

해당 취약점은 3D 가속화 설정이 enable 상태 일 때, 트리거 된다는 사실을 알게되었다.

그러므로, VirtualBox 세팅 시 3D Acceleration 옵션을 enabled 상태로 설정하였다. 

Virtual box settings -> Display -> Screen -> Enable 3D Acceleration

 

아래의 사진은 취약점을 찾은 발표자가 언급해준 내용이다.

 

즉, 해당 취약점을 이해하기 위해서는 VBoxSharedCrOpenGL, HGCM Protocol 그리고 svcCall에 대한 이해가 필요하다.

 

1.VBoxSharedcrOpenGL

 

My host Path

·      …/virtualBox-6.0.0/out/linux.amd64/release/bin/

·      …/virtualBox-6.0.0/out/linux.amd64/release/obj

 

VBoxSharedcrOpenGL의 기능은 무엇인가?

VirtualBox github repo의 경로명을 통해 우선 유추해보았다.

 

경로명에 따르면, VBox는 HostService comunication을 위해 contract되어 지는 서비스들이 존재한다. 다음은 HostService에서 사용되는 모듈들을 나열한 표이다.

·      DragAndDrop

·      GuestControl

·      GuestProperties

·      HostChannel

·      SharedClipboard

·      SharedFoldered

·      SharedOpenGL

·      Auth

 

OpenGL Application programming interface는 3D 그래픽에 관여 할 수 있는 프로그램이다. VirtualBox역시 3D 그래픽에 관여 할 수 있다는 것을 의미하고, 그러므로 3D 가속화 기능이 활성화 되어야 한다는 것도 알 수 있게 된다.

그렇다면, 이제 접근해볼 수 있는 관점은 3D 그래픽 기능에서 도대체 어떤 부분에서 취약점이 발생할 수 있는지 생각해 보아야한다. 우선 그래픽은 사용자가 I/O 중, Input을 통해 받기가 까다로울거라 예상하고 cpp 코드를 살펴보기로 하였다.

 

virtualbox/virtualbox/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp

 

헤더파일을 둘러봐도, 해당 코드가 어떤 역할을 하는지 가늠할 수 있다고 생각하여 헤더파일부터 둘러보았다. 위에서 이미 언급 된 ‘hgcm’ 역시 존재하며, 이 서비스의 경우 entrypoint와도 중요한 연계성을 띠고 있다는 것을 알게 되었다.

 

 

다음으로 해당 파일에서 사용중인 구조체에 대해 알아보았다. 취약점의 경우, 구조체 타입에 따라 취약성이 결정되기도 하기에 구조체 타입을 살펴보는 방법을 택했다.

 

첫번째 구조체 uint32_t의 경우 integer overflow가 가능하다. 하지만, 직접적으로 취약점에 이용될 수 있는지는 전혀 알 수 없다. 길이 검증이 후에 있을 수 도 있기 때문에 섣부른 판단은 하지 않는다.

 

Github repo를 통해 검색해보았을 때, 2가지의 구조체를 직접적으로 이용하는 코드는 다음과 같았다.

 

Case 1. CRVBOXSVCBUFFER

Service load state, Service get buffer, Service free buffer, Service Svccall

 

이 중 Service svccall에 관여하는 모듈들은 SHCRGL_GUEST라는 식별자들을 가지고 있었다. 이를 통해, Guest OS에 직접 관여할 수 있는게 svccall이 아닌가 하는 의심을 할 수 있다.

 

Crservice.cpp 해당 파일에서 사용할 수 있는 기능은 다음과 같다.

svcstate, svcdisconnect, svcconnect, svcunload .

 

 

2.HGCM Protocol

 

HGCM이란 무엇인지 알아야한다. 기능을 알아보기 위해 아래의 소스코드를 참조하였다.

virtualbox/virtualbox/src/VBox/Main/src-client/HGCM.cpp

 

HGCM Host-Guest Communication Manager 약자이다. 문장에서 간결하게 역할에 대해 숙지할 있다. Server & Client 간의 Service 프로그램이라고 요약할 있을 것이다.

HGCM Class내에 많은 기능이 수록되어있다. 다수의 포인터 구조체가 보이는 것으로 보아 Heap 연관 있는 클래스로도 생각된다.

 

 

라이브러리도 직접 로드 있는 기능이 있는 것으로 보여진다.

 

 

위에서 살펴본 코드 (crservice.cpp)에서VBOX_HGCM_SVC는 필수적으로 필요한 모듈이라는 것을 알 수 있다. 아울러, WRITE_BUFFER라는 식별자가 꽤 흥미를 불러일으켜 주기도 한다.

 

 

코드를 이것저것 검색하다가 HGCM Connect되는 서비스가 VBoxSharedCrOpenGL임을 확인할 수 있었다.

https://github.com/sailfishos/virtualbox/blob/b61c19a714e2f4a08b1e195862813a2d7ebf6d76/virtualbox/src/VBox/GuestHost/OpenGL/util/vboxhgcm.c

 

하지만, 모든 HGCM VBoxSharedCrOpenGL만을 서비스하지는 않는다. , 공격자 입장에서 특정 모듈에 있는 취약점을 찾았다면, 그 모듈만 연결할 수 있게 코드를 작성해야한다는 것을 의미한다.

 

3.Svccall

위에서 언급 되었던 GUEST_FN 작업들을 직접적으로 실행시켜주는 syscall 같은 존재로 인지되었다. 자세한 정보는 얻지 못했다.

타입도 CALLBACK이라고 적혀있으니 익스플로잇을 하기 위해 반드시 필요한 모듈이라고만 생각되었다.

 

 

모든 VBox 내용을 공부한 것은 아니지만, 이정도의 지식이면 해당 취약점을 찾은 발표자님의 발표를 이해할 있을 정도의 지식으로는 충분하다고 생각된다.

 

발표자님이 언급해주신 3가지 사항이 아래 사진에 첨부되어 있다.

발표자님은 서비스의 연결, 끊김 그리고 Chromium message 전송을 강조하였다.

 

서비스의 연결 끊김은 당연히 Communication 필요하므로 이해가 쉽게 되었으나, Chromium 경우 이해가 되지 않았다.

 

운이 좋게도, 해당 키워드를 LICENSE 파일에서 있었다. HostServices에서 이용 가능한 서비스 ‘SharedOpenGL’ 만이 라이센스 파일을 소지하고 있었다. 이는 SharedOpenGL 서비스만이 Chromium 사용한다는 것을 의미한다고 판단했다.

 

Officially oracle 블로그에서 정보를 얻을 있었다.

https://blogs.oracle.com/scoter/3d-acceleration-for-ubuntu-guests-v2

해당 내용을 요약하면 다음과 같다.

 

VirtualBox Guest VM에서 만든 OpenGL 요청을 인터셉트한 다음 호스트가 직접 실행할 호스트의 OpenGL 라이브러리로 전달하여 3D 가속화를 제공하게 되는데, 이때 renderer Chromium 아니면, 비록 3D 가속화 옵션을 구성설정에서 세팅하였더라도 OpenGL 드라이버를 사용할 없다.

 

또한 Chromium 브라우저에서 사용하는 개념이 아님을 명확히 숙지하고 있어야 한다. VirtualBox에서의 Chromium OpenGL 기반 3D 그래픽을 렌더링 있는 라이브러리라는 것으로 인지해야한다.

 

지금부터 CVE-2019-2525 대한 내용을 들어가보고자 한다.

참조한 코드는 VirtualBox v.6.0.0 이용하였다.

 

이미 1-day이기 때문에 취약한 부분에 대한 내용이 노출되어 있기에 바로 설명을 하며 이해도를 키워보고자 한다.

 

우선 취약점은 부분에서 발생한다고 한다. 여기서 발생한다고 생각을 했을지 상상해보고자 한다. 많은 취약점 Memory leak 발생한다는 것을 알고 있기에 데이터 타입에 집중한다.

 

코드 경로는 다음과 같다.

src/VBox/HostServices/SharedOpenGL/unpacker/unpack_shaders.c

 

 

아래의 코드에서 데이터 타입에 관련 정보는 다음과 같다.

packet_length, program, *name 3가지가 존재한다.

 

 

 

FYI: READ_DATA, DATA_POINTER, SET_RETURN_PTR, 그리고 SET_WRITEBACK_PTR 대문자인 것으로 보아 매크로임을 짐작할 있다.

따라서, 코드를 찾을 비교적 쉽게 찾을 있었다.

 

SET_WRITEBACK_PTR에서 crMemcpy 존재하며, crMemcpy함수는 VirtualBox에서 사용하는 데이터 복사 함수로 추정되는데, 내부적으로는 memcpy 기능을 하고있을 거라 예상이 된다.

 

Writeback_ptr, cr_unpackData, sizeof(*writeback_ptr) 해당 매크로에 고정되어있고, offset값에 따라 cr_unpackData[offset] 되어 writeback_ptr 메모리에 적재된다.

 

SET_RETURN_PTR 대해서도 알아보니 동일한 역할을 수행하나, destincation return_ptr 다를 뿐이다.

 

Return_ptr writeback_ptr 누가 중요한 역할을 하는것일까를 곰곰히 생각해보았는데, return_ptr 변수명이 익스플로잇에 영향을 끼칠 같다는 생각이 들었다.

그리고, 다른 것을 생각해보아야 하는 것이 매크로함수에 들어가는 offset 연산이 다르다는 것이다.

SET_RETURN_PTR 경우 x-16, SET_WRITEBACK_PTR 경우 x-8.

 

우선 이해가 안되니까, 잠시 넘어가자.

 

해당 취약점은 특정 값을 읽을 있는 OOB Read이다.

아래의 그림을 살펴보도록 하자.

 

현재 우리는 cr_unpackData 변수가 무슨 역할을 하는지는 모른 상태에서 분석을 하고 있다. 하지만, offset값이 잘못 경우 다른 영역에 침범할 있을 있다는 것을 예측할 있게 된다.

 

다시 본래의 함수로 돌아와보자. packet_length 이용되는 매크로 READ_DATA offset 0으로 고정되어 있다.

 

해결해야하는 문제는 2가지이다.

·      Packet_length 무엇을 하기 위해 작성 코드인가?

·      Packet_length 디버깅 하기 위해 어떻게 해야하는가?

 

먼저, 생각해보아야할 것이 현재 3D 가속화 옵션을 ‘GuestOS’ 부여해두었고, 이를 통해 Chromium 서비스를 이용할 있게 되었다. , Host(VM)에서 GuestOS로의 접근이 가능하다는 것을 의미한다.

 

Host(VMware)에서 다른 VirtualBox 실행시키면, Host(VMware)입장에서는 VirtualBox 프로세스로 메모리에 올라가게 되니까, attach 가능하다.

 

READ_DATA 적혀있는 cr_unpackData 경우 외부 export 적용되어 있음을 확인할 있다.

, GuestHost 3D 가속화 옵션이 켜져있을 OpenGL cr 시작되는 포인터들을 얻어와서 사용할 있게 된다.

Src/VBox/GuestHost/OpenGL/include/cr_unpack.h

 

 

상단의 코드가 불러오는 헤더파일목록이다.

 

If Data && pack / unpack => protocol이라는 결론이 나왔다. 데이터를 주고 받는 패킷은 프로토콜이 관여한다는 것은 이미 알고있는 배경지식이기에 쉽게 접근할 있었다.

 

./src/VBox/GuestHost/OpenGL/include/cr_protocol.h

해당 코드에서 이러한 구조체를 발견하였다.  

 

또한, 부분도 찾을 있었다.

매크로함수에서 이용되는 return_ptr, writeback_ptr 역시 OpenGL 임포트 되어있는 구조체였다.

 

아래 그림은 CRNetworkPointer 구조체에 대한 정의이다.

 

뿐만 아니라, unpack.py 파일에서 crUnpackExtend 호출하는 부분을 보았는데, CR_EXTEND_OPCODE라는 키워드를 발견할 있었다.

 

정리해보면, Chromium 서비스에서 OpenGL 이용할 있게 하고, GuestOS사용자는 패킷의 길이를 정하여 Host에게 전달하게 되는데, 이때 CRMessage 프로토콜 형식을 따르게 된다. 아울러, 패킷을 Host 인지할 하기 위해 unpack하는 과정을 거친다고 생각이 든다.

 

Host 경우 Chromium Server, GuestOS 경우 chromium Client 된다.

 

“Packet_length 무엇을 하기 위해 작성 코드인가?“ 대한 답변을 달아보자.

Packet_length 통해 주어진 구조체 일부에 접근할 있다.

 

과정에서 구조체의 범위를 조작할 있게 되면, 본래의 목적이 아닌 다른 주소를 leak 있다고 결론지을 있다.

 

이제 직접, packet_length에 브레이크 포인트를 걸고 디버깅을 하면서, 구조를 파악해 볼 시간이 되었다.