Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-3304 — # Laboratorio di riproduzione per CVE-2026-3304, una condizione di gara in fileFilter asincrono di Multer che causa l'esaurimento del disco tramite file temporanei orfani. Include server Docker vulnerabili e corretti, script di exploit e analisi della causa principale. | Kitploit
Strumenti/GitHubGitHub/mkway/cve-2026-3304
Analisi delle VulnerabilitàExploitSicurezza WebApprendimento e FormazioneLab e Pratica
GitHubmkway/cve-2026-3304

CVE-2026-3304

# Laboratorio di riproduzione per CVE-2026-3304, una condizione di gara in fileFilter asincrono di Multer che causa l'esaurimento del disco tramite file temporanei orfani. Include server Docker vulnerabili e corretti, script di exploit e analisi della causa principale.

Vedi Repository
287 mesi faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Ambiente di Laboratorio CVE-2026-3304

Solo per scopi educativi e di ricerca. Attaccare sistemi senza autorizzazione è illegale.

Questo ambiente di laboratorio è stato costruito analizzando la patch di Multer 2.1.0 e il suo codice di test ufficiale. Il server vulnerabile replica le condizioni esatte descritte nel test della patch, e il server corretto esegue Multer 2.1.0 per confermare che la correzione funziona.

Panoramica della Vulnerabilità

CampoDettagli
CVECVE-2026-3304
TargetMulter < 2.1.0 (middleware multipart/form-data di Node.js)
TipoDoS — File Orfano (pulizia incompleta dei file temporanei)
CWECWE-459: Pulizia Incompleta
CVSS 4.08.7 ALTO
Versione CorrettaMulter 2.1.0

Una richiesta multipart malformata con un attributo name mancante su una parte di file fa sì che Multer crei un file temporaneo su disco senza mai pulirlo. Richieste ripetute esauriscono lo spazio su disco, provocando un Denial of Service.


Analisi della Causa Radice

La vulnerabilità ha origine nel flusso di gestione del callback fileFilter all'interno di multer/lib/make-middleware.js.

Problema principale: temporizzazione di setImmediate + controllo errorOccured mancante

Quando Multer trasmette e analizza una richiesta multipart parte per parte, si verifica la seguente sequenza:

[Sequenza degli eventi di parsing — versione vulnerabile]

1. Intestazione della Parte 1 ricevuta
   → fileFilter(req, file, cb) chiamato
   → setImmediate(cb) → callback rimandato al tick successivo del ciclo di eventi

2. Corpo della Parte 1 ricevuto
   → /tmp/uploads/<uuid> aperto, i dati iniziano a essere scritti

3. Intestazione della Parte 2 ricevuta (attributo name mancante)
   → Multer rileva 'name mancante'
   → errorOccured = true  ← flag di errore impostato
   → abortWithCode('LIMIT_FIELD_KEY') chiamato → HTTP 500 pianificato

4. Il callback di setImmediate viene eseguito (tick successivo del ciclo di eventi)
   → risultato di fileFilter: includeFile = true (flusso normale)
   → [BUG] il flag errorOccured NON viene controllato
   → storage._handleFile() chiamato → file temporaneo salvato su disco

5. Risposta HTTP 500 inviata
   → il file temporaneo rimane su disco (file orfano)

Codice vulnerabile (make-middleware.js — Multer < 2.1.0)

// callback di completamento di fileFilter (rimandato tramite setImmediate)
fileFilter(req, file, function (err, includeFile) {
  if (err) {
    appender.removePlaceholder(placeholder)
    return abortWithError(uploadedFiles, err)
  }

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

  // ❌ errorOccured non viene mai controllato qui
  //    anche se è stato impostato un errore durante il parsing della Parte 2, l'esecuzione continua
  storage._handleFile(req, file, function (err, info) {
    if (err) {
      appender.removePlaceholder(placeholder)
      return abortWithError(uploadedFiles, err)
    }
    // il file temporaneo viene registrato in uploadedFiles e lasciato su disco
    appender.replacePlaceholder(placeholder, assign(file, info))
    checkFinished()
  })
})

Perché setImmediate è il problema?

Avvolgere fileFilter con setImmediate rimanda il suo callback al tick successivo del ciclo di eventi. In quella finestra, busboy (il parser multipart) continua ad analizzare le intestazioni della parte successiva, scopre il name mancante e imposta errorOccured = true. Quando il callback riprende, lo stato di errore è già impostato — ma il codice non lo controlla mai, quindi storage._handleFile viene chiamato incondizionatamente e il file temporaneo viene scritto su disco.


Analisi del Codice della Patch (Multer 2.1.0)

Commit di correzione: 739919097d

Un singolo controllo if (errorOccured) è stato aggiunto immediatamente dopo l'ingresso del callback fileFilter, prima che venga raggiunto storage._handleFile.

// callback di completamento di fileFilter (Multer 2.1.0)
fileFilter(req, file, function (err, includeFile) {
  if (err) {
    appender.removePlaceholder(placeholder)
    return abortWithError(uploadedFiles, err)
  }

  // ✅ [PATCH] Controlla errorOccured prima di procedere
  if (errorOccured) {
    appender.removePlaceholder(placeholder)
    return fileStream.resume()   // drena lo stream — nessun file scritto su disco
  }

  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()
  })
})

Riepilogo delle modifiche

ElementoVulnerabile (< 2.1.0)Corretto (2.1.0)
Controllo errorOccured❌ Non controllato✅ Controllato immediatamente all'ingresso del callback
_handleFile chiamato in caso di erroreSìBloccato
Pulizia del file temporaneo❌ Mancante✅ Tramite fileStream.resume()
File orfani per richiesta10

Perché fileStream.resume() pulisce: Chiamare fileStream.resume() drena e scarta lo stream senza passarlo a DiskStorage, quindi nessun file viene scritto e nulla rimane su disco.


Codice di Test Ufficiale della Patch

Il team di Multer ha incluso il seguente test Mocha nella patch 2.1.0 per verificare la correzione. Questo test è diventato il modello per questo ambiente di laboratorio — il server vulnerabile replica la configurazione esatta qui descritta (setImmediate fileFilter + richiesta multipart malformata), e il comportamento atteso viene verificato sia sulla versione vulnerabile che su quella corretta.

/* 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('pulizia async fileFilter', function () {
  it('non lascia file orfani quando la richiesta viene interrotta con nome campo mancante', function (done) {
    var uploadDir = fs.mkdtempSync(path.join(os.tmpdir(), 'multer-orphan-'))
    var app = express()

    // Trigger della vulnerabilità: fileFilter async tramite 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 })
    })

    // Gestore degli errori: risponde con 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'

      // Corpo dannoso: Parte 1 valida, Parte 2 con attributo name mancante
      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= mancante
        'Content-Type: application/octet-stream\r\n\r\nx\r\n' +
        '--' + boundary + '--\r\n'
Scarica lo strumento