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 a DXE Runtime UEFI application 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 the SPI flash storage (to gain persistence on target platform). Additionally, this vulnerability potentially could be used by threat actors to bypass OS security mechanisms (modify privileged memory or runtime variables), influencing the OS boot process, and in some cases would allow an attacker to hook or modify EFI Runtime services.
Binarly REsearch Team has discovered a stack overflow vulnerability that allows a local priviledged user to access UEFI DXE driver and execute arbitrary code.
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 a DXE Runtime UEFI application 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 the SPI flash storage (to gain persistence on target platform).Additionally, this vulnerability potentially could be used by threat 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.
The following piece of code contains a stack overflow vulnerability (firmware name: Q92_011500.bin
, driver name: 0D24
, code address: 0x1490
):
...
Attributes = a2;
DataSize = 0i64;
Interface = 0i64;
gBS_23A0->LocateProtocol(&ProprietaryProtocol_2040, 0i64, &Interface);
if ( gRT_23B0->GetVariable((CHAR16 *)L"DptfOptions", &VendorGuid, (UINT32 *)&Attributes, &DataSize, &Buffer) != EFI_BUFFER_TOO_SMALL
|| gRT_23B0->GetVariable((CHAR16 *)L"DptfOptions", &VendorGuid, (UINT32 *)&Attributes, &DataSize, &Buffer) )
{
goto _GetCoolControlData;
}
...
The first call to GetVariable
is used to get the length of NVRAM DptfOptions
variable.The second call to GetVariable
is used to get the value of NVRAM DptfOptions
variable (which will be written to the Buffer
stack variable).
Below is a section of the stack for the function under consideration:
-0000000000000030 Buffer dq ?
-0000000000000028 var_28 dd ?
-0000000000000024 db ? ; undefined
-0000000000000023 db ? ; undefined
-0000000000000022 db ? ; undefined
-0000000000000021 db ? ; undefined
-0000000000000020 db ? ; undefined
-000000000000001F db ? ; undefined
-000000000000001E db ? ; undefined
-000000000000001D db ? ; undefined
-000000000000001C db ? ; undefined
-000000000000001B db ? ; undefined
-000000000000001A db ? ; undefined
-0000000000000019 db ? ; undefined
-0000000000000018 var_18 dq ?
-0000000000000010 var_10 dd ?
-000000000000000C db ? ; undefined
-000000000000000B db ? ; undefined
-000000000000000A db ? ; undefined
-0000000000000009 db ? ; undefined
-0000000000000008 db ? ; undefined
-0000000000000007 db ? ; undefined
-0000000000000006 db ? ; undefined
-0000000000000005 db ? ; undefined
-0000000000000004 db ? ; undefined
-0000000000000003 db ? ; undefined
-0000000000000002 db ? ; undefined
-0000000000000001 db ? ; undefined
+0000000000000000 s db 16 dup(?)
+0000000000000010 r db 8 dup(?)
+0000000000000018 Interface dq ? ; offset
+0000000000000020 Attributes dq ?
+0000000000000028 DataSize dq ?
+0000000000000030 arg_18 dq ? ; offset
+0000000000000038
+0000000000000038 ; end of stack variables
Thus, by assigning a 64-byte value to the DptfOptions
variable, an attacker can completely overwrite the return address from the current function and execute arbitrary code.
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