Skip to content

Remote Memory Exposure in iSCSI DXE

Low
jkmathews published GHSA-8522-69fh-w74x Mar 14, 2025

Package

NetworkPkg/IScsiDxe (EDK2)

Affected versions

<=202502

Patched versions

None

Description

Copied from https://bugzilla.tianocore.org/show_bug.cgi?id=4206

Summary

A malicious iSCSI target can cause a remote BIOS to reveal its memory contents with a specially crafted R2T message.

Details

The following function is used to process iSCSI "Ready To Transfer" (R2T) PDUs that were received from the iSCSI target. An offset and length value are extracted from the R2T header, which are both 32-bit unsigned integers.

Below, the highlighted line may be subject to an integer overflow if either Offset or DesiredLength are excessively large. This would bypass the input validation, and would result in the Data being advanced beyond the end of the packet's output data buffer.

EFI_STATUS
IScsiOnR2TRcvd (
  IN NET_BUF                                         *Pdu,
  IN ISCSI_TCB                                       *Tcb,
  IN UINT64                                          Lun,
  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *Packet
  )
{
  ...
  R2THdr = (ISCSI_READY_TO_TRANSFER *) NetbufGetByte (Pdu, 0, NULL);
  ...
  R2THdr->BufferOffset = NTOHL (R2THdr->BufferOffset);
  R2THdr->DesiredDataTransferLength = NTOHL (R2THdr->DesiredDataTransferLength);
  ...
  XferContext->Offset             = R2THdr->BufferOffset;
  XferContext->DesiredLength      = R2THdr->DesiredDataTransferLength;

  // NCC: integer overflow on following line
  if (((XferContext->Offset + XferContext->DesiredLength) > Packet->OutTransferLength) || 
      (XferContext->DesiredLength > Tcb->Conn->Session->MaxBurstLength))
  {  
    return EFI_PROTOCOL_ERROR;
  }

  // NCC: Data point may be advanced too far if Offset is large
  Data    = (UINT8 *) Packet->OutDataBuffer + XferContext->Offset;
  Status  = IScsiSendDataOutPduSequence (Data, Lun, Tcb);
  ...

EDK2/NetworkPkg/IScsiDxe/IScsiProto.c

The tainted Data pointer is then passed to the following function, which builds and sends the response message. The response message may consist of multiple PDUs, which are generated from Data by the IScsiGenerateDataOutPduSequence() function and transmitted by the TcpIoTransmit() function.

Additionally, note that the Offset and DesiredLength fields in the Tcb->XferContext structure are tainted and are attacker-controlled.

EFI_STATUS
IScsiSendDataOutPduSequence (
  IN UINT8      *Data,
  IN UINT64     Lun, 
  IN ISCSI_TCB  *Tcb 
  )
{
  ...
  // Generate the Data Out PDU sequence.
  DataOutPduList = IScsiGenerateDataOutPduSequence (Data, Tcb, Lun);
  ...
  // Send the Data Out PDU's one by one.
  NET_LIST_FOR_EACH (Entry, DataOutPduList) {
    Pdu = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
    Status = TcpIoTransmit (&Tcb->Conn->TcpIo, Pdu);
    ...
  }
  ...

Inside IScsiGenerateDataOutPduSequence(), we see a fairly straight forward while-loop that walks Data up to its maximum length of XferContext->DesiredLength (an attacker-controlled value), breaking it down into PDUs that are each no larger than Conn->MaxRecvDataSegmentLength.

LIST_ENTRY *
IScsiGenerateDataOutPduSequence (
  IN UINT8      *Data,
  IN ISCSI_TCB  *Tcb,
  IN UINT64     Lun
  )
{
  LIST_ENTRY          *PduList;
  UINT32              DataSN;
  UINT32              DataLen;
  NET_BUF             *DataOutPdu;
  ISCSI_CONNECTION    *Conn;
  ISCSI_XFER_CONTEXT  *XferContext;
  UINT8               *DataOutPacket;

  PduList = AllocatePool (sizeof (LIST_ENTRY));
  ...
  InitializeListHead (PduList);
  ...
  Conn        = Tcb->Conn;
  ...
  XferContext = &Tcb->XferContext;

  while (XferContext->DesiredLength > 0) {
    // Determine the length of data this Data Out PDU can carry.
    DataLen = MIN (XferContext->DesiredLength, Conn->MaxRecvDataSegmentLength);

    // Create a Data Out PDU.
    DataOutPdu = IScsiNewDataOutPdu (Data, DataLen, DataSN, Tcb, Lun);
    ...
    InsertTailList (PduList, &DataOutPdu->List);

    // Update the context and DataSN.
    Data += DataLen;
    XferContext->Offset += DataLen;
    XferContext->DesiredLength -= DataLen;
    DataSN++;
  }
  ...

Based on this, it appears that the Data pointer can be read out of bounds, and the OOB memory will be copied into the response PDU and transmitted to the iSCSI target. This constitutes a remote memory exfiltration vulnerability.

PoC

n/a

Impact

What kind of vulnerability is it? Who is impacted?

Severity

Low

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
High
User interaction
Required
Scope
Unchanged
Confidentiality
None
Integrity
Low
Availability
Low

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:U/C:N/I:L/A:L

CVE ID

CVE-2025-2295

Weaknesses

Integer Overflow or Wraparound

The product performs a calculation that can produce an integer overflow or wraparound, when the logic assumes that the resulting value will always be larger than the original value. This can introduce other weaknesses when the calculation is used for resource management or execution control. Learn more on MITRE.