Header bannerHeader banner
Advisory ID:
BRLY-LOGOFAIL-2023-010

[BRLY-LOGOFAIL-2023-010] Null Pointer Dereference in DXE driver

June 20, 2024
Severity:
Medium
CVSS Score
6
Public Disclosure Date:
June 19, 2024

Summary

Binarly REsearch Team has discovered a Null Pointer Dereference vulnerability in DXE driver. Unchecked DqtCount leads to null pointer dereference during JPEG file processing in Insyde firmware.

Vendors Affected

Lenovo
Insyde

Affected Products

Yoga 7 14IAL7

Potential Impact

The impact of this vulnerability differs depending on whether the zero page is mapped or not. In the case where the zero page is mapped, it will lead to undefined or unexpected behaviour. Whereas, in the case where the zero page is not mapped, the vulnerability will lead to a Denial of Service (DoS).

Summary

Binarly REsearch Team has discovered a Null Pointer Dereference vulnerability in DXE driver. Unchecked DqtCount leads to null pointer dereference during JPEG file processing in Insyde firmware.

Vulnerability Information

     
  • BINARLY internal vulnerability identifier: BRLY-LOGOFAIL-2023-010  
  • Insyde PSIRT assigned CVE identifier: CVE-2023-40238  
  • CVSS v3.1: 6.0 Medium AV:L/AC:L/PR:H/UI:N/S:C/C:N/I:N/A:H

Affected modules with confirmed impact by Binarly REsearch Team

Module name Module GUID Module SHA256
JpegDecoderDxe 2707e46d-dbd7-41c2-9c04-c9fdb8bad86c 2d84dc4c04ebb70719f86f8c9053cab57f4f537f23648192bebc83d397732e2e

Potential impact

The impact of this vulnerability differs depending on whether the zero page is mapped or not. In the case where the zero page is mapped, it will lead to undefined or unexpected behaviour. Whereas, in the case where the zero page is not mapped, the vulnerability will lead to a Denial of Service (DoS).

Vulnerability description

The pseudocode of the vulnerable function is shown below:

__int64 __fastcall InitJfif(JfifData *Image, __int64 ImageSize)
{
  char *ImagePtr; // rbx
  char *v5; // rdi
  int v6; // eax
  _BYTE *v7; // r8
  unsigned int Index; // r9d
  int DqtCount; // edx
  unsigned __int8 v10; // al
  __int64 v11; // rcx
  __int64 v12; // rdx
  int v13; // edx
  char v14; // r8
  __int64 result; // rax
  unsigned __int64 Skip; // rax

  sub_310(&JfifData1, 3064i64, 0i64);
  if ( LOWORD(Image->SOI) != 0xD8FF )
    return 1i64;
  ImagePtr = &Image->SOI + 2;
  JfifData1.SOI = Image;
  v5 = Image + ImageSize;
  if ( ImagePtr >= v5 )
    return 0i64;
  while ( 1 )
  {
    if ( *ImagePtr == -1 )
    {
      v6 = ImagePtr[1];
      if ( v6 )
        break;
    }
    Skip = 1i64;
LABEL_40:
    ImagePtr += Skip;
    if ( ImagePtr >= v5 )
      return 0i64;
  }
  if ( v6 > 0xC0u && v6 != 0xC4 && v6 <= 0xCFu )
    return 6i64;
  switch ( v6 )
  {
    case 0xC0:
      qword_2218 = ImagePtr;
      result = sub_62C(ImagePtr);
LABEL_35:
      if ( result )
        return result;
      goto LABEL_36;
    case 0xC4:
      result = sub_71C(ImagePtr);
      goto LABEL_35;
    case 0xDA:                                  // JPEG_SOS
      JfifData1.field_10 = ImagePtr;
      v12 = ImagePtr[3] + (ImagePtr[2] << 8);
      if ( ((ImagePtr[4] - 1) & 0xFD) != 0 || ImagePtr[(v12 - 1)] || ImagePtr[v12] != 63 || ImagePtr[(v12 + 1)] )
        return 5i64;
      v13 = 0;
      if ( ImagePtr[4] )
      {
        while ( ImagePtr[2 * v13 + 5] <= 3u )
        {
          v14 = ImagePtr[2 * v13 + 6];
          if ( (v14 & 0xF0u) > 0x10 || (v14 & 0xFu) > 1 )
            break;
          if ( ++v13 >= ImagePtr[4] )
            goto LABEL_36;
        }
        return 5i64;
      }
      goto LABEL_36;
  }
  if ( v6 != 219 )
  {
    switch ( v6 )
    {
      case 221:
        LOWORD(JfifData1.field_28) = ImagePtr[5] + (ImagePtr[4] << 8);
        break;
      case 224:
        JfifData1.field_8 = ImagePtr;
        break;
      case 254:
        JfifData1.field_18 = ImagePtr;
        break;
    }
    goto LABEL_36;
  }
  v7 = ImagePtr + 4;
  Index = 0;
  // BRLY-LOGOFAIL-2023-010: Unchecked DqtCount leads to null pointer dereference
  DqtCount = (ImagePtr[3] - 2 + (ImagePtr[2] << 8)) / 65;
  if ( !DqtCount )
  {
LABEL_36:
    if ( ImagePtr[2] == -1 )
      Skip = 2i64;
    else
      Skip = (ImagePtr[2] << 8) + ImagePtr[3] + 2i64;
    goto LABEL_40;
  }
  while ( 1 )
  {
    v10 = *v7 & 0xF;
    if ( v10 > 3u || (*v7 & 0xF0) != 0 )
      return 3i64;
    v11 = (v7 + 1);
    v7 += 65;
    ++Index;
    JfifData1.DQT[v10] = v11;
    if ( Index >= DqtCount )
      goto LABEL_36;
  }
}

DqtCount is user controllable and unchecked variable. When DqtCount < 4 , JfifData1.DQT will contain less than 4 initialized elements (the rest of them will be equal to zero).

So, unchecked usage of pointers taken from JfifData1.DQT:

...
v5 = &unk_2060;
v6 = 8i64;
DQTPtr = JfifData1.DQT[byte_2119[16 * i]];
v8 = &v25[64 * i];
v9 = v8;
...
v12 = *(v11 + DQTPtr);

will cause a null pointer dereference *(v11 + DQTPtr). If the zero page is not mapped, it will cause a DoS during the boot process. If zero page is mapped, it will result in undefined behaviour.

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)
Lenovo PSIRT is notified 2023-06-21
Lenovo ID (LEN-132940) is assigned 2023-06-22
CERT/CC is notified 2023-07-10
Insyde PSIRT confirmed reported issues 2023-09-10
Insyde PSIRT assigned CVE ID 2023-11-27
Insyde advisory release date 2023-12-06
BINARLY public disclosure date 2024-06-19

Acknowledgements

Binarly REsearch Team

Tags
Vulnerability
supply chain
FWHunt
See if you are impacted now with our Firmware Vulnerability Scanner