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 the BIOS. Such a malicious firmware code in the BIOS could persist across operating system re-installs. Additionally, this vulnerability potentially could be used by threat actors to bypass security mechanisms provided by the UEFI firmware (for example, Secure Boot and some types of memory isolation for hypervisors).
Binarly REsearch Team identified a SMM callout in multiple HP devices, which allows an attacker to access the System Management Mode and execute arbitrary code.
An attacker can exploit this vulnerability to elevate privileges from ring 0 to ring -2, execute arbitrary code in System Management Mode - an evironment 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 the BIOS. Such a malicious firmware code in the BIOS could persist across operating system re-installs. Additionally, this vulnerability potentially could be used by threat actors to bypass security mechanisms provided by the UEFI firmware (for example, Secure Boot and some types of memory isolation for hypervisors).
Vulnerability exists in the software System Management Interrupt (SWSMI) handler located at offset 0x1574
in the module 0701.efi
(code example given from S05_02020000.bin
firmware).
The SWSMI handler with number 0xAE
dereferences gRT (EFI_RUNTIME_SERVICES
) pointer to call a GetVariable
service, which is located outside of SMRAM. Hence, this can result in a code execution in SMM (escalating privilege from ring 0 to ring -2).
Below is the decompiled code of the vulnerable handler:
EFI_STATUS __fastcall SwSmiHandler_1574(EFI_HANDLE DispatchHandle)
{
EFI_STATUS result;
UINT32 Attributes;
UINTN DataSize;
EFI_SMM_SW_DISPATCH2_PROTOCOL *EfiSmmSwDispatch2;
__int64 Data[6];
Attributes = 6;
DataSize = 32i64;
if ( (gRT_20F8->GetVariable(L"AmdMemContextData", &VendorGuid, &Attributes, &DataSize, Data) & 0x8000000000000000ui64) == 0i64 )
x_AmdMemContextHandler(Data);
result = gSmst_20F0->SmmLocateProtocol(&EFI_SMM_SW_DISPATCH_PROTOCOL_GUID_2050, 0i64, &EfiSmmSwDispatch2);
if ( (result & 0x8000000000000000ui64) == 0i64 )
return (EfiSmmSwDispatch2->UnRegister)(EfiSmmSwDispatch2, DispatchHandle);
return result;
}
Due to the fact this handler unregisters itself by calling EfiSmmSwDispatch2->UnRegister
, the vulnerability cannot be exploited from the operating system. However, using EFI_BOOT_SERVICES
and EFI_RUNTIME_SERVICES
is unsafe inside a code intended to run in SMM (from SMRAM) because an attacker capable of executing code in DXE phase could exploit this vulnerability to escalate privileges to SMM (ring -2). This can be achieved even after EfiSmmReadyToLock
event since no gSmst->InSmram()
check is applied.
To exploit this vulnerability from DXE evironment it is enough to:
GetVariable
service address in the EFI_RUNTIME_SERVICES
table with the shellcode address0701
from the firmware S05_02020000.bin
: EFI_STATUS __fastcall EfiEventReadyToBootNotifier(EFI_EVENT Event)
{
EFI_STATUS status;
EFI_SMM_CONTROL2_PROTOCOL *EfiSmmControl2Protocol;
char DataPort;
char CommandPort;
status = gBS_2098->LocateProtocol(&EFI_SMM_CONTROL2_PROTOCOL_GUID_2030, 0i64, &EfiSmmControl2Protocol);
if ( (status & 0x8000000000000000ui64) == 0i64 )
{
CommandPort = 0xAE;
DataPort = 1;
(EfiSmmControl2Protocol->Trigger)(EfiSmmControl2Protocol, &CommandPort, &DataPort, 0i64, 0i64);
return gBS_2098->CloseEvent(Event);
}
return status;
}
To fix this vulnerability, it is essential to replace the GetVariable
service from EFI_RUNTIME_SERVICES
with EfiSmmVariableProtocol->SmmSetVariable
.
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.
Binarly REsearch Team