
CryptoPro 서명 UEFI Shell을 통한 CVE-2022-34303 Secure Boot 우회를 시연하며, mm 명령을 사용하여 gSecurity2를 무효화하고 서명되지 않은 UEFI 애플리케이션을 로드합니다.
CryptoPro Secure Disk UEFI Shell - 취약한 UEFI 애플리케이션 직접 사용(BYOVUA) - 서명된 UEFI Shell 및 gSecurity2 손상을 통한 Secure Boot 우회.
이 저장소는 CVE-2022-34303을 악용하여 BYOVUA (Bring Your Own Vulnerable UEFI Application) 기법을 시연합니다. CVE-2022-34303은 CryptoPro Secure Disk UEFI 부팅 환경의 Secure Boot 우회 취약점입니다.
이 경우 Secure Boot가 신뢰하는 구성 요소는 Microsoft의 UEFI Third Party Certificate Authority가 서명한 사용자 정의 shim입니다. 이 shim이 실행되면 2단계로 UEFI Shell을 로드하며, 이를 통해 mm (memory modify) 명령어가 노출되어 OS 부팅 전 단계에서 임의 메모리 읽기 및 쓰기 기능을 제공합니다.
이 프리미티브를 사용하여 DXE 코어의 gSecurity2 전역 포인터를 찾아 무효화할 수 있습니다. 그 결과 이후의 UEFI 이미지 검증이 비활성화되어, Secure Boot가 활성화된 상태에서도 서명되지 않은 UEFI 애플리케이션, 즉 부트킷을 로드할 수 있게 됩니다.
BYOVUA는 커널 수준에서 사용되는 BYOVD (Bring Your Own Vulnerable Driver) 기법의 UEFI 버전입니다. 취약점이 있는 서명된 커널 드라이버를 가져오는 대신, 공격자는 Secure Boot를 무력화할 수 있는 기능을 포함한 서명된 UEFI 애플리케이션 - 이 경우 전체 UEFI Shell - 을 가져옵니다.
이 애플리케이션 - 이 경우 UEFI Shell을 2단계로 로드하는 사용자 정의 shim - 은 Microsoft가 신뢰하는 인증서로 서명되어 있기 때문에 Secure Boot에서 의심 없이 허용되며, 이 인증서를 Secure Boot 데이터베이스(db)에 포함한 모든 시스템 - 지난 10년간 출시된 거의 모든 UEFI 지원 PC - 에서 신뢰됩니다. 일단 실행되면 내장 명령어를 통해 공격자에게 직접적인 하드웨어 및 메모리 접근 권한을 제공하며, 이는 운영 체제가 로드되기 전에 작동하여 현대적인 보안 제어(ASLR, DEP, 커널 보호)가 존재하지 않는 환경입니다.
Shell_Full.efi는 사전 부팅 인증 및 디스크 암호화 제품인 CryptoPro Secure Disk의 일부로 배포되는 UEFI Shell입니다.
| 속성 | 값 |
|---|---|
| 파일 | Shell_Full.efi = EFI/Boot/BootX64.efi (SHIM) -> EFI/CPSD/Bootxsa.efi (Shell) |
| 벤더 | CryptoPro Secure Disk |
| CVE | CVE-2022-34303 |
| 서명 | Microsoft Corporation UEFI CA 2011 (Third Party) |
| 발견 | Eclypsium (Mickey Shkatov, Jesse Michael) - 2022년 8월 |
| 발표 | DEF CON 30 - "One Bootloader to Load Them All" |
| 폐기 | Microsoft KB5012170을 통해 DBX에 추가됨 (2022년 8월) |
이 취약점은 버그가 아니라 설계 결함입니다. UEFI Shell은 Secure Boot 환경에서 실행되도록 의도되지 않은 정당한 진단 도구입니다. 그러나 Microsoft가 신뢰하는 인증서로 서명하고 상용 제품의 일부로 배포함으로써, 벤더들은 의도치 않게 Secure Boot에 대한 서명된 우회 경로를 만들어냈습니다.
핵심 문제: Secure Boot가 신뢰하는 서명된 바이너리가 내장 명령어를 통해 무제한적인 메모리 읽기/쓰기 기능을 제공한다는 것입니다. 이러한 조합은 전체 Secure Boot 신뢰 모델을 무너뜨립니다.
mm (memory modify) 명령어는 시스템 메모리에 대한 직접적인 읽기 및 쓰기 접근을 제공하는 표준 UEFI Shell 내장 명령어입니다. 이는 UEFI Shell Specification (섹션 5.3)에 문서화되어 있습니다.```
MM Address [Value] [-w 1|2|4|8] [-MEM | -MMIO | -IO | -PCI | -PCIE] [-n]
| 파라미터 | 설명 |
|-----------|-------------|
| `Address` | 대상 메모리 주소 |
| `Value` | 기록할 값 (읽기 전용인 경우 생략) |
| `-w` | 너비: 1, 2, 4, 또는 8 바이트 |
| `-MEM` | 시스템 메모리 접근 |
| `-MMIO` | 메모리 매핑 I/O |
| `-IO` | I/O 포트 접근 |
| `-n` | 비대화형 (다음 주소에 대한 프롬프트 없음) |
---
<div id='gsecurity2'/>
### ***gSecurity2와 보안 아키텍처 프로토콜***
UEFI에서의 보안 부팅 이미지 검증은 UEFI 플랫폼 초기화(PI) 명세에 정의된 [보안 아키텍처 프로토콜](https://uefi.org/specs/PI/1.8/V2_DXE_Architectural_Protocols.html#security-architectural-protocols)을 통해 강제됩니다.
DXE 코어(DxeMain)는 [`gSecurity2`](https://github.com/tianocore/edk2/blob/edk2-stable202608/MdeModulePkg/Core/Dxe/DxeMain.h#L252)라는 전역 포인터를 유지하며, 이는 `EFI_SECURITY2_ARCH_PROTOCOL` 구조체를 가리킵니다. 이 프로토콜은 단일 함수 포인터인 `FileAuthenticationState`를 포함하며, 이는 UEFI 이미지가 로드될 때마다 `LoadImage()`에 의해 호출됩니다:```c
// EFI_SECURITY2_ARCH_PROTOCOL structure (PI Specification)
typedef struct _EFI_SECURITY2_ARCH_PROTOCOL {
EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState;
} EFI_SECURITY2_ARCH_PROTOCOL;
// GUID: 94AB2F58-1438-4EF1-9152-18941A3A0E68
LoadImage()가 호출되면 DXE 코어는 다음을 확인합니다:```c
if (gSecurity2 != NULL)
{
Status = gSecurity2->FileAuthenticationState(gSecurity2, DevicePath, FileBuffer, FileSize, BootPolicy
);
if (EFI_ERROR(Status))
{
// Image rejected - signature verification failed
}
}
`gSecurity2 = NULL`로 설정하면 `if` 검사가 실패하고 `FileAuthenticationState`가 호출되지 않는다. 이미지 검증이 완전히 건너뛰어진다 - **Secure Boot는 "활성화"된 상태로 남지만 더 이상 강제되지 않는다**. 서명되지 않은 UEFI 애플리케이션을 자유롭게 로드할 수 있게 된다.
gSecurity2를 자동으로 찾아 패치하는 목적에 맞게 제작된 UEFI 애플리케이션을 포함한 이 기법에 대한 심층적인 기술적 이해는 동반 프로젝트를 참조하라: [Exploitation Technique - UEFI Secure Boot Bypass via gSecurity2 Corruption](https://github.com/TheMalwareGuardian/Exploitation-Technique-UEFI-SecureBoot-Bypass-gSecurity2-Corruption).
---
<div id='BYOVD'/>
### ***커널 BYOVD와의 유사점***
UEFI BYOVUA와 커널 BYOVD 사이의 구조적 유사점은 정확히 일치한다:```
┌──────────────────────────────────────────────────────────────┐
│ UEFI BYOVUA (Secure Boot Bypass) │
│ │
│ Signed Shell ─ mm ─> gSecurity2 = NULL ─> Load unsigned │
│ (trusted by (Security2 Protocol) UEFI apps │
│ Secure Boot) │
├──────────────────────────────────────────────────────────────┤
│ Kernel BYOVD (DSE Bypass) │
│ │
│ Signed Driver ─ IOCTL ─> g_CiOptions = 0 ─> Load unsigned │
│ (trusted by (CI.dll) kernel drivers │
│ DSE / CI) │
└──────────────────────────────────────────────────────────────┘
두 공격 모두 동일한 근본적인 결함을 악용합니다. 보안 메커니즘에 의해 신뢰되는 서명된 구성 요소가 바로 그 메커니즘을 비활성화하는 데 필요한 기본 요소를 제공한다는 점입니다.
서명된 Shell_Full.efi는 EFI 시스템 파티션(ESP)에 배치되고 부팅 옵션으로 구성됩니다. Secure Boot가 신뢰하는 인증서 체인으로 서명되어 있기 때문에 펌웨어는 문제없이 이를 검증하고 로드합니다.```
EFI System Partition (ESP)
└── EFI/
└── Boot/
| └── BootX64.efi (SHIM) ← Signed by Microsoft Windows UEFI Driver Publisher
|
└── CPSD/
└── Bootxsa.efi (Shell) ← Signed by Security Coding Factory Software CA
└── startup.nsh (Script) ← Auto-executed on shell launch
---
<div id='Phase2'/>
### ***Phase 2 - Security2 프로토콜 핸들 열거***
UEFI Shell에서 목표는 `EFI_SECURITY2_ARCH_PROTOCOL` (GUID: `94AB2F58-1438-4EF1-9152-18941A3A0E68`)을 노출하는 핸들을 찾고, 해당 프로토콜 인터페이스의 메모리 주소를 얻는 것이다.
> **참고:** `dh -p <GUID>` 명령은 대부분의 EDK2 Shell 빌드에서 원시 GUID를 해석하지 않는다 - 등록된 프로토콜 이름만 인식한다. 아래 접근 방식은 모든 EDK2 Shell 버전에서 작동한다.
**Step 1 - SecurityStubDxe 핸들 찾기**
모든 핸들을 나열하고 `SecurityStubDxe`를 찾는다. 이는 두 Security Architectural Protocol을 모두 설치하는 DXE 드라이버이다:```
Shell> dh
출력에서 SecurityStubDxe로 로드된 핸들을 식별합니다:```
10: Image(SecurityStubDxe)
**2단계 - 인접 핸들 검사**