Skip to content

Vulnerability in BitStream_LE::Skip(size_t bits) #196

@cjee21

Description

@cjee21

BitStream_LE::Skip(size_t bits) is not implemented and forwards to Get(bits). However, Get(bits) only supports a maximum of 32 bits and has no checks for input of size_t HowMany. Code that uses BitStream_LE such as MediaInfoLib assumes Skip can skip any amount of bits as long as it does not exceed Remain.

void Skip(size_t bits)
{
Get(bits);
}

Examples:

BitStream*      BT; 
BT=new BitStream_LE;
void File__Analyze::Skip_BT(size_t Bits, const char* Name)
{
    INTEGRITY(Bits<=BT->Remain(), "Size is wrong", BT->Offset_Get())
    if (Trace_Activated)
    {
        if (Bits<=32) //TODO: in BitStream.h, handle >32 bit gets
            Param(Name, BT->Get(Bits));
        else
        {
            Param(Name, "(Data)");
            BT->Skip(Bits);
        }
    }
    else
        BT->Skip(Bits);
}
void File__Analyze::Trusted_IsNot (const char* Reason)
{
    if (Element[Element_Level].UnTrusted)
        return;

    //Enough data?
    if (!FrameIsAlwaysComplete && !Element[Element_Level].IsComplete && (Buffer_Size - (Buffer_Offset + Element_Offset + BS->Offset_Get() + BT->Offset_Get()) < 64))
    {
        Element_WaitForMoreData();
        return;
    }

    #if MEDIAINFO_TRACE
        Param(Reason, 0);
    #endif //MEDIAINFO_TRACE

    Element[Element_Level].UnTrusted=true;
    Synched=false;
    if (!Status[IsFilled] && Trusted>0)
    {
        Trusted--;
        if (Trusted == 0 && !Status[IsAccepted])
            Reject();
    }

    if (BS && (BS->Offset_Get() || BS->Remain()))
        BS->Skip(BS->Remain());
    else if (BT && (BT->Offset_Get() || BT->Remain()))
        BT->Skip(BT->Remain());
    else
        Element_Offset=Element_Size;
}

Calling Skip with bits greater than 32 has a high chance of occurring and will result in the following security issues (written by AI):

Security Impacts

The most critical security risks involve Information Disclosure and Denial of Service (DoS), particularly if the HowMany parameter is influenced by external, untrusted input (e.g., a field in a malicious file header).

1. Information Disclosure (Memory Leak)

  • The Mechanism: The Mask[HowMany] access is a classic Out-of-Bounds Read. Because Mask is a static array, an attacker might be able to read other sensitive constants or pointers stored near it in the binary's data segment by observing the masked output.
  • The Risk: Furthermore, because the boundary checks can be bypassed via integer overflow, the function may read bytes from the heap that were never intended to be part of the bit-stream, effectively leaking the contents of adjacent memory allocations.

2. Denial of Service (DoS)

  • The Mechanism: If an attacker provides a very large value for HowMany, the expression endbyte * 8 + (long)HowMany can overflow. This allows the function to bypass the Attach(NULL, 0) safety check.
  • The Risk: The function will then attempt to access ptr[1], ptr[2], etc., at an address that may be outside the allocated memory region. This results in a Segmentation Fault (SIGSEGV), causing the application to crash immediately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions