
일부 구형 Qualcomm 칩셋의 하이퍼바이저 펌웨어에서 발견된 보안 문제
CVE-2022-22063는 일부 구형 퀄컴 칩셋의 하이퍼바이저 펌웨어에서 발견된 보안 문제입니다. 보호되지 않은 하드웨어 구성 요소("부트 리매퍼")를 악용하여 수정된 운영 체제에서 하이퍼바이저에 대한 전체 읽기/쓰기 액세스 권한을 얻을 수 있습니다(권한 상승). 특정 펌웨어 버전(예: 주소 또는 변수)에 대한 지식이 필요하지 않기 때문에 영향을 받는 플랫폼에서 이 문제를 악용하는 것은 간단합니다.
참고: 퀄컴이 고객에게 수정 사항을 제공했지만(업데이트를 출시할 충분한 시간 포함) 영향을 받는 많은 장치가 이미 상당히 오래되어 공급업체로부터 수정 사항을 받지 못할 수 있습니다. 이 문제는 수정되었거나 손상된 운영 체제(다른 보안 문제 사용)에서만 악용될 수 있습니다. 펌웨어에 취약점이 있더라도 운영 체제를 최신 상태로 유지하고 보안을 유지하는 것만으로도 충분할 수 있습니다.
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H이 문제는 퀄컴의 2022년 12월 보안 게시판에도 게시되었습니다.
이 문제는 영향을 받는 대상에서 실행되는 하드웨어와 소프트웨어의 조합에 따라 달라집니다.
hyp 파티션에 있는 ELF 이미지)를 실행합니다.APCS_BOOT_START_ADDR_NSEC라는 하드웨어 레지스터를 사용하여 구성 가능)가 있습니다.영향을 받는 하드웨어가 있을 가능성이 있는 칩셋(예: MSM8909 및 MSM8953)도 더 있지만, 손상될 수 있는 별도의 하이퍼바이저 펌웨어가 없습니다.
권한 상승: 이미 손상된 운영 체제 커널(예: Linux)이 주어지면, 이 문제는 하이퍼바이저 수준(ARM에서 EL1 -> EL2)으로 권한을 간단하게 상승시킬 수 있습니다. 하이퍼바이저가 관리하는 모든 메모리를 읽거나 쓸 수 있습니다. 이로 인해 하이퍼바이저가 관리하는 서로 다른 보안 도메인 또는 가상 머신(있는 경우, 구성에 따라 다름)의 격리가 깨집니다.
(참조: Qualcomm Snapdragon 플랫폼의 액세스 제어 소개)
시큐어 부트: 생산에 사용되는 대부분의 퀄컴 장치는 펌웨어의 무단 수정을 방지하기 위해 시큐어 부트를 사용합니다. 펌웨어는 부트 체인에 의해 암호화 방식으로 서명되고 확인됩니다. 이 문제를 통해 수정된 운영 체제(공식적으로 지원되는 "부트로더 잠금 해제" 또는 다른 익스플로잇을 통해)에서 로드된 하이퍼바이저 펌웨어를 런타임에 수정하거나 완전히 교체할 수 있습니다.
(참조: Qualcomm Secure Boot and Image Authentication Technical Overview (v1.0) 및 (v2.0))
참고: 이 문제는 원래 Qualcomm Snapdragon 410(MSM8916) 플랫폼에서 발견되었습니다. 다음 설명 중 일부는 MSM8916에 특정될 수 있습니다. 예:
그러나 일반적인 개념은 영향을 받는 모든 플랫폼에 유사하게 적용됩니다.
ARMv8-A 64비트 아키텍처는 4개의 권한 수준("예외 수준", EL)을 정의합니다. 일반적으로 애플리케이션, 운영 체제 커널 및 하이퍼바이저에 사용되는 별도의 수준이 있습니다:
CPU는 예를 들어 들어오는 인터럽트로 인해 예외가 발생하는 동안 수준 간 전환합니다. 하이퍼바이저 호출(hvc)과 같은 특수 명령어를 사용하여 일부 수준 간 전환도 가능합니다.
(참조: AArch64 Exception model)
하이퍼바이저는 별도의 운영 체제 커널을 사용하여 하나 이상의 가상 머신을 호스팅할 수 있습니다. 각 가상 머신은 스테이지 2 변환을 사용하여 자체 메모리 뷰를 제공받을 수 있습니다. 가상 머신의 모든 메모리 액세스는 두 단계의 변환을 거칩니다. 첫 번째 단계는 (가상) 운영 체제에서 관리되고, 두 번째 단계는 하이퍼바이저에서 관리됩니다. 하이퍼바이저 또는 다른 가상 머신에서 사용하는 메모리는 변환 테이블에서 생략하여 숨길 수 있습니다.
(참조: AArch64 virtualization, AArch64 memory management)
퀄컴의 하이퍼바이저 펌웨어는 EL2에서 실행되며 스테이지 2 변환을 사용하여 메인 운영 체제 커널(EL1, 일반적으로 Linux)이 하이퍼바이저 메모리에 액세스하지 못하도록 합니다. 이 설정에서 스테이지 2 변환은 주소 변환 없이 주로 메모리 보호에 사용됩니다. 메인 운영 체제는 메모리 매핑된 입출력(MMIO) 공간에 있는 대부분의 하드웨어 구성 요소(예: SD 컨트롤러 또는 카메라 서브시스템)에 직접 액세스할 수 있습니다. 하이퍼바이저/EL2(hyp) 및 시큐어 모니터/EL3(tz의 일부)에 속하는 메모리에 대한 액세스는 제한됩니다:
_부트 리매퍼_는 가상화와 관련이 없습니다. CPU 코어의 초기 부팅 중에 필요합니다. 이 하드웨어 플랫폼에서 CPU 코어는 항상 주소 0x0에서 실행을 시작합니다. 부트 리매퍼는 CPU 주변에 구축된 추가 하드웨어 구성 요소로, 처음 64 또는 128 KiB(0x00000 - 0x20000)를 구성 가능한 메모리 영역으로 다시 매핑합니다.
기본적으로 부트 리매퍼는 부트 ROM(장치가 시작될 때 실행되는 첫 번째 코드)을 가리킵니다. 나중에 매핑이 변경되어 다른 CPU 코어가 RAM에 로드된 EL3 펌웨어(tz의 일부)에서 즉시 실행을 시작합니다:
CPU가 액세스하는 주소(tz 내)는 두 개의 다른 물리적 주소를 사용하여 액세스할 수 있습니다. RAM의 실제 주소(0x8650xxxx)와 부트 리매퍼를 사용한 다시 매핑된 주소(0x0000xxxx)입니다.
실제로 부트 리매퍼에는 두 개의 별도 인스턴스가 있습니다:
APCS_BOOT_START_ADDR_SEC(= 0x0b010004)를 사용하여 구성할 수 있지만 보안 상태에서만 가능합니다.APCS_BOOT_START_ADDR_NSEC(= 0x0b010008)를 사용하여 구성할 수 있습니다.두 부트 리매퍼 인스턴스 모두 다시 매핑된 영역의 기본 주소와 두 개의 구성 비트(REMAP_EN은 다시 매핑 활성화, BOOT_128KB_EN은 64KiB 대신 처음 128KiB를 다시 매핑)를 포함하는 메모리 레지스터를 사용하여 구성할 수 있습니다.
(참조: Qualcomm Snapdragon 410E Technical Reference Manual rev. D, 85쪽 및 116쪽)
이전 두 섹션의 지식을 사용하면 기본 아이디어는 간단합니다. 부트 리매퍼를 사용하여 하이퍼바이저의 메모리 보호(스테이지 2 변환)를 우회합니다.
부트 리매퍼는 CPU 시작 중에만 작동하지 않습니다. 언제든지 사용할 수 있으며 다시 매핑된 영역에 대한 전체 읽기/쓰기/실행 액세스를 허용합니다. 또한 퀄컴의 하이퍼바이저는 영향을 받는 장치에서 운영 체제가 비보안 인스턴스의 부트 리매퍼를 구성하고 액세스하는 것을 방지하지 않는 것으로 보입니다(스테이지 2 변환을 사용하여 보호되지 않음). 따라서 이 문제는 다음을 통해 쉽게 악용할 수 있습니다:
hyp)을 가리키도록 구성한 다음,다시 매핑된 영역은 블록별로 동적으로 이동하여 부트 리매퍼를 통해 사용 가능한 64/128KiB보다 큰 메모리 영역에 액세스할 수 있습니다. 또한 이를 사용하여 하이퍼바이저 메모리 보호를 완전히 비활성화할 수도 있습니다(개념 증명 참조).
참고: 동일한 익스플로잇은 시큐어 월드 펌웨어(tz)에서는 작동하지 않습니다. 부트 리매퍼를 사용하면 스테이지 2 변환을 우회할 수 있지만 DRAM의 tz 메모리 영역은 부트 리매퍼를 통과한 후 액세스를 차단하는 추가 하드웨어 구성 요소(CPU 외부)에 의해 보호되는 것으로 보입니다:
tz 메모리 영역은 보안 상태에서만 액세스할 수 있을 가능성이 높습니다. 이 익스플로잇은 하이퍼바이저의 메모리 보호만 우회할 수 있으며, 다른 하드웨어 보안 메커니즘은 그대로 유지됩니다.
부트 리매퍼를 사용하면 펌웨어 버전에 대한 지식 없이 런타임에 원래 하이퍼바이저 펌웨어를 완전히 비활성화하고 교체할 수 있습니다. 특히, 수정할 수 있는 변수 및 함수의 메모리 주소를 얻기 위해 리버스 엔지니어링을 사용할 필요가 없습니다. 오픈 소스 Linux 코드의 메모리 예약 또는 내부 저장소의 hyp 파티션에서 사용할 수 있는 하이퍼바이저 펌웨어 바이너리의 ELF 헤더를 읽는 등 하이퍼바이저 펌웨어의 대략적인 메모리 영역을 아는 것만으로 충분합니다.
일반적인 아이디어는 다음과 같습니다:
hvc)을 수행하여 운영 체제에서 하이퍼바이저로 전환합니다(EL1에서 EL2로).이를 구현하는 코드는 길지 않지만 일부 저수준 AArch64 어셈블리와 CPU 캐시와의 신중한 상호 작용이 포함됩니다. 그러나 여전히 주요 질문이 남아 있습니다. 코드를 특정 하이퍼바이저 펌웨어 버전에 종속되지 않도록 하려면 셸 코드를 정확히 어디에 작성해야 할까요?
하이퍼바이저 호출(또는 일반적으로 모든 예외) 중에 CPU 실행은 특수 메모리 주소인 _예외 벡터_로 강제됩니다. 예외 벡터는 현재 또는 낮은 예외 수준에서 발생하는 다양한 유형의 예외를 처리하는 코드를 포함하는 더 큰 _벡터 테이블_의 일부입니다:
각 상자는 32개의 어셈블리 명령어를 위한 공간이 있는 예외 벡터를 나타냅니다. 이 정도 공간으로는 충분하지 않으므로 일반적으로 추가 코드를 위한 더 많은 공간이 있는 다른 곳으로 점프하는 분기 명령어를 포함합니다.
오프셋은 각 예외 수준에 대한 벡터 테이블의 기준 주소를 정의하는 벡터 기준 주소 레지스터(VBAR)를 기준으로 합니다. 하이퍼바이저는 기준 주소를 VBAR_EL2 CPU 레지스터에 씁니다.
하이퍼바이저 호출은 더 낮은 예외 수준(EL1에서 실행되는 운영 체제 커널에서 EL2의 하이퍼바이저로)에서 발생하는 동기 예외입니다. 운영 체제 커널이 32비트 모드에서 실행 중인 경우 CPU는 VBAR_EL2+0x600으로 점프하고, 64비트 모드에서는 VBAR_EL2+0x400으로 점프합니다. 부트 리매퍼를 사용하여 이 주소에 사용자 정의 코드를 작성하고 하이퍼바이저 호출을 수행하면 CPU가 셸 코드 실행을 시작합니다.
안타깝게도 VBAR_EL2는 EL1에서 실행되는 운영 체제 커널이 읽을 수 없습니다. 하이퍼바이저(EL2) 자체 또는 그 이상에서만 읽을 수 있습니다. 그럼에도 불구하고 이 지식을 사용하면 무차별 대입을 통해 진입 주소를 훨씬 쉽게 추측할 수 있습니다. 벡터 테이블의 기준 주소는 크기(0x800 = 2KiB)의 배수로 정렬되어야 합니다. 즉, 128KiB 영역 내에는 64개의 가능한 위치가 있고, 1MiB 영역 내에는 512개의 위치가 있습니다:
빨간색 상자는 하이퍼바이저 호출 중 CPU가 점프할 수 있는 모든 가능한 위치를 보여줍니다. 모든 위치에 셸 코드를 작성하는 것은 접근 방식을 하나의 특정 펌웨어 버전(실제로는 특정 주소에 벡터 테이블이 있음)에 독립적으로 유지하는 데 충분합니다.
이는 더 개선될 수 있습니다. 부트 리매퍼는 읽기 및 쓰기 액세스를 모두 허용하므로 메모리 위치에서 읽은 기존 코드/데이터를 기반으로 일부 휴리스틱을 추가할 수 있습니다. 여기에는 유효한 AArch64(A64) 명령어와 NOP 또는 분기 명령어와 같은 반복적인 채우기 바이트가 포함될 가능성이 높습니다. (예외 벡터당 32개 명령어에 대한 공간은 더 많은 공간이 있는 적절한 함수로 분기하는 것이 더 쉽기 때문에 종종 부분적으로만 사용됩니다.)
이 저장소에 포함된 개념 증명 코드는 Snapdragon 410(MSM8916/APQ8016) 플랫폼용 퀄컴의 오픈 소스 Little Kernel(LK) 부트로더의 수정 버전입니다. 원래는 DragonBoard 410c 개발 보드로 테스트하기 위한 것입니다. 간단함을 위해 모두 선택되었습니다. 이 문제는 Linux와 같은 다른 운영 체제, 다른 영향을 받는 플랫폼 및 시큐어 부트가 있는 장치에서도 악용될 수 있습니다. 단, 운영 체제 커널 내에서 사용자 정의 코드를 실행할 수 있는 방법이 있어야 합니다.
코드는 위에서 설명한 접근 방식을 구현하여 실행 중인 하이퍼바이저를 완전히 비활성화한 다음 다른 버전으로 교체합니다. 새로운 "하이퍼바이저"는 가상 머신을 지원하지 않지만 간단한 하이퍼바이저 호출을 사용하여 _인생, 우주, 그리고 모든 것에 대한 궁극적인 질문에 대한 답_을 제공할 수 있습니다.``` $ fastboot oem CVE-2022-22063 < waiting for any device > (bootloader) Hypervisor, what is the Answer to The Ultimate Question of (bootloader) Life, the Universe and Everything? (bootloader) Old hypervisor returned answer: -2 (bootloader) Old non-secure boot remapper base address: 0x100000 (bootloader) Setting boot remapper to hypervisor memory (0x86400000) (bootloader) Using boot remapper to copy shell code to hypervisor memory (bootloader) Copying to all possible vector tables (starting at 0x600) (bootloader) Calling shell code to disable running hypervisor (bootloader) Found old EL2 vector base address at 0x86404000 (bootloader) Copying new code directly to hypervisor memory (0x86400000) (bootloader) Hypervisor, what is the Answer to The Ultimate Question of (bootloader) Life, the Universe and Everything? (bootloader) New hypervisor returned answer: 42 OKAY [ 0.015s] Finished. Total time: 0.015s
### 테스트
개념 증명 코드는 다음과 같이 빌드하고 테스트할 수 있습니다:```shell
$ git clone https://git.codelinaro.org/clo/la/kernel/lk.git -b caf_migration/LA.BR.1.2.9.1_rb1.5
$ cp CVE-2022-22063.c lk/platform/msm8916/
$ git apply LK.diff
# Build LK for msm8916 and flash it to device
$ fastboot oem CVE-2022-22063
...
그러나 이 구성은 DragonBoard 410c 개발 보드와 같이 보안 부팅이 없어 기본 부트로더를 쉽게(그리고 안전하게) 교체할 수 있는 기기에만 적합합니다. 이 저장소의 코드는 주로 참고용으로 제공되며, 쉬운 사용/테스트를 위한 것이 아닙니다.
향후에는 이 코드를 lk2nd의 새 버전에 통합하여 다양한 기기에서 기본 부트로더를 교체하지 않고도 훨씬 쉽게 테스트할 수 있도록 할 계획입니다.
Qualcomm에 따르면, 이 문제는 스테이지 2 변환을 사용하여 부트 리매퍼 영역에 대한 접근을 차단함으로써 해결되었습니다. 부트 리매퍼 구성(APCS_BOOT_START_ADDR_NSEC 레지스터)은 여전히 접근 가능하지만, 이제 두 메모리 영역 모두 차단됩니다:
또 다른 가능한 수정 방법은 하이퍼바이저에서 APCS_BOOT_START_ADDR_NSEC 레지스터를 보호하는 것입니다. 이 경우 리매핑된 영역은 계속 접근 가능할 수 있습니다. 운영 체제가 부트 리매퍼를 다른 메모리 영역으로 재구성할 방법이 없기 때문입니다.
Qualcomm에 따르면, 이 문제는 일반적인 자동화 도구를 사용할 수 없었기 때문에 처리하기가 특히 어려웠습니다. 대부분의 보고되는 문제는 소프트웨어 문제로, 소스 코드를 확인하여 영향을 받는 기기를 식별할 수 있습니다. 이 문제의 경우 하드웨어와 소프트웨어를 모두 수동으로 확인해야 했습니다(플랫폼에 문제가 있는 레지스터가 있는지, 하이퍼바이저가 취약한지). 불행히도 자동화를 사용하지 않으면 문제가 보안 게시판에 자동으로 예약되지 않았습니다. 두 번째 엠바고 연장은 고객에게 보안 문제를 인지시키고 기기에 패치를 적용할 시간을 주기 위해 요청되었습니다. 향후 보고서에서 이러한 문제를 피하기 위해 프로세스를 개선하고 있습니다.
CVE-2022-22063 Report and Diagrams © 2022 by Stephan Gerhold are licensed under Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0).
개념 증명 코드(CVE-2022-22063.c)는 MIT 라이선스에 따라 제공됩니다.