Skip to content

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

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions