Header bannerHeader banner
Advisory ID:
BRLY-2022-087

[BRLY-2022-087] Memory contents leak / information disclosure vulnerability in DXE driver on Dell platform.

June 22, 2023
Severity:
Medium
CVSS Score
4.9
Public Disclosure Date:
June 21, 2023

Summary

Binarly REsearch Team has discovered a memory contents leak / information disclosure vulnerability that allows a potential attacker to dump stack memory or global memory into an NVRAM variable. This in turn could help building a successful attack vector based on exploiting a memory corruption vulnerability.
Vendors Affected Icon

Vendors Affected

Intel
Affected Products icon

Affected Products

XPS 13 9310

Potential Impact

An attacker with high physical access can exploit this vulnerability to read the contents of stack memory or global memory. This information could help with exploitation of other vulnerabilities in DXE to elevate privileges from ring 3 or ring 0 (depends on the operating system) to a DXE driver and execute arbitrary code. Malicious code installed as a result of this exploitation could survive operating system (OS) boot process and runtime, or modify NVRAM area on the SPI flash storage (to gain persistence). Additionally, threat actors could use this vulnerability to bypass OS security mechanisms (modify privileged memory or runtime variables), influence OS boot process, and in some cases allow an attacker to hook or modify EFI Runtime services.

Summary

Binarly REsearch Team has discovered a memory contents leak / information disclosure vulnerability that allows a potential attacker to dump stack memory or global memory into an NVRAM variable. This in turn could help building a successful attack vector based on exploiting a memory corruption vulnerability.

Vulnerability Information

  • BINARLY internal vulnerability identifier: BRLY-2022-087
  • Dell PSIRT assigned CVE identifier: CVE-2023-28033
  • DSA identifier: DSA-2023-099/DSA-2023-204
  • CVSS v3.1: 4.9 Medium AV:P/AC:L/PR:H/UI:N/S:C/C:H/I:N/A:N

Affected Dell firmware with confirmed impact by Binarly REsearch Team

Product Firmware version CPU Module name Module GUID Module SHA256
XPS 13 9310 0.3.11.0 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 10ff0c63534aad2bd5efe36d56f1f3efc6e7c59a4fc7cec66591f9194e364058
Precision 3450-China HDD Protection 0.1.13.0 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 178539a0d9800a3b770b7c54ebd1f40d4facf5c577c259cae441c537d615f13b
Precision 3450-China HDD Protection 0.1.13.0 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 178539a0d9800a3b770b7c54ebd1f40d4facf5c577c259cae441c537d615f13b
Latitude 5421 0.1.15.0 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 1af72c75afc536205fd1dbaa789e5c209429e3e5bbd0bc9831fc6c5e4bd4cab3
Latitude 5430 0.1.8.3 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 2be4781be7f3debf3c2ac5d0e01dfae6c204fb23cb5455c45a2818b88c163654
Latitude 9520 0.1.17.0 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 3d3150a82da8f1e143f85bfe50d894a735886c243b3dd93209b1346ad200c054
Latitude 5420 0.1.22.0 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 45ac9b658dc2bd2ae7a2feaa7f399961fb70f183e2603fbfc9a499d272a833b8
Precision 7670, Precision 7770 0.1.7.1 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 46addb141f1fc234e3bcc77f10f8d276f933e3377c5db50e4f1321337106c234
Inspiron 3020 0.1.0.0 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 632ae6150fad73ef8b3a3b9adee9efbed9429e5c400d26499ca82bfb6f29f23f
Inspiron 3020 0.1.0.0 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 632ae6150fad73ef8b3a3b9adee9efbed9429e5c400d26499ca82bfb6f29f23f
Inspiron 3020 0.1.0.0 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 632ae6150fad73ef8b3a3b9adee9efbed9429e5c400d26499ca82bfb6f29f23f
Precision 7560,Precision 7760 0.1.16.0 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 68270661ff7f6e553fe4a6502904d2d16f0e94317869c2d17a501453e13bd5fd
Latitude 7320, Latitude 7320, Latitude 7420, Latitude 7420, Latitude 7520 0.1.21.0 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 721a8f1b0510855485c033332a1499bd290088894ac9760fc23c8484ea7591b7
Inspiron 14 5410,Inspiron 14 5418,Inspiron 15 5510,Inspiron 15 5518,Vostro 14 5410,Vostro 15 5510 0.2.15.2 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 75d8d0e2ce3f001b2330ac20eb6f97220c5a12ea56e92bda834e2ed9c02a2959
Inspiron 15 3511, Vostro 15 3510 0.1.18.2 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 85d1e1cf6f5175d22ab262bc5034720287bfaf54e5a1b9074e624b106f627808
Latitude 5430 Rugged 0.1.13.2 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 94f826159bcbbd934e8fc64c2807b62e37bcc2c36ae8634c34de04d278cf54ee
Latitude 5430 Rugged 0.1.13.2 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c 94f826159bcbbd934e8fc64c2807b62e37bcc2c36ae8634c34de04d278cf54ee
OptiPlex 7090 UFF 0.1.15.0 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c aee366908494a2cc349954d5d3d90e655793b63d89e7300f258447a10f413520
Inspiron 5301, Vostro 5301 0.1.21.0 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c b2665b563f77f06537d58056470a3d0a493fc44ec8c82a5a286ce2b3e799b0e7
XPS 13 9365 0.2.24.0 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c befd809dc391328ad5553f72f6528c74c152fb51aef52738f2c7f5e10dcda3c4
Inspiron 15 3511, Vostro 15 3510 0.1.18.2 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c ccff42bc8795516de883265e3abae04e226f5ce2fefed5f26a1b5361732ad42b
Inspiron 3910-China HDD Protection 0.1.7.3 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c dccccb8c891fdfb772ce9ed8130b65897bff4ab6bc0f2e91055d169f528df4d1
Inspiron 3910-China HDD Protection 0.1.7.3 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c dccccb8c891fdfb772ce9ed8130b65897bff4ab6bc0f2e91055d169f528df4d1
Inspiron 3910-China HDD Protection 0.1.7.3 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c dccccb8c891fdfb772ce9ed8130b65897bff4ab6bc0f2e91055d169f528df4d1
Latitude 9420, Latitude 9420 0.1.16.2 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c dce6485962f9696dc5ac8dcdb92acf9c13dd275fd20c7629aeb89e36c1785380
Latitude 9420, Latitude 9420 0.1.16.2 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c dce6485962f9696dc5ac8dcdb92acf9c13dd275fd20c7629aeb89e36c1785380
Latitude 5420 0.1.22.0 Intel Setup e6a7a1ce-5881-4b49-80be-69c91811685c fd097b2327a983291c443da05b5f588491de06a3aa212c98a5f4bb8046241784

Potential impact

An attacker with high physical access can exploit this vulnerability to read the contents of stack memory or global memory. This information could help with explotation of other vulnerabilities in DXE to elevate privileges from ring 3 or ring 0 (depends on the operating system) to a DXE driver and execute arbitrary code. Malicious code installed as a result of this exploitation could survive operating system (OS) boot process and runtime, or modify NVRAM area on the SPI flash storage (to gain persistence). Additionally, threat actors could use this vulnerability to bypass OS security mechanisms (modify privileged memory or runtime variables), influence OS boot process, and in some cases allow an attacker to hook or modify EFI Runtime services.

Vulnerability description

Let's take XPS 13 9310's firmware (version: 0.3.11.0, module sha256: 10ff0c63534aad2bd5efe36d56f1f3efc6e7c59a4fc7cec66591f9194e364058) as an example.

The following code in the module actually allows leaking memory:

  • a call to a gRT->GetVariable() offset: 0xa0c0
  • a call to a gRT->SetVariable() offset: 0xa105
char __fastcall sub_9338(__int64 a1, unsigned __int64 a2)
{
  char *v2; // rax
  unsigned int *v3; // rbx
  int v4; // ecx
  unsigned __int64 v5; // rax
  char *v6; // r9
  unsigned __int64 v7; // rax
  unsigned __int64 v8; // rax
  unsigned __int8 v9; // r14
  __int64 v10; // rdx
  __int64 v11; // rcx
  unsigned __int16 v12; // ax
  __int64 v13; // r9
  unsigned __int16 v14; // dx
  char v15; // al
  unsigned __int64 v16; // rsi
  int v17; // eax
  char *v18; // rbx
  char v19; // al
  char *v20; // rax
  char *v21; // r8
  char *v22; // r8
  __int64 v23; // r15
  unsigned __int64 v24; // rdi
  __int16 v25; // ax
  char v26; // dl
  unsigned __int64 v27; // rbx
  char v28; // dl
  char v29; // dl
  unsigned int v30; // ebx
  char v31; // dl
  unsigned int v32; // ebx
  char v33; // dl
  char v34; // dl
  char v35; // dl
  unsigned int v36; // ebx
  char v37; // dl
  unsigned __int64 v38; // rax
  char v39; // bl
  unsigned __int64 v40; // rax
  unsigned __int8 *v41; // r8
  __int64 v42; // rax
  UINT32 v43; // ebx
  __int64 v44; // rax
  bool v45; // zf
  _BYTE *v46; // rax
  int v47; // ebx
  unsigned int v48; // r8d
  unsigned __int64 v49; // rax
  unsigned __int64 v50; // rbx
  unsigned __int64 v51; // r14
  char v52; // al
  unsigned __int64 v53; // rbx
  unsigned __int8 v54; // di
  __int64 v55; // rax
  unsigned __int64 i; // rdi
  __int64 v57; // rcx
  unsigned __int8 v58; // r8
  unsigned __int8 v59; // dl
  __int64 v60; // rax
  unsigned __int8 v61; // cl
  unsigned __int8 v62; // al
  unsigned __int8 v63; // di
  unsigned __int8 v64; // dl
  __int64 v65; // rax
  unsigned __int8 v66; // cl
  unsigned __int8 v67; // al
  char *v68; // r8
  __int64 v70; // [rsp+20h] [rbp-89h]
  __int64 v71; // [rsp+20h] [rbp-89h]
  __int64 v72; // [rsp+20h] [rbp-89h]
  __int64 v73; // [rsp+20h] [rbp-89h]
  __int64 v74; // [rsp+20h] [rbp-89h]
  __int64 v75; // [rsp+20h] [rbp-89h]
  __int64 v76; // [rsp+20h] [rbp-89h]
  __int64 v77; // [rsp+20h] [rbp-89h]
  __int64 v78; // [rsp+20h] [rbp-89h]
  __int64 v79; // [rsp+28h] [rbp-81h]
  __int64 v80; // [rsp+30h] [rbp-79h]
  UINTN DataSize; // [rsp+40h] [rbp-69h] BYREF
  char *v82; // [rsp+48h] [rbp-61h] BYREF
  char *v83; // [rsp+50h] [rbp-59h]
  int v84; // [rsp+58h] [rbp-51h] BYREF
  UINT32 Attributes; // [rsp+5Ch] [rbp-4Dh] BYREF
  UINT32 v86; // [rsp+60h] [rbp-49h] BYREF
  char v87[6]; // [rsp+68h] [rbp-41h] BYREF
  char v88; // [rsp+6Eh] [rbp-3Bh]
  void *DxeCpuInfoProtocol; // [rsp+70h] [rbp-39h] BYREF
  _BYTE v90[16]; // [rsp+78h] [rbp-31h] BYREF
  __int64 v91; // [rsp+88h] [rbp-21h] BYREF
  char Data[20]; // [rsp+90h] [rbp-19h] BYREF
  char v93; // [rsp+A4h] [rbp-5h]
  char v94; // [rsp+110h] [rbp+67h] BYREF
  unsigned __int64 v95; // [rsp+118h] [rbp+6Fh] BYREF
  int v96; // [rsp+120h] [rbp+77h] BYREF
  UINT32 v97; // [rsp+128h] [rbp+7Fh] BYREF

  v95 = a2;
  DataSize = 176i64;
  LOBYTE(v95) = 0;
  v96 = 0;
  qword_A4188 = 0i64;
  v2 = (gRT->GetVariable)(L"SetupVolatileData", &EFI_SETUP_VARIABLE_GUID, 0i64, &DataSize, byte_A4600);
  if ( v2 < 0 )
    return v2;
  v2 = (gBS->LocateProtocol)(&DXE_CPU_INFO_PROTOCOL_GUID, 0i64, &DxeCpuInfoProtocol);
  if ( v2 < 0 )
    return v2;
  sub_EBFC(&v95, &v94);
  v3 = *(DxeCpuInfoProtocol + 2);
  *(v3 + 3) = *(v3 + 3);
  *(v3 + 9) = *(*(DxeCpuInfoProtocol + 2) + 36i64);
  v4 = 100 * v95;
  v3[8] = 0;
  v3[6] = v4;
  sub_2A0(1u, 0i64, 0i64, &v84, 0i64);
  if ( (v84 & 0x800) != 0 )
    v5 = __readmsr(0xC80u);
  else
    LODWORD(v5) = v95;
  v6 = aEnabled;
  if ( (v5 & 0x80000000) == 0i64 )
    v6 = aDisabled;
  sub_6FC(qword_A4168, 0x464u, aA, v6);
  sub_6FC(qword_A4168, 0x1F7u, aA, *(v3 + 3));
  sub_6FC(qword_A4168, 0x1FCu, L"%d MHz", v3[6]);
  sub_6FC(qword_A4168, 0x1F9u, a0xX, *v3);
  sub_6FC(qword_A4168, 0xFCBu, aA, aNotImplemented);
  v7 = __readmsr(0x8Bu);
  v8 = ((HIDWORD(v7) << 32) | v7) >> 32;
  if ( v8 )
    sub_6FC(qword_A4168, 0xFCEu, asc_A2980, v8);
  sub_6FC(qword_A4168, 0xFD1u, L"%dCore(s) / %dThread(s)");
  v9 = 0;
  do
  {
    v10 = *(v3 + 9);
    v11 = 9i64 * v9;
    switch ( *(v11 + v10 + 1) )
    {
      case 1:
        v15 = *(v11 + v10 + 2);
        if ( v15 == 1 )
        {
          v13 = *(v11 + v10 + 3);
          v14 = 511;
        }
        else
        {
          if ( v15 != 2 )
            goto LABEL_26;
          v13 = *(v11 + v10 + 3);
          v14 = 514;
        }
        goto LABEL_19;
      case 2:
        v13 = *(v11 + v10 + 3);
        v14 = 517;
LABEL_19:
        if ( *(v3 + 22) == 1 )
        {
          sub_6FC(qword_A4168, v14, L"%d KB");
        }
        else
        {
          LODWORD(v70) = *(v3 + 22);
          sub_6FC(qword_A4168, v14, L"%d KB x %d", v13, v70);
        }
        goto LABEL_26;
      case 3:
        v12 = 520;
        break;
      case 4:
        v12 = 523;
        break;
      default:
        goto LABEL_26;
    }
    sub_6FC(qword_A4168, v12, L"%d MB");
LABEL_26:
    ++v9;
  }
  while ( v9 <= *(v3 + 44) );
  v16 = 0i64;
  v17 = sub_EB10() - &unk_806C0;
  if ( !v17 || (v18 = 0i64, v17 == 16) )
    v18 = aTigerlake;
  v19 = sub_EB3C();
  if ( v19 )
  {
    switch ( v19 )
    {
      case 1:
        v20 = aDt;
        break;
      case 2:
        v20 = aUlx;
        break;
      case 3:
        v20 = aHalo;
        break;
      default:
        v20 = 0i64;
        break;
    }
  }
  else
  {
    v20 = aUlt;
  }
  if ( v18 && v20 )
    sub_6FC(qword_A4168, 0xFC5u, L"%a %a", v18, v20);
  else
    sub_6FC(qword_A4168, 0xFC5u, aA, aUnknown);
  DataSize = 47i64;
  v2 = (gRT->GetVariable)(L"SetupCpuFeatures", &EFI_SETUP_VARIABLE_GUID, &Attributes, &DataSize, Data);
  if ( v2 >= 0 )
  {
    v21 = aSupported_1;
    if ( !Data[6] )
      v21 = aNotSupported_1;
    sub_D2F0(v90, 0xFui64, v21);
    sub_6FC(qword_A4168, 0x20Fu, aA, v90);
    v22 = aSupported_1;
    if ( !Data[8] )
      v22 = aNotSupported_1;
    sub_D2F0(v90, 0xFui64, v22);
    sub_6FC(qword_A4168, 0x212u, aA, v90);
    v2 = __readmsr(0x606u);
    v23 = 2i64 << ((v2 & 0xFu) - 1);
    if ( v23 )
    {
      v24 = __readmsr(0x614u);
      v25 = WORD2(v24) & 0x7FFF;
      if ( (v24 & 0x7FFF00000000i64) == 0 )
        v25 = 0x7FFF;
      LODWORD(v71) = (1000 * (v25 % v23) / v23);
      sub_6FC(qword_A4168, 0x320u, L"%d.%d", (v25 / v23), v71);
      LODWORD(v72) = (1000 * ((WORD1(v24) & 0x7FFFui64) % v23) / v23);
      sub_6FC(qword_A4168, 0x323u, L"%d.%d", (WORD1(v24) & 0x7FFFui64) / v23, v72);
      LODWORD(v73) = (1000 * ((v24 & 0x7FFF) % v23) / v23);
      sub_6FC(qword_A4168, 0x32Cu, L"%d.%d", ((v24 & 0x7FFF) / v23), v73);
      v95 = __readmsr(0x610u);
      LODWORD(v74) = (1000 * ((v95 & 0x7FFF) % v23) / v23);
      sub_6FC(qword_A4168, 0x326u, L"%d.%d", ((v95 & 0x7FFF) / v23), v74);
      LODWORD(v75) = (1000 * ((WORD2(v95) & 0x7FFF) % v23) / v23);
      sub_6FC(qword_A4168, 0x329u, L"%d.%d", ((WORD2(v95) & 0x7FFF) / v23), v75);
      v26 = byte_A3FC8;
      v27 = __readmsr(0x1ADu);
      v95 = v27;
      if ( !byte_A3FC8 )
        v26 = v27;
      byte_A3FC8 = v26;
      sub_6FC(qword_A4168, 0x397u, aD, v27);
      v28 = byte_A3FCD;
      if ( !byte_A3FCD )
        v28 = BYTE1(v27);
      byte_A3FCD = v28;
      sub_6FC(qword_A4168, 0x39Au, aD, BYTE1(v27));
      v29 = byte_A3FCF;
      if ( !byte_A3FCF )
        v29 = BYTE2(v27);
      byte_A3FCF = v29;
      sub_6FC(qword_A4168, 0x39Du, aD, BYTE2(v27));
      v30 = BYTE3(v27);
      v31 = byte_A3FC9;
      if ( !byte_A3FC9 )
        v31 = v30;
      byte_A3FC9 = v31;
      sub_6FC(qword_A4168, 0x3A0u, aD, v30);
      v32 = HIDWORD(v95);
      v33 = byte_A3FCC;
      if ( !byte_A3FCC )
        v33 = BYTE4(v95);
      byte_A3FCC = v33;
      sub_6FC(qword_A4168, 0x3A3u, aD, BYTE4(v95));
      v34 = byte_A3FCB;
      if ( !byte_A3FCB )
        v34 = BYTE1(v32);
      byte_A3FCB = v34;
      sub_6FC(qword_A4168, 0x3A6u, aD, BYTE1(v32));
      v35 = byte_A3FD0;
      if ( !byte_A3FD0 )
        v35 = BYTE2(v32);
      byte_A3FD0 = v35;
      sub_6FC(qword_A4168, 0x3A9u, aD, BYTE2(v32));
      v36 = HIBYTE(v32);
      v37 = byte_A3FCE;
      if ( !byte_A3FCE )
        v37 = v36;
      byte_A3FCE = v37;
      sub_6FC(qword_A4168, 0x3ACu, aD, v36);
      v38 = __readmsr(0xCEu);
      v39 = (HIDWORD(v38) >> 1) & 3;
      sub_6FC(qword_A4168, 0x266u, aD, ((HIDWORD(v38) >> 1) & 3) + 1);
      if ( v39 )
      {
        __readmsr(0x648u);
        sub_6FC(qword_A4168, 0x269u, L"Ratio:%d TAR:%d PL1:%d.%dW");
        __readmsr(0x649u);
        sub_6FC(qword_A4168, 0x26Cu, L"Ratio:%d TAR:%d PL1:%d.%dW");
        __readmsr(0x64Au);
        sub_6FC(qword_A4168, 0x26Fu, L"Ratio:%d TAR:%d PL1:%d.%dW");
        v95 = __readmsr(0x610u);
        LODWORD(v76) = (1000 * ((MEMORY[0xFEDC59A0] & 0x7FFF) % v23) / v23);
        sub_6FC(
          qword_A4168,
          0x278u,
          L"%d.%dW (MSR:%d.%d)",
          ((MEMORY[0xFEDC59A0] & 0x7FFF) / v23),
          v76,
          (v95 & 0x7FFF) / v23,
          (1000 * ((v95 & 0x7FFF) % v23) / v23));
        LODWORD(v80) = (1000 * ((WORD2(v95) & 0x7FFF) % v23) / v23);
        LODWORD(v79) = ((WORD2(v95) & 0x7FFF) / v23);
        LODWORD(v77) = (1000 * ((MEMORY[0xFEDC59A4] & 0x7FFF) % v23) / v23);
        sub_6FC(qword_A4168, 0x27Bu, L"%d.%dW (MSR:%d.%d)", ((MEMORY[0xFEDC59A4] & 0x7FFF) / v23), v77, v79, v80);
        v40 = __readmsr(0x64Cu);
        v41 = L"%d (Locked)";
        if ( (v40 & 0x80000000) == 0i64 )
          v41 = L"%d (Unlocked)";
        sub_6FC(qword_A4168, 0x275u, v41, v40);
      }
      DataSize = 8i64;
      v42 = (gRT->GetVariable)(L"CpuSetupVolatileData", &CPU_SETUP_VARIABLE_GUID, &v97, &DataSize, v87);
      v43 = v97;
      if ( v42 < 0 )
        v43 = 6;
      v97 = v43;
      v44 = sub_F470(&CPU_DATA_HOB_GUID);
      v45 = v44 == -24;
      v46 = (v44 + 24);
      qword_A4188 = v46;
      v88 = v45 ? 0 : ~*v46;
      (gRT->SetVariable)(L"CpuSetupVolatileData", &CPU_SETUP_VARIABLE_GUID, v43, 8i64, v87);
      v47 = *(&loc_5A10 + (MEMORY[0xC0000048] & 0xFFFFFFFE)) & 0xFFE;
      sub_2A0(0x15u, 0i64, 0i64, &v96, 0i64);
      if ( v96 == 38400000 )
        v48 = 300 * v47;
      else
        v48 = v96 == 24000000 ? (375 * v47) >> 1 : 0;
      LODWORD(v78) = v48 % 0x3E8;
      sub_6FC(qword_A4168, 0x1E0u, L"%d.%dMHz", (v48 / 0x3E8), v78);
      LOBYTE(v2) = sub_EB3C();
      if ( v2 == 3 )
      {
        v2 = (gBS->LocateProtocol)(&EFI_PI_MP_SERVICES_PROTOCOL_GUID, 0i64, &gEfiPiMpServicesProtocol);
        if ( v2 >= 0 )
        {
          v49 = __readmsr(0x35u);
          v50 = v49;
          v51 = v49;
          v52 = byte_A3FCA;
          v53 = v50 >> 16;
          if ( v53 < v51 )
            v52 = 1;
          byte_A3FCA = v52;
          v82 = sub_EC68(4 * v53);
          v2 = sub_EC68(8 * v53);
          v83 = v2;
          if ( v82 )
          {
            if ( v2 )
            {
              (*(gEfiPiMpServicesProtocol + 6))(gEfiPiMpServicesProtocol, &v91);
              v54 = 0;
              if ( v51 )
              {
                v55 = 0i64;
                do
                {
                  if ( v55 == v91 )
                    sub_8C94(&v82);
                  else
                    (*(gEfiPiMpServicesProtocol + 3))(gEfiPiMpServicesProtocol, sub_8C94, v55, 0i64, 0i64, &v82, 0i64);
                  v55 = ++v54;
                }
                while ( v54 < v51 );
              }
              for ( i = 0i64; i < v53; ++i )
                sub_6FC(qword_A4168, word_A2AB0[i], aD, v82[4 * i]);
              v57 = 1i64;
              v93 = 0;
              if ( v53 > 1 )
              {
                while ( BYTE1(*v82) == BYTE1(*&v82[4 * v57]) )
                {
                  if ( ++v57 >= v53 )
                    goto LABEL_100;
                }
                v93 = 1;
              }
LABEL_100:
              (gRT->SetVariable)(L"SetupCpuFeatures", &EFI_SETUP_VARIABLE_GUID, Attributes, 47i64, Data);
              if ( *(*(DxeCpuInfoProtocol + 2) + 66i64) )
              {
                v58 = -1;
                v59 = 0;
                if ( v53 )
                {
                  v60 = 0i64;
                  do
                  {
                    v61 = v82[4 * v60 + 1];
                    v62 = v58;
                    if ( v58 > v61 )
                      v62 = v61;
                    ++v59;
                    v58 = v62;
                    v60 = v59;
                  }
                  while ( v59 < v53 );
                }
                v63 = 0;
                v64 = 0;
                if ( v53 )
                {
                  v65 = 0i64;
                  do
                  {
                    v66 = v82[4 * v65];
                    v67 = v63;
                    if ( v63 < v66 )
                      v67 = v66;
                    ++v64;
                    v63 = v67;
                    v65 = v64;
                  }
                  while ( v64 < v53 );
                }
                DataSize = 654i64;
                (gRT->GetVariable)(             // <= first call (we can rewrite DataSize here)
                  L"CpuSetup",
                  &CPU_SETUP_VARIABLE_GUID,
                  &v86,
                  &DataSize,
                  &unk_A4760);
                byte_A4897 = v63;
                if ( v53 )
                {
                  v68 = v82;
                  do
                  {
                    *(&unk_A4760 + v16 + 545) = v68[4 * v16];
                    ++v16;
                  }
                  while ( v16 < v53 );
                }
                (gRT->SetVariable)(             // <= second call
                  L"CpuSetup",
                  &CPU_SETUP_VARIABLE_GUID,
                  v86,
                  DataSize,
                  &unk_A4760);
              }
              (gBS->FreePool)(v82);
              LOBYTE(v2) = (gBS->FreePool)(v83);
            }
          }
        }
      }
    }
  }
  return v2;
}

The gRT->SetVariable() service is called with the DataSize as an argument, which will be overwritten inside the gRT->GetVariable() service if the length of CpuSetup NVRAM variable is greater than 654.

Thus, a potential attacker can dump X - 654 bytes from the stack (or global memory) into CpuSetup NVRAM variable by setting CpuSetup NVRAM variable's size to X > 654.

To fix this vulnerability the DataSize must be re-initialized with the size of CpuSetup before calling gRT->SetVariable().

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 (YYYY-mm-dd)
Dell PSIRT is notified 2022-12-29
Dell PSIRT confirmed reported issue 2023-03-16
Dell PSIRT assigned CVE number 2023-06-15
Dell PSIRT provide patch release 2023-06-15
BINARLY public disclosure date 2023-06-21

Acknowledgements

Binarly REsearch Team

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