[BRLY-2021-007] The stack buffer overflow vulnerability leads to arbitrary code execution in UEFI application on multiple HP devices.

February 4, 2022

Summary

BINARLY efiXplorer team has discovered a stack overflow vulnerability that allows a local root user to access UEFI Runtime DXE application and execute arbitrary code.

Vulnerability Information

  • BINARLY internal vulnerability identifier: BRLY-2021-007
  • HP PSIRT assigned CVE identifier: CVE-2021-39301
  • CERT/CC assigned case number: VU#917518
  • CVSS v3.1 Score 7.7 High AV:L/AC:L/PR:H/UI:R/S:C/C:H/I:H/A:H

Affected HP firmwares with confirmed impact by Binarly team

Fimware Application name Application version Application MD5 File GUID
S05_02020000.bin 0138 2.2.0.0 604c4ac862ab8e21d73f3df3977bd09c C988BDED-6977-464D-B714-E61DEBD2DE97
S09_02020000.bin 0138 2.2.0.0 604c4ac862ab8e21d73f3df3977bd09c C988BDED-6977-464D-B714-E61DEBD2DE97
S15_02020000.bin 0138 2.2.0.0 604c4ac862ab8e21d73f3df3977bd09c C988BDED-6977-464D-B714-E61DEBD2DE97
S25_02020000.bin 0138 2.2.0.0 604c4ac862ab8e21d73f3df3977bd09c C988BDED-6977-464D-B714-E61DEBD2DE97
S27_02020000.bin 0138 2.2.0.0 604c4ac862ab8e21d73f3df3977bd09c C988BDED-6977-464D-B714-E61DEBD2DE97
S29_02020000.bin 0138 2.2.0.0 604c4ac862ab8e21d73f3df3977bd09c C988BDED-6977-464D-B714-E61DEBD2DE97
S70_01040200.bin 0138 2.2.0.0 604c4ac862ab8e21d73f3df3977bd09c C988BDED-6977-464D-B714-E61DEBD2DE97
S73_01040200.bin 0138 2.2.0.0 604c4ac862ab8e21d73f3df3977bd09c C988BDED-6977-464D-B714-E61DEBD2DE97
S78_01010500.bin 0138 2.2.0.0 604c4ac862ab8e21d73f3df3977bd09c C988BDED-6977-464D-B714-E61DEBD2DE97

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 Runtime UEFI application and execute arbitrary code.A malicious code installed as a result of vulnerability exploitation in UEFI application 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 vulnerabile code below is located at offset 0x7B68 (firmware name: S05_02020000.bin, application name: 0138):

bool CheckBatterySafety()
{
  EFI_GUID VendorGuid;
  char Buffer;
  UINTN DataSize;

  VendorGuid.Data1 = 0xFB3B9ECE;
  *&VendorGuid.Data2 = 0x49334ABA;
  *VendorGuid.Data4 = 0xD6B49DB4;
  *&VendorGuid.Data4[4] = 0x5123897D;
  Buffer = 0;
  DataSize = 1i64;
  return (!gRT_157B30->GetVariable(L"BatterySafetyModeStatus", &VendorGuid, 0i64, &DataSize, &Buffer)
       || !gRT_157B30->GetVariable(L"BatterySafetyMode", &VendorGuid, 0i64, &DataSize, &Buffer))
      && Buffer == 1;
}

If the length of NVRAM variable BatterySafetyModeStatus is greater than 1, the DataSize is set to the length of BatterySafetyModeStatus variable and a second call to GetVariable service will occur.

After the second call to GetVariable service, the value of NVRAM variable BatterySafetyMode will be written to the Buffer stack variable.

By controlling the values of BatterySafetyModeStatus and BatterySafetyMode variables, we can write any data onto the stack and thus execute arbitrary code on the stack.

Steps for exploitation

Change BatterySafetyModeStatus and BatterySafetyMode variables.

By changing the value of BatterySafetyModeStatus variable, we change the value of the DataSize before the second call to GetVariable.

By changing the value of BatterySafetyMode variable, we overflow the stack and execute arbitrary code on the stack.

It is important to note that the Buffer value on the stack lies after the current function return address:

-0000000000000010 VendorGuid      EFI_GUID ?
+0000000000000000  s              db 8 dup(?)
+0000000000000008  r              db 8 dup(?)
+0000000000000010 Buffer          db ?
+0000000000000011                 db ? ; undefined
+0000000000000012                 db ? ; undefined
+0000000000000013                 db ? ; undefined
+0000000000000014                 db ? ; undefined
+0000000000000015                 db ? ; undefined
+0000000000000016                 db ? ; undefined
+0000000000000017                 db ? ; undefined
+0000000000000018 DataSize        dq ?
+0000000000000020
+0000000000000020 ; end of stack variables

So, it is necessary to overwrite the return address of the parent function and not the return address of the current function.

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-02-04
BINARLY public disclosure date 2022-02-04

Acknowledgements

BINARLY efiXplorer team

References

Tags
UEFI
DXE