Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
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.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-34213 — Un utente Docmost con privilegi bassi potrebbe fornire un attachmentId vittima all'endpoint di upload generico e sovrascrivere l'allegato memorizzato di un'altra pagina all'interno dello stesso spazio di lavoro. | Kitploit
Strumenti/GitHubGitHub/0xmrma/cve-2026-34213
Analisi delle VulnerabilitàSfruttamento di Applicazioni WebPenetration TestingPaper e RicercaApprendimento e Formazione
GitHub0xmrma/cve-2026-34213

CVE-2026-34213

Un utente Docmost con privilegi bassi potrebbe fornire un attachmentId vittima all'endpoint di upload generico e sovrascrivere l'allegato memorizzato di un'altra pagina all'interno dello stesso spazio di lavoro.

Vedi Repository
1 mese 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-34213

Un utente Docmost con privilegi ridotti potrebbe fornire un attachmentId vittima all'endpoint di upload generico e sovrascrivere un allegato memorizzato di un'altra pagina nello stesso spazio di lavoro.

Introduzione

Ho identificato, divulgato in modo responsabile e riprodotto un difetto di autorizzazione di Alta gravità in Docmost, la piattaforma collaborativa open-source per la documentazione.

Il sito ufficiale di Docmost la presenta come un wiki aziendale on-premise con oltre 3 milioni di download, e afferma che è utilizzata da team di organizzazioni tra cui Vilnius City, Bechtle, il Governo Australiano, la Croce Rossa e ETS Quebec.

Il bug risiedeva nel percorso generico di upload dei file che Docmost utilizza anche per i flussi di salvataggio/aggiornamento dei diagrammi.

Stavo esaminando quel codice con una domanda molto specifica in mente:

Cosa succede se l'endpoint di upload verifica l'accesso in modifica su una pagina, ma il target di sovrascrittura viene selezionato con un ID allegato controllato dall'utente separato?

In questo caso, quella domanda ha portato direttamente a un reale fallimento del binding degli oggetti.

Docmost permetteva a un chiamante di inviare:

  • un pageId per una pagina a cui era consentito modificare, e
  • un attachmentId appartenente a una pagina diversa nello stesso spazio di lavoro

Il server eseguiva un controllo di consistenza della sovrascrittura, ma la guardia utilizzava la logica booleana sbagliata.

Ciò significava che la richiesta poteva superare l'autorizzazione e sovrascrivere comunque l'allegato vittima.

Questo problema è diventato CVE-2026-34213.

Docmost: docmost/docmost Avviso: GHSA-89fp-2hch-j9gp CVE: CVE-2026-34213 Corretto in: v0.71.0

photo0 ---

Catena di Attacco

pageId controllato dall'attaccante con accesso in modifica -> attachmentId vittima controllato dall'attaccante -> guardia di sovrascrittura difettosa considera valida la sovrascrittura tra pagine -> percorso di archiviazione ricostruito dall'attaccanteId vittima -> byte dell'attaccante sostituiscono il file vittima -> la pagina vittima continua a servire l'allegato modificato


Cosa Fa Questa Parte di Docmost

Docmost memorizza gli allegati delle pagine caricati come record di database più file di backup nell'archiviazione.

Per i caricamenti normali, il server crea un nuovo ID allegato e scrive un nuovo file.

Per i flussi di salvataggio/aggiornamento dei diagrammi, invece, il client riutilizza intenzionalmente un attachmentId esistente in modo che lo stesso file di diagramma possa essere aggiornato sul posto invece di generare un nuovo record di allegato ogni volta.

Questo comportamento è legittimo di per sé.

Il problema è che crea un percorso ad alto rischio:

  • un input identifica la pagina da autorizzare
  • un altro input identifica l'allegato da sovrascrivere

Ogni volta che un endpoint combina queste due responsabilità, l'implementazione deve vincolarle esattamente tra loro.

Docmost non lo ha fatto.


Perché Questa Superficie Meritava di Essere Esaminata

Gli endpoint misti di creazione/aggiornamento sono luoghi comuni per i bug di autorizzazione.

Il motivo è semplice:

  • i flussi di creazione sono solitamente autorizzati rispetto all'oggetto contenitore
  • i flussi di aggiornamento sono solitamente autorizzati rispetto al record esistente
  • se un endpoint cerca di fare entrambe le cose, è facile convalidare prima la cosa sbagliata e trattare il secondo identificatore come "solo metadati"

Questo è esattamente lo schema qui.

POST /api/files/upload convalidava che il chiamante potesse modificare la pagina denominata da pageId.

Ma se veniva fornito anche attachmentId, il server passava a un percorso di sovrascrittura e selezionava un record di allegato esistente separatamente.

Questo rendeva la domanda di sicurezza critica:

il percorso di sovrascrittura dimostra che l'allegato selezionato appartiene effettivamente alla pagina autorizzata?

La risposta nelle versioni vulnerabili era no.


Causa Principale

La causa principale era un bypass dell'autorizzazione tramite una chiave controllata dall'utente, combinato con un bug di logica booleana nella guardia di sovrascrittura.

Il flusso vulnerabile appariva così:

  1. AttachmentController.uploadFile() leggeva pageId dai dati del modulo multipart.
  2. Caricava quella pagina e chiamava validateCanEdit(page, user).
  3. Separatamente accettava un attachmentId opzionale dalla stessa richiesta.
  4. AttachmentService.uploadFile() caricava l'allegato esistente tramite quell'ID fornito dall'attaccante.
  5. La guardia di sovrascrittura tentava di verificare che l'allegato esistente corrispondesse alla pagina autorizzata.
  6. La guardia usava && invece di rifiutare in caso di mancata corrispondenza.

La guardia vulnerabile era:

root@kitploit:~
if (
  existingAttachment.pageId !== pageId &&
  existingAttachment.fileExt !== preparedFile.fileExtension &&
  existingAttachment.workspaceId !== workspaceId
) {
  throw new BadRequestException("File attachment does not match");
}

Quella condizione rifiutava la richiesta solo se:

  • l'ID della pagina non corrispondeva, e
  • l'estensione del file non corrispondeva, e
  • l'ID dello spazio di lavoro non corrispondeva

tutti contemporaneamente.

Questo è l'opposto di ciò che una guardia di sovrascrittura dovrebbe fare.

Nel caso reale dell'attacco, l'attaccante rimaneva intenzionalmente all'interno dello stesso spazio di lavoro.

Quindi:

  • existingAttachment.workspaceId !== workspaceId era false

Una volta che quell'operando diventava falso, l'intera condizione && veniva valutata come falsa, anche se l'allegato apparteneva a una pagina diversa.

Quindi il server trattava una sovrascrittura tra pagine come valida.

Questa era la prima metà del bug.

La seconda metà è ciò che ha reso reale l'impatto.

Dopo il controllo, il servizio ricostruiva il percorso di destinazione dell'archiviazione usando l'attachmentId e il nome file forniti dall'attaccante:

root@kitploit:~
const filePath =
  `${getAttachmentFolderPath(AttachmentType.File, workspaceId)}/` +
  `${attachmentId}/${preparedFile.fileName}`;

Poi, sul percorso di aggiornamento, Docmost aggiornava solo i metadati mutabili come:

  • fileSize
  • updatedAt

Non riassociava la proprietà alla pagina dell'attaccante.

Quindi la pagina vittima continuava a puntare allo stesso record di allegato e allo stesso ID allegato. Solo i byte del file sottostante cambiavano.

Ecco perché non si trattava di una mancata corrispondenza innocua.

Era una primitiva di sovrascrittura non autorizzata persistente.


Perché Questo È un Problema di Sicurezza, Non Solo un Errore Logico

Non era un bug estetico né un problema di collisione di nomi file.

L'attaccante non aveva bisogno di una race condition. L'attaccante non doveva indovinare un percorso casuale. L'attaccante non aveva bisogno di accesso in scrittura alla pagina vittima.

Aveva bisogno solo di:

  • accesso in lettura per conoscere un riferimento di allegato vittima, e
  • accesso in scrittura a qualsiasi altra pagina nello stesso spazio di lavoro

Da lì, poteva sostituire i byte del file memorizzato per l'allegato di un'altra pagina mentre la pagina vittima continuava a fare riferimento e servire quell'allegato come se nulla fosse cambiato.

Questo è un fallimento diretto dell'integrità.

In termini pratici, l'attaccante poteva:

  • manomettere i diagrammi
  • sostituire gli allegati con contenuti fuorvianti
  • corrompere i file referenziati
  • creare tracce di audit confuse perché l'allegato sembrava ancora appartenere alla pagina vittima

Il punto importante è questo:

il server accettava un target di sovrascrittura scelto dall'attaccante, senza vincolarlo alla pagina di cui era stato effettivamente verificato il permesso di modifica.

Questo è un fallimento del controllo degli accessi, non solo una cattiva igiene booleana.


Perché lo Sfruttamento Era Pratico

Lo sfruttamento era particolarmente pratico per gli allegati dei diagrammi.

Il client di Docmost riutilizza intenzionalmente attachmentId per i salvataggi dei diagrammi e utilizza nomi file deterministici:

  • diagram.excalidraw.svg
  • diagram.drawio.svg

Questo è importante perché abbassa i requisiti dell'attaccante.

Per gli allegati generici, l'attaccante ha bisogno sia di:

  • l'ID dell'allegato vittima
  • il nome file vittima

Per i diagrammi, il nome file è già prevedibile.

Quindi, se l'attaccante può leggere il contenuto della pagina vittima, spesso può recuperare l'unico pezzo mancante di cui ha bisogno:

  • l'attachmentId vittima

Nella mia configurazione di validazione, ho usato esattamente quel percorso:

  • l'attaccante aveva solo accesso in lettura allo spazio vittima
  • l'attaccante aveva accesso in scrittura a uno spazio diverso controllato dall'attaccante
  • entrambi gli spazi appartenevano allo stesso spazio di lavoro

Questo è bastato.

Lo sfruttamento ha attraversato i confini delle pagine e dei confini degli spazi all'interno dello stesso spazio di lavoro, soddisfacendo comunque il controllo difettoso dello spazio di lavoro.


Prova di Concetto

Ho convalidato il problema in tempo reale contro Docmost v0.70.3 usando un laboratorio usa e getta costruito da docmost/docmost:0.70.3, Postgres e Redis.

Il flusso del PoC era:

  1. Creare un account proprietario.
  2. Creare uno spazio vittima e uno spazio controllato dall'attaccante nello stesso spazio di lavoro.
  3. Invitare un secondo utente come attaccante.
  4. Concedere all'attaccante:
    • accesso in lettura allo spazio vittima
    • accesso in scrittura allo spazio controllato dall'attaccante
  5. Nello spazio vittima, caricare un allegato di diagramma su una pagina vittima.
  6. Come attaccante, recuperare le informazioni della pagina vittima e annotare l'attachmentId vittima.
  7. Inviare POST /api/files/upload con:
    • pageId = ID pagina attaccante
    • attachmentId = ID allegato vittima
    • file = file sostitutivo controllato dall'attaccante usando il nome file vittima
  8. Scaricare l'allegato vittima prima e dopo la sovrascrittura e confrontare gli hash.

La forma minima della richiesta era:

root@kitploit:~
POST /api/files/upload
Content-Type: multipart/form-data

pageId=<attackerPageId>
attachmentId=<victimAttachmentId>
[email protected];filename=diagram.excalidraw.svg

Il risultato live osservato era:

  • ID allegato vittima appreso dall'attaccante: 019d18ae-b176-751c-8525-b5f3cede131d
  • ID pagina attaccante usato per la richiesta di sovrascrittura: 019d18ae-b15b-70e9-ac67-64948e87cc5e
  • ID pagina proprietario vittima rimasto: 019d18ae-b12f-75ec-8c1c-5aff3ba6be9c
  • risposta del server alla richiesta di sovrascrittura: 200 OK
  • SHA-256 del file vittima prima della sovrascrittura:
root@kitploit:~
686a0a0ede90ece1cbb975bb29304a6c3a90373a9c3ab2496345cf7ca59cc8fa
  • SHA-256 del file vittima dopo la sovrascrittura:
root@kitploit:~
e0168298846cdaf75c4d880f4b721d7c0ef0ef310f75617bf2b833af34cdbeba
  • SHA-256 del payload dell'attaccante:
root@kitploit:~
e0168298846cdaf75c4d880f4b721d7c0ef0ef310f75617bf2b833af34cdbeba
  • l'archiviazione montata ha confermato che il percorso vittima ora conteneva:
root@kitploit:~
Sostituzione attaccante da un'altra pagina

Questa è una prova completa di sovrascrittura end-to-end, non solo una revisione teorica del codice sorgente.


Perché il PoC è Stato Scelto in Questo Modo

Ho usato due stili di prova durante il triage:

  • un harness autonomo ristretto che rispecchiava la logica di sovrascrittura vulnerabile, e
  • un exploit HTTP live completo contro un'istanza Docmost usa e getta

L'harness autonomo era utile per isolare il fallimento della logica booleana.

Il PoC HTTP live era l'artefatto più forte perché dimostrava l'intera storia di sicurezza:

  • l'autorizzazione della pagina è riuscita sulla pagina attaccante
  • l'attachmentId vittima è stato accettato
  • la richiesta di sovrascrittura ha restituito successo
  • la pagina vittima è rimasta il proprietario logico
  • i byte memorizzati su disco sono cambiati in contenuto controllato dall'attaccante

Questa distinzione è importante nei bug di controllo degli accessi.

"la condizione è sbagliata" non è sufficiente da sola.

"la condizione è sbagliata e l'applicazione può essere guidata end-to-end in una sovrascrittura non autorizzata persistente" è il caso completo.


Analisi della Correzione

La correzione è stata distribuita in v0.71.0 e ha cambiato la guardia di sovrascrittura da && a ||:

root@kitploit:~
if (
  existingAttachment.pageId !== pageId ||
  existingAttachment.fileExt !== preparedFile.fileExtension ||
  existingAttachment.workspaceId !== workspaceId
) {
  throw new BadRequestException("File attachment does not match");
}

Quella patch è minima, diretta e corretta per il bug che è stato segnalato.

Ripristina la regola giusta:

la sovrascrittura è consentita solo quando l'allegato esistente corrisponde esattamente ai presupposti di pagina/spazio di lavoro/tipo autorizzati.

Una volta che la guardia rifiuta su qualsiasi mancata corrispondenza:

  • le sovrascritture tra pagine falliscono
  • le sovrascritture tra spazi di lavoro falliscono
  • le mancate corrispondenze di tipo/estensione falliscono

Questa era la giusta tipologia di correzione:

  • nessuna riprogettazione
  • nessuna logica vaga di compatibilità
  • nessun tentativo di recupero "al meglio"

Solo un binding stretto tra la pagina autorizzata e il target di sovrascrittura.

C'è ancora una lezione di ingegneria più ampia qui:

gli endpoint di upload generici che servono anche flussi di aggiornamento in-place dovrebbero essere trattati come superfici API ad alto rischio.

Anche quando il bug immediato è risolto, progetti più forti a lungo termine sono:

  • endpoint di aggiornamento dedicati per i flussi di salvataggio dei diagrammi
  • controlli di binding immutabili sul nome file oltre che sull'ID allegato
  • copertura di regressione che modella esplicitamente i tentativi di sovrascrittura tra pagine

Ma per la vulnerabilità stessa, la patch pubblicata ha chiuso il problema principale in modo pulito.


Casi di Regressione Che Contano

Che il progetto abbia aggiunto o meno i propri test privati intorno alla correzione, questi sono i casi che contano per la copertura a lungo termine:

  • la sovrascrittura con lo stesso ID pagina e lo stesso ID allegato dovrebbe riuscire
  • la sovrascrittura con un ID pagina diverso e lo stesso spazio di lavoro dovrebbe fallire
  • la sovrascrittura con uno spazio di lavoro diverso dovrebbe fallire
  • la sovrascrittura con estensione file non corrispondente dovrebbe fallire
  • la sovrascrittura usando un nome file di diagramma noto ma un ID allegato estraneo dovrebbe fallire
  • la sovrascrittura non dovrebbe mai preservare silenziosamente la proprietà vittima dopo che i byte controllati dall'attaccante sono stati scritti

Il punto di questi test non è solo la correttezza.

È bloccare il binding di autorizzazione in modo che futuri refactoring "utili" dell'upload non riaprano la stessa classe di bug.


Gravità e Classificazione

L'avviso pubblicato ha classificato questo problema come:

  • CWE-639: Bypass dell'autorizzazione tramite chiave controllata dall'utente
  • CVSS v3.1:
root@kitploit:~
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L

Ciò si colloca a 7.1 / Alta, che è la conclusione giusta.

La metrica importante qui è l'Integrità.

Non era un bug di metadati di basso livello. L'attaccante controllava completamente i byte di sostituzione scritti nel percorso dell'allegato di un'altra pagina, e la pagina vittima continuava a servire l'oggetto modificato successivamente.

Questo è esattamente il tipo di manomissione incrociata dei record memorizzati che merita Integrità Alta.

La Disponibilità rimane Bassa ha senso anche perché corrompere un diagramma o un documento allegato può rendere inutilizzabile il contenuto vittima, ma l'impatto principale è ancora la modifica non autorizzata piuttosto che l'interruzione completa del servizio.


Divulgazione

Ho segnalato il problema privatamente tramite GitHub Security Advisories con:

  • analisi della causa principale
  • un PoC HTTP live
  • prove richiesta/risposta
  • hash dei file prima/dopo
  • una configurazione di laboratorio usa e getta bloccata

Il problema è stato accettato dal manutentore, è stato assegnato CVE-2026-34213 e pubblicato il 14 aprile 2026.

L'avviso pubblico elenca:

  • versioni interessate: >= v0.3.0
  • versione corretta: v0.71.0

Questa cronologia corrispondeva anche alla mia revisione locale del codice sorgente: la logica di sovrascrittura vulnerabile era presente nella prima release taggata che ho controllato nella riga vulnerabile.


Cosa Insegna Davvero Questo Bug

La lezione interessante qui non è semplicemente "usa || invece di &&."

Questo è il sintomo.

La lezione più profonda è:

se un campo controllato dall'utente dimostra l'autorizzazione e un altro campo controllato dall'utente seleziona l'oggetto da aggiornare, questi due campi devono essere vincolati insieme esplicitamente ed esattamente.

Questa regola si presenta ovunque:

  • allegati di documenti
  • media del profilo
  • riferimenti a oggetti cloud
  • modifiche a issue/commenti
  • rielaborazione di job in background

Nel momento in cui un sistema dice:

  • "puoi modificare la pagina X"
  • "per favore, dimmi anche quale record esistente aggiornare"

ha creato un confine di sicurezza che deve essere applicato con invarianti di corrispondenza esatta.

Qualunque cosa più morbida di questo si trasforma prima o poi in un bug di chiave controllata dall'utente.

Questo problema rafforza anche un secondo punto che è facile sottovalutare:

piccoli errori booleani nel codice delle guardie possono avere conseguenze di sicurezza di primo ordine.

Una condizione a tre clausole che "sembra ragionevole" a prima vista è bastata per invertire il modello di protezione per il percorso di sovrascrittura.

Ecco perché queste superfici meritano una revisione deliberata piuttosto che una fiducia casuale.


Punti Chiave

  • Docmost usava un endpoint sia per nuovi upload che per aggiornamenti in-place degli allegati.
  • L'autorizzazione veniva verificata rispetto al pageId fornito dal chiamante, ma la selezione del target di sovrascrittura utilizzava un attachmentId separato fornito dal chiamante.
  • La guardia di sovrascrittura rifiutava solo quando tutte le condizioni di mancata corrispondenza erano vere contemporaneamente.
  • Nel caso dell'attacco nello stesso spazio di lavoro, quel controllo falliva aperto.
  • Il servizio ricostruiva il percorso di archiviazione dall'ID allegato vittima e scriveva byte controllati dall'attaccante al suo interno.
  • Il record dell'allegato rimaneva legato alla pagina vittima dopo la sovrascrittura.
  • I nomi file deterministici dei diagrammi rendevano lo sfruttamento particolarmente pratico.
  • La correzione in v0.71.0 ha correttamente modificato la guardia per rifiutare su qualsiasi mancata corrispondenza.

Parole Finali

Questa vulnerabilità non riguardava un comportamento di archiviazione esotico.

Riguardava un percorso di aggiornamento che si fidava di un identificatore di oggetto selezionato dall'attaccante più di quanto avrebbe dovuto.

Docmost dimostrava l'accesso in modifica su una pagina, accettava un ID allegato esistente da un'altra pagina, e poi lasciava che un controllo di sovrascrittura difettoso trasformasse quella mancata corrispondenza in una sostituzione di file tra pagine riuscita.

Ecco perché è diventato CVE-2026-34213.

La patch in v0.71.0 ha risolto il problema immediato in modo pulito, ma la lezione più ampia rimane preziosa:

quando l'autorizzazione e la selezione dell'oggetto sono divise tra campi controllati dall'utente separati, il binding esatto è la proprietà di sicurezza.

Scarica lo strumento