Header bannerHeader banner

[BRLY-2022-039] SMRAM memory contents leak / information disclosure vulnerability in SMM driver (SMRAM read).

November 16, 2023

Summary

BINARLY efiXplorer team identified an SMM memory contents leak / information disclosure vulnerability, which allows an attacker to read portions of SMRAM memory. This in turn could help building a successful attack vector exploiting SMM memory corruption vulnerability.

Vulnerability Information

  • BINARLY internal vulnerability identifier: BRLY-2022-039
  • Intel PSIRT assigned CVE identifier: CVE-2023-22444
  • Intel advisory: INTEL-SA-00917
  • CVSS v3.1: 6.0 Medium AV:L/AC:L/PR:H/UI:N/S:C/C:H/I:N/A:N

Affected Intel firmware confirmed to be impacted by Binarly team

Device/Firmware File Name SHA256 (File PE32 section) File GUID
Intel NUC M15 / BCTGL357 v0077 (Latest) SmbiosDmiEdit bc5e6a7e8ba2d10413ba767089914ad1a797c23cbe7e2c1f8ff800112538d657 E2A74738-8934-48F5-8412-99E948C8DC1B

Potential impact

An attacker can exploit this vulnerability to elevate privileges from ring 0 to ring -2, execute arbitrary code in System Management Mode - an evironment more privileged than operating system (OS) and completely isolated from it. Running arbitrary code in SMM additionally bypasses SMM-based SPI flash protections against modifications, which can help an attacker to install a firmware backdoor/implant into the BIOS. Such a malicious firmware code in the BIOS could persist across operating system re-installs. Additionally, this vulnerability potentially could be used by threat actors to bypass security mechanisms provided by the UEFI firmware (for example, Secure Boot and some types of memory isolation for hypervisors).

Vulnerability description

The vulnerability exists in the function located at offset 0x1D28.This function located inside SW SMI handler and the SMI handler registered the following way:

...
    result = gSmst_0->SmmLocateProtocol(&EFI_SMM_SW_DISPATCH2_PROTOCOL_GUID, 0, &EfiSmmSwDispatch2Protocol);
    if ( result >= 0 )
    {
      RegisterContext.SwSmiInputValue = 0x50;
      result = EfiSmmSwDispatch2Protocol->Register(
                 EfiSmmSwDispatch2Protocol,
                 SwSmiHandler,
                 &RegisterContext,
                 &DispatchHandle);
      if ( result >= 0 )
      {
        RegisterContext.SwSmiInputValue = 0x51;
        result = EfiSmmSwDispatch2Protocol->Register(
                   EfiSmmSwDispatch2Protocol,
                   SwSmiHandler,
                   &RegisterContext,
                   &DispatchHandle);
        if ( result >= 0 )
        {
          RegisterContext.SwSmiInputValue = 0x52;
          result = EfiSmmSwDispatch2Protocol->Register(
                     EfiSmmSwDispatch2Protocol,
                     SwSmiHandler,
                     &RegisterContext,
                     &DispatchHandle);
          if ( result >= 0 )
          {
            RegisterContext.SwSmiInputValue = 0x53;
            Status = (EfiSmmSwDispatch2Protocol->Register)(
                       EfiSmmSwDispatch2Protocol,
                       SwSmiHandler,
                       &RegisterContext,
                       &DispatchHandle);
            if ( Status < 0 )
              return Status;
            return Result;
          }
        }
      }
    }
  }
  return result;
}

The pseudocode for the vulnerable function is shown below:

char __fastcall WriteOnceStatusSetVar(char value1, char value2, __int16 value3)
{
  char Result;
  unsigned __int8 Index;
  _BYTE *table_ptr;
  __int64 Counter;
  __int64 Status;
  EFI_RUNTIME_SERVICES *RuntimeServices;
  UINTN Size;
  char WriteOnceStatusData[64];
  UINTN DataSize;

  DataSize = 64;
  Result = 0;
  Index = 0;
  table_ptr = &gTable;
  Counter = 2;
  Status = gRT->GetVariable(L"WriteOnceStatus", &EFI_SMBIOS_NVRAM_DATA_GUID, 0, &DataSize, WriteOnceStatusData);
  do
  {
    if ( *(table_ptr - 1) == value1 && *table_ptr == value2 && table_ptr[1] )
    {
      if...                                     // will not be executed is Status != EFI_SUCCESS
      if ( Index < 0x10 && !Result )
      {
        RuntimeServices = gRT;
        Size = DataSize;
        WriteOnceStatusData[4 * Index] = value1;
        WriteOnceStatusData[4 * Index + 1] = value2;
        *&WriteOnceStatusData[4 * Index + 2] = value3;
        Status = (RuntimeServices->SetVariable)(
                   L"WriteOnceStatus",
                   &EFI_SMBIOS_NVRAM_DATA_GUID,
                   7,
                   Size,
                   WriteOnceStatusData);
      }
    }
_Next:
    table_ptr += 3;
    --Counter;
  }
  while ( Counter );
  return Result;
}

As we can see from the pseudocode, for the WriteOnceStatus variable gRT->SetVariable() service is called with the DataSize value, which can be overwritten inside the gRT->GetVariable() service.

Thus, a potential attacker can write X - 64 bytes from the SMRAM stack region to NVRAM if writes any buffer of length X > 64 to the WriteOnceStatus NVRAM variable before triggering the SW SMI handler.

In order to fix this vulnerability, the DataSize variable must be initialized before gRT->SetVariable().

Disclosure timeline

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.

Disclosure Activity Date (YYYY-MM-dd)
Intel PSIRT is notified 2022-12-19
Intel PSIRT assigned CVE number 2023-02-28
Intel PSIRT provide patch release 2023-08-08
BINARLY public disclosure date 2023-11-16

Acknowledgements

BINARLY efiXplorer team

Tags
No items found.