The heap buffer overflow vulnerability in child SW SMI handler on multiple HP devices.
BINARLY efiXplorer team has discovered a heap buffer overflow vulnerability in a child SW SMI handler on multiple HP devices that allows corruption of heap metadata.
Image preview
Potential Impact
An attacker can exploit this vulnerability to elevate privileges from ring 0 to ring -2, execute arbitrary code in System Management Mode - an environment more privileged than operating system (OS) and completely isolated from it. Running arbitrary code in SMM additionally bypasses SMM-based SPI flash protections against modifications, which can help an attacker to install a firmware backdoor/implant into BIOS. Such malicious firmware code in BIOS could persist across operating system re-installs. Additionally, this vulnerability potentially could be used by threat actors to bypass security mechanisms provided by UEFI firmware (for example, Secure Boot and some types of memory isolation for hypervisors).
Image preview
Vulnerability Information
- BINARLY internal vulnerability identifier: BRLY-2021-032
- HP PSIRT assigned CVE identifier: CVE-2022-23924
- CERT/CC assigned case number: VU#683814
- CVSS v3.1 8.2 High AV:L/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H
Image preview
Affected HP firmware
| Device/Firmware | File Name | SHA256 (File PE32 section) | File GUID |
|---|---|---|---|
Device / firmware version: 02.05.01 Rev.A | 0135 | b4bafc81429259891b9b9fd60bc06eedf2e61cbee3fbdd1963579d00c7b025a5 | 3F626A59-87D2-4FCF-B5DE-9D12A8B2AF88 |
Image preview
Vulnerability description
The vulnerability was found in the child SW SMI handler registered with GUID 3b46cda7-0bd6-4323-a03b-bdf94a023f0a and located at offset 0x2158 in the driver.
The pseudocode for this handler is shown below:
EFI_STATUS __fastcall SmiHandler_2158(
EFI_HANDLE DispatchHandle,
const void *Context,
_QWORD *CommBuffer,
UINTN *CommBufferSize)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
Num = 4;
if ( CommBuffer && CommBufferSize && (-(__int64)(*CommBufferSize != 24) & EFI_INVALID_PARAMETER) == 0 )
{
Size = GetStrSize((_WORD *)CommBuffer[1]);
CommBuffer1 = CommBuffer[1];
Size1 = Size;
Res = 0;
if ( CommBuffer1 && Size1 )
Res = SmmIsBufferOutsideSmmValid(CommBuffer1, Size1);
if ( (-(__int64)(Res == 0) & EFI_INVALID_PARAMETER) == 0 )
{
if ( *(_BYTE *)CommBuffer )
{
if ( *(_BYTE *)CommBuffer == 1 )
{
if ( GetWideStrSize((_WORD *)CommBuffer[1]) )
{
Res1 = FactoryConfigHandler((_WORD *)CommBuffer[1], (__int64)&Num, 1);// possible heap overflow
goto _Exit;
}
}
else if ( *(_BYTE *)CommBuffer == 2 )
{
Res1 = BuildIdHandler((_WORD *)CommBuffer[1], (__int64)&Num, 1);// possible heap overflow
_Exit:
CommBuffer[2] = Res1;
return 0;
}
}
else if ( GetWideStrSize((_WORD *)CommBuffer[1]) )
{
CommBuffer[2] = Validate((_WORD *)CommBuffer[1]) ? 0 : EFI_CRC_ERROR;
return 0;
}
CommBuffer[2] = EFI_INVALID_PARAMETER;
}
}
return 0;
}
If the initial checks pass, the following happens in this handler:
- if the first byte from
CommBufferis1and a pointer to a wide string is located at offsetCommBuffer + 8, then functionFactoryConfigHandler(offset:0x1A60) will be called - if the first byte from
CommBufferis2and a pointer to a wide string is located at offsetCommBuffer + 8, then functionBuildIdHandler(offset:0x1C88) will be called
BuildIdHandler
Consider the FactoryConfigHandler function.
Status = SmmGetVariable(L"FactoryConfig", &VariableValue);
if ( Stautus )
goto _Exit;
if ( GetWideStrSize(StringFromCommBufferPtr) )
{
StrSize = GetStrSize(StringFromCommBufferPtr);
Value = VariableValue;
if ( VariableValue && StrSize )
{
if ( StrSize > 500 )
StrSize = 500;
if ( VariableValue != StringFromCommBufferPtr )
CopyMem(VariableValue, StringFromCommBufferPtr, StrSize);
}
...
}
SmmGetVariable function will do the following:
- gets the size of the
FactoryConfigNVRAM variable - allocates a buffer with
gSmst->SmmAllocatePool(EfiRuntimeServicesData, Size, &Buffer)(insideSmmAllocatePool, offset:0x2F98) - сopies the value of the
FactoryConfigNVRAM variable to the allocated buffer - as a result, the
VariableValuevariable will contain the address of the buffer in the heap containing the value of theFactoryConfigvariable- at the same time, we control the size of this buffer, because we can change the
FactoryConfigNVRAM variable
- at the same time, we control the size of this buffer, because we can change the
CopyMem will copy the data at the address that an attacker can control into VariableValue. In this case, the size of the data copied is equal to the size of the string located at the controlled address in CommBuffer (but not more than 500).
In other words, attacker control both buffers:
- the size of the destination buffer
- the size and data of the source buffer
This will lead to a heap buffer overflow.
To exploit this vulnerability it is enough to:
- If the size of the
FactoryConfigNVRAM variable >= 500, set the value of this variable so that its size is less than 500 - Setup Communication Buffer:
02 00 00 00 00 00 00 00- pointer to wide string with size >= 500
00 00 00 00 00 00 00 00
- Trigger the SW SMI Handler (SW SMI number and pointer to Communication Buffer are specified in UEFI ACPI table) via
0xB2IO port.
BuildIdHandler
This function has the same vulnerability.
But the allocated buffer will contain the value of the BuildId variable, and the maximum data size that can be written in the allocated buffer is 112.
To exploit this vulnerability it is enough to:
- If the size of the
BuildIdNVRAM variable >= 112, set the value of this variable so that its size is less than 112 - Setup Communication Buffer:
01 00 00 00 00 00 00 00- pointer to wide string with size >= 112
00 00 00 00 00 00 00 00
- Trigger the SW SMI Handler (SW SMI number and pointer to Communication Buffer are specified in UEFI ACPI table) via
0xB2IO port
Image preview
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 |
|---|---|
HP PSIRT is notified | 2021-07-12 |
HP PSIRT confirmed reported issue | 2021-08-09 |
HP PSIRT assigned CVE number | 2021-08-19 |
CERT/CC created a case | 2021-11-16 |
HP PSIRT provide patch release | 2022-03-08 |
BINARLY public disclosure date | 2022-03-08 |
Image preview
Acknowledgements
Image preview
See if you are impacted now with our Firmware Vulnerability Scanner
Find Vulnerabilities, Generate SBOMs & CBOMs