[BRLY-2021-053] The stack buffer overflow vulnerability leads to arbitrary code execution in DXE driver on Intel platform
Reported as a part of Intel Camping with Tigers bug bounty program
Summary
BINARLY efiXplorer team has discovered a stack overflow vulnerability that allows a local root user to access UEFI DXE driver and execute arbitrary code.
Vulnerability Information
- BINARLY internal vulnerability identifier: BRLY-2021-053
- HP PSIRT assigned CVE identifier: CVE-2021-39299, CVE-2021-39300
- CVSS v3.1: 7.5 High AV:L/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H
Affected Intel firmwares with confirmed impact by Binarly team
Device/Firmware | File Name | SHA256 (File PE32 section) | File GUID |
---|---|---|---|
HP EliteBook x360 1040 G8 | 0614 | eeeacc5cb2fad20df51283460831816aed4f67e769e4f57186180adf7d20da3d | 03E0A38B-3FBE-49CB-B311-726611213182 |
Potential impact
An attacker with local privileged access can exploit this vulnerability to elevate privileges from ring 3 or ring 0 (depends on the operating system) to DXE driver and execute arbitrary code. A malicious code installed as a result of vulnerability exploitation in DXE driver could survive across an operating system (OS) boot process and runtime or modify NVRAM area on SPI flash storage (to gain persistence on target platform). Additionally, this vulnerability potentially could be used by malicious actors to bypass OS security mechanisms (modify privileged memory or runtime variables), influence on OS boot process, and in some cases would allow an attacker to hook or modify EFI Runtime services.
Vulnerability description
The vulnerability exists in notifier for SA_POLICY_PROTOCOL
located at offset 0x1538
.
The pseudocode for this notifier is shown below:
__int64 SaPolisyProtocolNotifier()
{
EFI_STATUS Status; // rax
__int64 result; // rax
void *Interface; // [rsp+30h] [rbp-50h] BYREF
EFI_GUID VendorGuid; // [rsp+48h] [rbp-38h] BYREF
char IntelTechnologiesOptionsBuffer[40]; // [rsp+58h] [rbp-28h] BYREF
char Buffer; // [rsp+A0h] [rbp+20h] BYREF
UINTN DataSize; // [rsp+A8h] [rbp+28h] BYREF
...
VendorGuid.Data1 = 0xFB3B9ECE;
*&VendorGuid.Data2 = 0x49334ABA;
*VendorGuid.Data4 = 0xD6B49DB4;
*&VendorGuid.Data4[4] = 0x5123897D;
gBS->LocateProtocol(&SA_POLICY_PROTOCOL_GUID, 0, &Interface);
...
ZeroMem(&Buffer, 1);
DataSize = 0;
Status = gRT->GetVariable(L"PciePwrMgmt", &VendorGuid, 0, &DataSize, &Buffer);
if ( Status == EFI_BUFFER_TOO_SMALL )
Status = gRT->GetVariable(L"PciePwrMgmt", &VendorGuid, 0, &DataSize, &Buffer);
if ( Status || Buffer )
{
...
}
...
DataSize = 30;
gRT->GetVariable(L"IntelTechnologiesOptions", &VendorGuid, 0, &DataSize, IntelTechnologiesOptionsBuffer);
...
return result;
}
Consider following code snippet:
DataSize = 0;
Status = gRT->GetVariable(L"PciePwrMgmt", &VendorGuid, 0, &DataSize, &Buffer);
if ( Status == EFI_BUFFER_TOO_SMALL )
Status = gRT->GetVariable(L"PciePwrMgmt", &VendorGuid, 0, &DataSize, &Buffer);
The first call to GetVariable
is occurs with DataSize = 0
. Thus, after this call, the DataSize
variable will contain the real size of the PciePwrMgmt
NVRAM variable buffer and GetVariable will return EFI_BUFFER_TOO_SMALL
.
During the second call, the data from the PciePwrMgmt
NVRAM variable will be written to the Buffer
stack variable.
The size of the Buffer
on the stack is 1 byte, but a potential attacker could make the buffer size of the PciePwrMgmt
NVRAM variable much larger than 1 which will lead to a stack overflow and arbitrary code execution.
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-01-05 |
HP PSIRT provide patch release | 2022-01-27 |
BINARLY public disclosure date | 2022-05-23 |
Acknowledgements
BINARLY efiXplorer team