Passa al contenuto principale

Appendice C. Problemi di Autenticazione

Questa appendice descrive un meccanismo di autenticazione opzionale che può essere utilizzato per verificare l'integrità dei messaggi NTP e fornire protezione contro attacchi di modifica e replay dei messaggi. Il meccanismo si basa sulla funzione di hash crittografico MD5 e utilizza una chiave segreta condivisa tra i peer. Quando l'autenticazione è abilitata, un campo autenticatore contenente un identificatore chiave e un digest del messaggio viene aggiunto al messaggio NTP.

Il meccanismo di autenticazione fornisce i seguenti servizi di sicurezza:

  1. Integrità del Messaggio: Assicura che il messaggio non sia stato modificato durante il transito.
  2. Autenticazione della Fonte: Verifica che il messaggio provenga da un peer legittimo che possiede la chiave segreta condivisa.
  3. Protezione da Replay: Quando combinato con il meccanismo di timestamp NTP, fornisce protezione contro attacchi di replay.

Il meccanismo di autenticazione è opzionale e non deve essere implementato in tutti i casi. Tuttavia, quando la sicurezza è una preoccupazione, specialmente in ambienti dove server di tempo non autorizzati potrebbero iniettare informazioni temporali false, il meccanismo di autenticazione fornisce un mezzo efficace di protezione.

C.1. Meccanismo di Autenticazione NTP

Il meccanismo di autenticazione NTP utilizza la funzione di hash crittografico MD5 per calcolare un digest del messaggio sul messaggio NTP e una chiave segreta condivisa. Il digest del messaggio viene aggiunto al messaggio NTP nel campo autenticatore, insieme a un identificatore chiave che specifica quale chiave è stata utilizzata.

Il campo autenticatore ha il seguente formato:

 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Key Identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Message Digest |
| |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Identificatore Chiave: Questo è un intero senza segno a 32 bit che identifica la chiave crittografica utilizzata per generare il digest del messaggio.

Digest del Messaggio: Questo è un hash MD5 a 128 bit calcolato sul messaggio NTP (fino a ma senza includere il campo autenticatore) e la chiave segreta condivisa.

Le chiavi segrete condivise sono configurate manualmente e memorizzate in un file chiavi accessibile al demone NTP. Ogni chiave ha un identificatore unico ed è rappresentata come un valore a 64 bit (8 ottetti). Il formato della chiave è compatibile con l'algoritmo di crittografia DES, anche se DES non viene utilizzato direttamente nel meccanismo di autenticazione.

C.2. Procedure di Autenticazione NTP

Le procedure di autenticazione vengono invocate durante le operazioni di trasmissione e ricezione. Quando l'autenticazione è abilitata, la procedura di trasmissione calcola il digest del messaggio e aggiunge l'autenticatore al messaggio in uscita. La procedura di ricezione verifica l'autenticatore sui messaggi in arrivo e imposta di conseguenza il bit autenticato.

C.2.1. Procedura di Cifratura

La procedura di cifratura viene chiamata dalla procedura di trasmissione quando l'autenticazione è abilitata. Calcola il digest del messaggio MD5 e aggiunge l'autenticatore al messaggio NTP.

begin encrypt procedure
if (peer.authenable = 0) exit; /* autenticazione disabilitata */

/* Aggiungere identificatore chiave */
pkt.keyid <- peer.hostkeyid;

/* Calcolare digest MD5 su messaggio e chiave */
digest <- MD5(message || key[peer.hostkeyid]);

/* Aggiungere digest al messaggio */
pkt.check <- digest;

end encrypt procedure

Il calcolo MD5 viene eseguito sull'intero messaggio NTP (inclusi header NTP e campi timestamp) seguito dalla chiave segreta condivisa. Il digest a 128 bit risultante viene aggiunto al messaggio nel campo autenticatore.

C.2.2. Procedura di Decifratura

La procedura di decifratura viene chiamata dalla procedura di ricezione per verificare l'autenticatore sui messaggi in arrivo. Ricalcola il digest del messaggio utilizzando la chiave indicata e lo confronta con il digest nel messaggio ricevuto.

begin decrypt procedure
if (peer.authenable = 0) begin /* autenticazione disabilitata */
peer.authentic <- 1;
exit;
endif

/* Verificare se l'identificatore chiave è valido */
if (pkt.keyid not in sys.keys) begin
peer.authentic <- 0;
exit;
endif

/* Estrarre digest ricevuto */
received_digest <- pkt.check;

/* Calcolare digest atteso */
expected_digest <- MD5(message || key[pkt.keyid]);

/* Confrontare digest */
if (received_digest = expected_digest)
peer.authentic <- 1;
else
peer.authentic <- 0;

end decrypt procedure

Se l'autenticazione ha successo (i digest corrispondono), il bit autenticato (peer.authentic) viene impostato a 1, indicando che il messaggio proviene da un peer legittimo. Se l'autenticazione fallisce, il bit viene impostato a 0 e, a seconda della configurazione, il messaggio può essere rifiutato.

C.2.3. Procedure dei Messaggi di Controllo

Quando i messaggi di controllo NTP descritti nell'Appendice B sono implementati con autenticazione, viene utilizzato lo stesso meccanismo di autenticazione. Le procedure di cifratura e decifratura vengono applicate nello stesso modo dei messaggi NTP regolari.

Per i messaggi di controllo, l'autenticazione è particolarmente importante perché questi messaggi possono essere utilizzati per leggere e modificare variabili interne dell'implementazione NTP. Senza autenticazione, un attaccante potrebbe potenzialmente disturbare la sincronizzazione temporale o estrarre informazioni sensibili.

Considerazioni di Implementazione

Le seguenti considerazioni dovrebbero essere prese in considerazione quando si implementa il meccanismo di autenticazione:

  1. Gestione delle Chiavi: Le chiavi segrete condivise devono essere configurate manualmente su tutti i peer che utilizzeranno l'autenticazione. Le chiavi dovrebbero essere cambiate periodicamente per mantenere la sicurezza.

  2. Impatto sulle Prestazioni: Il calcolo del digest MD5 aggiunge overhead di elaborazione a ogni messaggio. Sui sistemi con risorse CPU limitate, questo può influenzare l'accuratezza del timing. Le implementazioni dovrebbero considerare il caching dei calcoli del digest o l'utilizzo dell'accelerazione hardware quando disponibile.

  3. Precisione del Timestamp: L'operazione di cifratura dovrebbe essere eseguita il più vicino possibile alla trasmissione effettiva del messaggio per ridurre al minimo l'impatto sulla precisione del timestamp. Alcune implementazioni pre-calcolano l'offset del digest per compensare il ritardo di cifratura.

  4. Spazio dell'Identificatore Chiave: Lo spazio dell'identificatore chiave a 32 bit consente un gran numero di chiavi, facilitando la rotazione delle chiavi e supportando più domini di autenticazione.

  5. Compatibilità Retroattiva: Messaggi con e senza autenticazione possono coesistere. I peer che non supportano l'autenticazione ignorano semplicemente il campo autenticatore.

  6. Limitazioni di Sicurezza: Il meccanismo di autenticazione protegge contro attacchi di modifica e replay dei messaggi ma non fornisce crittografia del contenuto del messaggio. Le informazioni temporali stesse vengono trasmesse in chiaro.

Il meccanismo di autenticazione descritto qui fornisce un equilibrio pratico tra sicurezza e prestazioni per la maggior parte delle distribuzioni NTP. Per ambienti che richiedono garanzie di sicurezza più forti, misure aggiuntive come IPsec o altri meccanismi di sicurezza a livello di trasporto possono essere appropriate.