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-2025-68621 | Kitploit
Strumenti/GitHubGitHub/sivaadityacoder/cve-2025-68621
Analisi delle VulnerabilitàExploitSicurezza WebCrittografiaPaper e RicercaApprendimento e Formazione
GitHubsivaadityacoder/cve-2025-68621

CVE-2025-68621

Vedi Repository
3 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

CVE-2025-68621 — Attacco di tipo Timing su Trilium Notes in /api/login/sync

Gravità: ALTA (CVSS 7.4) Software interessato: TriliumNext/Trilium < 0.101.0 Tipo di vulnerabilità: CWE-208 – Discrepanza temporale osservabile Corretta in: Trilium 0.101.0 (PR #8129) Pubblicata: 2026-02-06 | Riservata: 2025-12-19


Indice

  1. Il mio approccio
  2. Causa principale
  3. Impatto
  4. Correzione
  5. Concetti chiave
  6. Cronologia
  7. Riferimenti

Il mio approccio

Cos'è Trilium Notes?

Trilium Notes è un'applicazione open-source, multipiattaforma e gerarchica per prendere appunti, progettata per costruire grandi basi di conoscenza personali. Supporta:

  • Un server self-hosted con cui più client possono sincronizzarsi
  • Tipi di nota avanzati (testo, codice, canvas, diagrammi)
  • Una potente API di scripting

La funzionalità di sincronizzazione consente a un client Trilium di autenticarsi su un server Trilium così che le note rimangano sincronizzate tra dispositivi. Questo endpoint di sincronizzazione è il punto di ingresso per CVE-2025-68621.

Cos'è un attacco timing?

Un attacco timing è un attacco side-channel in cui un attaccante apprende informazioni segrete misurando quanto tempo impiega un sistema per elaborare input diversi.

L'esempio classico è il confronto tra stringhe:

root@kitploit:~
"correct_password" !== "aorrect_password"   → fails at position 0 → fast
"correct_password" !== "cXrrect_password"   → fails at position 1 → slightly slower
"correct_password" !== "correct_password"   → matches fully     → slowest

La maggior parte dei linguaggi di programmazione confronta le stringhe carattere per carattere e si ferma appena trova una discrepanza (uscita anticipata). Questo significa:

  • Un'ipotesi che corrisponde al primo byte richiede un tempo leggermente maggiore rispetto a una che non corrisponde immediatamente.
  • Inviando migliaia di ipotesi e calcolando la media dei tempi di risposta, un attaccante può determinare statisticamente quale byte è corretto — posizione per posizione — finché non viene recuperato l'intero segreto.

La soluzione è usare una funzione di confronto a tempo costante che ispezioni sempre ogni byte, indipendentemente da dove si verifica una discrepanza.

Come è stata scoperta la vulnerabilità

La vulnerabilità è stata scoperta tramite revisione manuale del codice della logica di autenticazione di Trilium. Il ricercatore ha esaminato il flusso di login di sincronizzazione in apps/server/src/routes/api/login.ts e ha notato il seguente schema nella funzione loginSync() (intorno alla riga 111):

root@kitploit:~
const documentSecret = options.getOption("documentSecret");
const expectedHash   = utils.hmac(documentSecret, timestampStr);
const givenHash      = req.body.hash;

if (expectedHash !== givenHash) {          // ← VULNERABLE LINE
    return [400, { message: "Sync login credentials are incorrect..." }];
}

Il campanello d'allarme è l'uso dell'operatore !== integrato di JavaScript per confrontare gli hash HMAC. L'operatore !== non è a tempo costante — esce appena trova un carattere diverso. Poiché il confronto avviene su stringhe semplici (senza usare una funzione di confronto crittograficamente sicura), il tempo di risposta rivela informazioni su quanti byte iniziali dell'ipotesi dell'attaccante sono corretti.

Il ricercatore si è quindi chiesto:

"Questa piccola differenza di temporizzazione può essere amplificata abbastanza, attraverso una rete, da recuperare l'intero hash HMAC di 44 caratteri codificato in Base64?"

La risposta si è rivelata sì — con abbastanza misurazioni ripetute e un po' di analisi statistica, il segnale supera il rumore.

L'algoritmo dell'attacco

Quando un client Trilium vuole sincronizzarsi, chiama POST /api/login/sync con un body JSON come il seguente:

root@kitploit:~
{
  "timestamp":   "2025-12-19T10:00:00.000Z",
  "syncVersion": 34,
  "hash":        "<HMAC-SHA256 of documentSecret + timestamp, Base64-encoded>"
}

Il recupero byte per byte funziona come segue:

root@kitploit:~
For position = 0 to 43:
    For each candidate character c in charset (A-Z, a-z, 0-9, +, /, =):
        Send SAMPLES requests with hash = known_prefix + c + padding
        Record average response time
    Best character = candidate with highest average time
    Append best character to known_prefix

Dopo 44 iterazioni (una per carattere Base64), viene recuperato l'intero hash HMAC di 44 caratteri.

Requisiti pratici:

  • >100 000 richieste HTTP totali (50 campioni × 65 caratteri del charset × 44 posizioni ≈ 143 000)
  • >1 000 indirizzi IP sorgente diversi a causa del rate-limiting di Trilium (richiede proxy rotanti o una botnet)
  • Basso jitter di rete tra attaccante e server (LAN o connessione cloud stabile è l'ideale)
  • Un timer ad alta precisione (time.perf_counter() in Python offre una risoluzione in nanosecondi)

Prova di concetto

Vedi poc.py per un PoC Python completamente annotato.

Breve riepilogo di ciò che fa il PoC:

  1. Itera attraverso tutte le 44 posizioni dei caratteri Base64 dell'hash HMAC.
  2. Per ogni posizione, prova ogni carattere del charset Base64 (A–Z, a–z, 0–9, +, /, =).
  3. Invia 50 richieste HTTP POST a /api/login/sync per ogni candidato e misura la mediana del tempo di risposta.
  4. Seleziona il candidato con il tempo di risposta mediano più alto come carattere corretto.
  5. Dopo aver recuperato tutti i 44 caratteri, autentica con l'hash recuperato.

Disclaimer: Questo PoC è fornito esclusivamente a scopo didattico e per ricerca sulla sicurezza responsabile. Non utilizzarlo contro sistemi che non possiedi o per i quali non hai esplicita autorizzazione scritta a testare.


Causa principale

Gli operatori !== (e ===) di JavaScript eseguono un confronto lessicografico con uscita anticipata. La riga vulnerabile in apps/server/src/routes/api/login.ts:

root@kitploit:~
if (expectedHash !== givenHash) {
    return [400, { message: "Sync login credentials are incorrect..." }];
}

Il comportamento di uscita anticipata crea una differenza di temporizzazione misurabile per ogni byte corrispondente:

Ogni byte corrispondente aggiuntivo costa una piccolissima quantità extra di tempo CPU δ. Su migliaia di campioni, il tempo di risposta medio per un'ipotesi "byte N corretto" è misurabilmente più lungo di quello per un'ipotesi "byte N errato", rivelando abbastanza informazioni da recuperare l'intero hash HMAC carattere per carattere.

Dettaglio del punteggio CVSS

Stringa del vettore: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N


Impatto

Un exploit riuscito garantisce all'attaccante:

  • Accesso completo in lettura a tutte le note, inclusi i metadati delle note crittografate
  • Accesso completo in scrittura — l'attaccante può creare, modificare o eliminare le note
  • Accesso persistente — l'hash recuperato può essere riutilizzato (all'interno della finestra temporale)

Ciò è particolarmente grave per gli utenti che conservano dati personali sensibili (password, documenti privati, voci di diario) nella propria base di conoscenza Trilium.


Correzione

La correzione sostituisce il confronto !== non a tempo costante con la funzione integrata crypto.timingSafeEqual() di Node.js:

Prima (vulnerabile):

root@kitploit:~
if (expectedHash !== givenHash) {
    return [400, { message: "Sync login credentials are incorrect..." }];
}

Dopo (sicuro):

root@kitploit:~
import * as crypto from "crypto";

const expectedBuffer = Buffer.from(expectedHash);
const givenBuffer    = Buffer.from(givenHash ?? "");

if (expectedBuffer.length !== givenBuffer.length ||
    !crypto.timingSafeEqual(expectedBuffer, givenBuffer)) {
    return [400, { message: "Sync login credentials are incorrect..." }];
}

crypto.timingSafeEqual() confronta sempre ogni byte, quindi il tempo di esecuzione non dipende da quanti byte corrispondono. Il segnale di temporizzazione scompare.

Vedi vulnerable.ts e fix.ts per esempi di codice affiancati.

Come aggiornare

Se stai eseguendo un server Trilium self-hosted, aggiorna immediatamente alla versione 0.101.0 o successiva.

root@kitploit:~
# Docker example
docker pull zadam/trilium:0.101.0

Concetti chiave

  1. Non usare mai === / !== per confrontare segreti. Gli operatori di uguaglianza di JavaScript non sono a tempo costante. Qualsiasi confronto di HMAC, token o password che usa === / !== è una potenziale oracle di temporizzazione.

  2. Usa sempre crypto.timingSafeEqual() in Node.js (o un equivalente nel tuo linguaggio/runtime) quando confronti valori crittografici. È l'API standard e progettata appositamente per questo compito.

  3. Gli attacchi timing sono reali attraverso la rete. Sebbene le differenze in nanosecondi sembrino impossibili da rilevare su internet, le tecniche statistiche e un numero sufficiente di campioni possono estrarre un segnale chiaro da misurazioni rumorose — soprattutto in ambienti a basso jitter.

  4. Il rate-limiting da solo non è una mitigazione sufficiente. Anche con rate-limiting per IP, un attaccante con accesso a proxy rotanti o a una botnet può comunque accumulare abbastanza campioni per sfruttare la differenza di temporizzazione.

  5. La verifica HMAC merita la stessa attenzione del confronto delle password. Gli hash HMAC sono segreti. Tratta qualsiasi confronto di un valore segreto come se i canali laterali di temporizzazione potessero essere sfruttati.

  6. La revisione del codice per i pattern crittografici è essenziale. Questa vulnerabilità è stata trovata tramite revisione manuale — una singola riga di codice che sembrava innocua ma aveva gravi implicazioni per la sicurezza. Audit dedicati di crittografia/sicurezza aiutano a individuare questi problemi in anticipo.


Cronologia

Data

Riferimenti


Questo repository è mantenuto per scopi educativi e di ricerca secondo i principi della divulgazione responsabile.

Scarica lo strumento
Ipotesi vs. attesoByte confrontatiTempo
Byte 0 errato1~T
Byte 0 corretto, byte 1 errato2~T + δ
Byte 0–1 corretti, byte 2 errato3~T + 2δ
………
Tutti i 44 byte corretti44~T + 43δ
MetricaValoreMotivo
Punteggio base7.4 ALTO
Vettore di attaccoRete (N)Sfruttabile via internet
Complessità di attaccoAlta (H)Richiede molte richieste + timing stabile
Privilegi richiestiNessuno (N)Nessun account necessario
Interazione dell'utenteNessuna (N)La vittima non deve fare nulla
AmbitoInvariato (U)È interessato solo il server Trilium
RiservatezzaAlta (H)L'intera base di note è leggibile
IntegritàAlta (H)L'attaccante può scrivere/modificare le note
DisponibilitàNessuna (N)Nessuna componente di denial-of-service
Evento
2025-12-19CVE-2025-68621 riservata da GitHub Security
2025-12-21Aperta la PR di correzione #8129
2025-12-25PR unita; rilasciata Trilium 0.101.0
2026-02-06CVE pubblicata pubblicamente
2026-02-09Aggiunto arricchimento ADP CISA
RisorsaLink
Advisory di sicurezza GitHubGHSA-hxf6-58cx-qq3x
Pull Request di correzioneTriliumNext/Trilium#8129
Record CVE (CVEProject)CVE-2025-68621.json
CWE-208Discrepanza di temporizzazione osservabile
Repository di Trilium NotesTriliumNext/Trilium