Header bannerHeader banner
Advisory ID:
BRLY-2021-006

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

February 4, 2022
Severity:
High
CVSS Score
8.2
Public Disclosure Date:
February 4, 2022

Summary

Binarly REsearch Team has discovered a stack overflow vulnerability that allows a local priviledged user to access UEFI DXE driver and execute arbitrary code.
Vendors Affected Icon

Vendors Affected

HP
Affected Products icon

Affected Products

HP ProBook x361

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 a DXE Runtime UEFI application and execute arbitrary code. A malicious code installed as a result of the 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.

Summary

Binarly REsearch Team has discovered a stack overflow vulnerability that allows a local priviledged user to access UEFI DXE driver and execute arbitrary code.

Vulnerability Information

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

Affected HP firmwares with confirmed impact by Binarly REsearch Team

Fimware Driver name Driver MD5 File GUID
Q98_011500.bin 0D24 9ca37e96fc799bd289fa2bce907254b0 53132845-B75A-44F7-912D-DE964E1C37D9
Q93_011500.bin 0D24 783e0624e33bbd29fd73dc72b16bf544 53132845-B75A-44F7-912D-DE964E1C37D9
Q85_011500.bin 0D24 64e0d850110de977c78f56e7ae99154c 53132845-B75A-44F7-912D-DE964E1C37D9
Q92_011500.bin 0D24 64e0d850110de977c78f56e7ae99154c 53132845-B75A-44F7-912D-DE964E1C37D9
R70_010600.bin 0D24 bc08c9d782b1ec4f0ebbb653c756ba2f 53132845-B75A-44F7-912D-DE964E1C37D9
Q96_011500.bin 0D24 783e0624e33bbd29fd73dc72b16bf544 53132845-B75A-44F7-912D-DE964E1C37D9
Q95_011400.bin 0D24 a0578bede408689e1401dee8adbd74fa 53132845-B75A-44F7-912D-DE964E1C37D9

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 a DXE Runtime UEFI application and execute arbitrary code.A malicious code installed as a result of the 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.

Vulnerability description

The following piece of code contains a stack overflow vulnerability (firmware name: Q92_011500.bin, driver name: 0D24, code offset: 0x171F):

...
_GetCoolControlData:
  DataSize = 8i64;
  vStatus = gRT_23B0->GetVariable(
              (CHAR16 *)L"CoolControlData",
              &gVendorGuid,
              (UINT32 *)&Attributes,
              &DataSize,
              vCoolControlDataValue);
  // If the length of the CoolControlData variable is greater than 8, then at the moment vStatus = EFI_BUFFER_TOO_SMALL
  // (this means that the GetVariable call will occur a second time)
  if ( !vStatus
    || (vStatus = gRT_23B0->GetVariable(
                    (CHAR16 *)L"CoolControlData",
                    &gVendorGuid,
                    (UINT32 *)&Attributes,
                    &DataSize,
                    vCoolControlDataValue)) == 0 )
  {
    LOBYTE(v19) = vCoolControlDataValue[1];
    LOBYTE(v20) = 1;
    sub_1A78(v20, v19);
  }
  return vStatus;
}

The value of the DataSize is initialized only once (before the first call to GetVariable service).If the length of NVRAM CoolControlData variable is greater than 8, then after the second call to GetVariable service, a stack overflow may occur, followed by execution of arbitrary code.

Below is a section of the stack for the function under consideration:

-0000000000000038 vCoolControlDataValue db ?
-0000000000000037 var_37          db ?
-0000000000000036                 db ? ; undefined
-0000000000000035                 db ? ; undefined
-0000000000000034                 db ? ; undefined
-0000000000000033                 db ? ; undefined
-0000000000000032                 db ? ; undefined
-0000000000000031                 db ? ; undefined
-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 72-byte value to CoolControlData variable, an attacker can completely overwrite the return address from the current function and execute arbitrary code.

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 REsearch Team

References

Tags
DXE
UEFI
FWHunt
See if you are impacted now with our Firmware Vulnerability Scanner