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 driver and execute arbitrary code.A malicious code installed as a result of the vulnerability exploitation in a 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 threat actors to bypass OS security mechanisms (modify privileged memory or runtime variables), influence on 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 buffer overflow vulnerability that allows an attacker to 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 driver and execute arbitrary code.A malicious code installed as a result of the vulnerability exploitation in a 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 threat actors to bypass OS security mechanisms (modify privileged memory or runtime variables), influence on the OS boot process, and in some cases would allow an attacker to hook or modify EFI Runtime services.
The pseudocode of the vulnerable function is shown below:
__int64 sub_1ED8()
{
__int64 DataSize;
char Value[4];
Value[0] = 0;
DataSize = 1;
if ( (gSkipFlag & 1) == 0 )
{
gSkipFlag = 1;
if ( !(gRT->GetVariable)(L"DISABLEBATTERY", &MICROSOFT_VENDOR_GUID, 0, &DataSize, Value) )
gDisableBattery = Value[0] != 0;
if ( !(gRT->GetVariable)(L"PrintChargerAppDbgMsg", &gVariableGuid, 0, &DataSize, Value) )
gPrintChargerAppDbgMsg = Value[0] != 0;
if ( !(gRT->GetVariable)(L"ChargerPDLogLevel", &gVariableGuid, 0, &DataSize, Value) )
gChargerPDLogLevel = Value[0];
if ( !(gRT->GetVariable)(L"ChargerPDLogTimer", &gVariableGuid, 0, &DataSize, Value) )
{
gChargerPDLogTimer = Value[0];
gChargerPDLogTimerFlag = Value[0] != 0;
}
if ( !(gRT->GetVariable)(L"ForcePowerTesting", &MICROSOFT_VENDOR_GUID, 0, &DataSize, Value) )
{
gForcePowerTestingValue = 2;
gForcePowerTestingFlag = Value[0] != 0;
}
}
return 0;
}
As we can see from the pseudocode, DataSize
is initialized only once (before the first call to gRT->GetVariable()
).
Thus, if the data size of the variable in NVRAM is greater than 1, DataSize will be overwritten. Thus, a next call to gRT-GetVariable()
may cause an overflow on the stack (and subsequent execution of arbitrary code).
In order to fix this vulnerability, the DataSize
variable must be initialized before each call to gRT->GetVariable()
:
Value[0] = 0;
DataSize = 1;
if ( (gSkipFlag & 1) == 0 )
{
gSkipFlag = 1;
if ( !(gRT->GetVariable)(L"DISABLEBATTERY", &MICROSOFT_VENDOR_GUID, 0, &DataSize, Value) )
gDisableBattery = Value[0] != 0;
DataSize = 1;
if ( !(gRT->GetVariable)(L"PrintChargerAppDbgMsg", &gVariableGuid, 0, &DataSize, Value) )
gPrintChargerAppDbgMsg = Value[0] != 0;
DataSize = 1;
if ( !(gRT->GetVariable)(L"ChargerPDLogLevel", &gVariableGuid, 0, &DataSize, Value) )
gChargerPDLogLevel = Value[0];
DataSize = 1;
if ( !(gRT->GetVariable)(L"ChargerPDLogTimer", &gVariableGuid, 0, &DataSize, Value) )
{
gChargerPDLogTimer = Value[0];
gChargerPDLogTimerFlag = Value[0] != 0;
}
DataSize = 1;
if ( !(gRT->GetVariable)(L"ForcePowerTesting", &MICROSOFT_VENDOR_GUID, 0, &DataSize, Value) )
{
gForcePowerTestingValue = 2;
gForcePowerTestingFlag = Value[0] != 0;
}
}
return 0;
}
This vulnerability is subject to a 90 day disclosure deadline. After 90 days elapsed or a patch has been made broadly available (whichever is earlier), the vulnerability report will become visible to the public.
Binarly REsearch Team