Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

FeedsKontaktDatenschutz© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2026-3304 — # Reproduktionslabor für CVE-2026-3304, eine Multer-async-fileFilter-Race-Condition, die durch verwaiste temporäre Dateien zur Erschöpfung des Speicherplatzes führt. Enthält anfällige und gepatchte Docker-Server, Exploit-Skripte und Root-Cause-Analyse. | Kitploit
Tools/GitHubGitHub/mkway/cve-2026-3304
SchwachstellenanalyseExploitationWebsicherheitLernen & BildungLabs & Praxis
GitHubmkway/cve-2026-3304

CVE-2026-3304

# Reproduktionslabor für CVE-2026-3304, eine Multer-async-fileFilter-Race-Condition, die durch verwaiste temporäre Dateien zur Erschöpfung des Speicherplatzes führt. Enthält anfällige und gepatchte Docker-Server, Exploit-Skripte und Root-Cause-Analyse.

Repository anzeigen
22vor 7 MonatenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2026-3304 Laborumgebung

Nur für Bildungs- und Forschungszwecke. Angriffe auf Systeme ohne Autorisierung sind illegal.

Diese Laborumgebung wurde durch die Analyse des Multer-2.1.0-Patches und seines offiziellen Testcodes erstellt. Der verwundbare Server repliziert exakt die im Patch-Test beschriebenen Bedingungen, und der gepatchte Server führt Multer 2.1.0 aus, um zu bestätigen, dass der Fix funktioniert.

Schwachstellenübersicht

FeldDetails
CVECVE-2026-3304
ZielMulter < 2.1.0 (Node.js multipart/form-data Middleware)
TypDoS — Verwaiste Datei (unvollständige Bereinigung temporärer Dateien)
CWECWE-459: Unvollständige Bereinigung
CVSS 4.08.7 HOCH
Gepatchte VersionMulter 2.1.0

Eine fehlerhafte Multipart-Anfrage mit einem fehlenden name-Attribut bei einem Dateiteil führt dazu, dass Multer eine temporäre Datei auf der Festplatte erstellt, diese aber nie bereinigt. Wiederholte Anfragen erschöpfen den Speicherplatz, was zu einem Denial of Service führt.


Root-Cause-Analyse

Die Schwachstelle entsteht im fileFilter-Callback-Behandlungsablauf innerhalb von multer/lib/make-middleware.js.

Kernproblem: setImmediate-Timing + fehlende errorOccured-Prüfung

Wenn Multer eine Multipart-Anfrage Teil für Teil streamt und parst, läuft die folgende Sequenz ab:

[Parsing-Ereignissequenz — verwundbare Version]

1. Teil-1-Header empfangen
   → fileFilter(req, file, cb) aufgerufen
   → setImmediate(cb) → Callback auf den nächsten Event-Loop-Tick verschoben

2. Teil-1-Body empfangen
   → /tmp/uploads/<uuid> geöffnet, Daten werden geschrieben

3. Teil-2-Header empfangen (name-Attribut fehlt)
   → Multer erkennt 'name fehlt'
   → errorOccured = true  ← Fehlerflag gesetzt
   → abortWithCode('LIMIT_FIELD_KEY') aufgerufen → HTTP 500 geplant

4. setImmediate-Callback feuert (nächster Event-Loop-Tick)
   → fileFilter-Ergebnis: includeFile = true (normaler Ablauf)
   → [BUG] errorOccured-Flag wird NICHT geprüft
   → storage._handleFile() aufgerufen → temporäre Datei auf der Festplatte gespeichert

5. HTTP-500-Antwort gesendet
   → temporäre Datei bleibt auf der Festplatte (verwaiste Datei)

Verwundbarer Code (make-middleware.js — Multer < 2.1.0)

// fileFilter-Abschluss-Callback (über setImmediate verschoben)
fileFilter(req, file, function (err, includeFile) {
  if (err) {
    appender.removePlaceholder(placeholder)
    return abortWithError(uploadedFiles, err)
  }

  if (!includeFile) {
    appender.removePlaceholder(placeholder)
    return fileStream.resume()
  }

  // ❌ errorOccured wird hier nie geprüft
  //    selbst wenn beim Parsen von Teil 2 ein Fehler gesetzt wurde, wird die Ausführung fortgesetzt
  storage._handleFile(req, file, function (err, info) {
    if (err) {
      appender.removePlaceholder(placeholder)
      return abortWithError(uploadedFiles, err)
    }
    // temporäre Datei wird in uploadedFiles registriert und auf der Festplatte belassen
    appender.replacePlaceholder(placeholder, assign(file, info))
    checkFinished()
  })
})

Warum ist setImmediate das Problem?

Das Umschließen von fileFilter mit setImmediate verschiebt dessen Callback auf den nächsten Event-Loop-Tick. In diesem Fenster parst busboy (der Multipart-Parser) weiter die Header des nächsten Teils, entdeckt das fehlende name und setzt errorOccured = true. Wenn der Callback fortgesetzt wird, ist der Fehlerzustand bereits gesetzt — aber der Code prüft ihn nie, also wird storage._handleFile bedingungslos aufgerufen und die temporäre Datei auf die Festplatte geschrieben.


Patch-Code-Analyse (Multer 2.1.0)

Fix-Commit: 739919097d

Eine einzelne if (errorOccured)-Absicherung wurde unmittelbar nach dem Eintritt in den fileFilter-Callback hinzugefügt, bevor storage._handleFile erreicht wird.

// fileFilter-Abschluss-Callback (Multer 2.1.0)
fileFilter(req, file, function (err, includeFile) {
  if (err) {
    appender.removePlaceholder(placeholder)
    return abortWithError(uploadedFiles, err)
  }

  // ✅ [PATCH] errorOccured vor dem Fortfahren prüfen
  if (errorOccured) {
    appender.removePlaceholder(placeholder)
    return fileStream.resume()   // Stream leeren — keine Datei auf die Festplatte geschrieben
  }

  if (!includeFile) {
    appender.removePlaceholder(placeholder)
    return fileStream.resume()
  }

  storage._handleFile(req, file, function (err, info) {
    if (err) {
      appender.removePlaceholder(placeholder)
      return abortWithError(uploadedFiles, err)
    }
    appender.replacePlaceholder(placeholder, assign(file, info))
    checkFinished()
  })
})

Zusammenfassung der Änderungen

ElementVerwundbar (< 2.1.0)Gepatcht (2.1.0)
errorOccured-Prüfung❌ Nicht geprüft✅ Sofort beim Callback-Eintritt geprüft
_handleFile bei Fehler aufgerufenJaBlockiert
Bereinigung temporärer Dateien❌ Fehlt✅ Über fileStream.resume()
Verwaiste Dateien pro Anfrage10

Warum fileStream.resume() bereinigt: Der Aufruf von fileStream.resume() leert und verwirft den Stream, ohne ihn an DiskStorage zu übergeben, sodass keine Datei geschrieben wird und nichts auf der Festplatte zurückbleibt.


Offizieller Patch-Testcode

Das Multer-Team hat den folgenden Mocha-Test in den 2.1.0-Patch aufgenommen, um den Fix zu verifizieren. Dieser Test wurde zur Vorlage für diese Laborumgebung — der verwundbare Server repliziert das hier beschriebene exakte Setup (setImmediate fileFilter + fehlerhafte Multipart-Anfrage), und das erwartete Verhalten wird sowohl gegen die verwundbare als auch gegen die gepatchte Version verifiziert.

/* eslint-env mocha */

var assert = require('assert')
var fs = require('fs')
var os = require('os')
var path = require('path')
var http = require('http')

var express = require('express')
var multer = require('../')

describe('async fileFilter cleanup', function () {
  it('does not leave orphan files when request aborts with missing field name', function (done) {
    var uploadDir = fs.mkdtempSync(path.join(os.tmpdir(), 'multer-orphan-'))
    var app = express()

    // Vulnerability trigger: async fileFilter via setImmediate
    var upload = multer({
      dest: uploadDir,
      fileFilter: function (req, file, cb) {
        setImmediate(function () { cb(null, true) })
      }
    })

    app.post('/upload', upload.any(), function (req, res) {
      res.json({ success: true })
    })

    // Error handler: respond with 400
    app.use(function (err, req, res, next) {
      res.status(400).json({ error: err.code })
    })

    var server = app.listen(0, function () {
      var port = server.address().port
      var boundary = 'TestBound'

      // Malicious body: Part 1 valid, Part 2 missing name attribute
      var body =
        '--' + boundary + '\r\n' +
        'Content-Disposition: form-data; name="f"; filename="a.bin"\r\n' +
        'Content-Type: application/octet-stream\r\n\r\nORPHAN FILE DATA\r\n' +
        '--' + boundary + '\r\n' +
        'Content-Disposition: form-data; filename="b.bin"\r\n' +   // ← name= missing
        'Content-Type: application/octet-stream\r\n\r\nx\r\n' +
        '--' + boundary + '--\r\n'

      var req = http.request({
        hostname: 'localhost',
        port: port,
        path: '/upload',
        method: 'POST',
        headers: {
          'Content-Type': 'multipart/form-data; boundary=' + boundary,
          'Content-Length': Buffer.byteLength(body)
        }
      }, function (res) {
        res.resume()
        res.on('end', function () {
          setTimeout(function () {
            var files = fs.readdirSync(uploadDir)

            // Assert 1: server must respond with 400 (error)
            assert.strictEqual(res.statusCode, 400)
Tool herunterladen