Un tempo di attività lungo dimostra solo che l’avvio è riuscito con i privilegi che il demone aveva in quel momento. I guasti che contano qui arrivano più tardi: un nuovo client si connette, un elenco di revoca viene sostituito, uno script ausiliario deve scrivere un file. Ognuno è un’apertura nuova eseguita dall’account senza privilegi, con la propria domanda di permessi e il proprio messaggio di errore. Tre decisioni separano una configurazione che continua a funzionare da una che fallisce al prossimo evento.

Separate ciò che è stato caricato presto da ciò che si apre dopo

Un descrittore è un handle su una descrizione di file aperta, e il modo di accesso è stato fissato quando quella descrizione è stata creata. Cambiare l’utente del processo in seguito non chiude l’handle, per questo un file di chiave letto come root continua a funzionare dopo la riduzione. Anche il modo non cambia: un handle aperto in lettura non diventa scrivibile, e un handle scrivibile non viene revocato solo perché l’account ha perso i diritti sul percorso. Questi due fatti spiegano la maggior parte del comportamento sorprendente di questi rapporti.

L’altra metà è la memoria. Un demone può analizzare un certificato, conservare il materiale analizzato e chiudere il file; ciò che resta in uso sono dati, non un file aperto. Il traffico continuo quindi non prova né che un descrittore sia aperto né che il nome del percorso sia raggiungibile. Prova solo che il materiale necessario alla sessione corrente è stato ottenuto prima.

Un’apertura successiva è un’altra transazione. Viene eseguita con le credenziali correnti, il contesto di sicurezza corrente e la vista di montaggio corrente, quindi un percorso leggibile all’avvio può essere rifiutato alla connessione successiva. La rotazione aggiunge una trappola: scrivere un nuovo file sullo stesso nome di percorso lascia un descrittore esistente legato al vecchio oggetto, così un ricaricamento può sembrare riuscito mentre il demone usa ancora il contenuto precedente. Confrontate l’inode tenuto dal processo con quello sul disco prima di credere che la rotazione abbia effetto.

Nominate le tre letture di esecuzione e quando ciascuna scatta

Tre risorse vengono normalmente aperte molto dopo l’inizializzazione, e falliscono in momenti diversi. Un file di configurazione specifico di un client viene letto quando quel client si connette, quindi può rompersi per un utente mentre tutti gli altri continuano. I dati di revoca vengono consultati durante l’autenticazione del peer e di nuovo quando il file viene sostituito. Una directory temporanea viene toccata solo quando uno script o un plugin scrive qualcosa.

Nessuna delle tre appartiene al percorso di avvio, per questo un server sano da settimane può fallire alla connessione successiva. La categoria nomina anche il proprietario della correzione: le prime due sono permessi di lettura sulla configurazione sotto l’account del demone, e la terza è una posizione scrivibile con uno scopo ristretto.

Path reopened laterWhat triggers the openFirst sign when it fails
Client configuration fileA connection for that client identityOne client rejected while others connect
Revocation dataPeer authentication, including after replacementRevoked and valid peers both refused
Script or plugin temporary directoryA helper needs to create a fileThe helper exits with a path error

persist-key risponde a una domanda più ristretta di quanto la maggior parte supponga. Mantiene il file di chiave aperto durante i riavvii documentati SIGUSR1 e ping-restart, e non fa nulla per i file CCD, i dati di revoca, gli eseguibili ausiliari o un riavvio completo del processo. Questi seguono ancora i propri percorsi di apertura, sotto qualunque account stia girando in quel momento.

Confermate l’account e la vista che ha realmente

Chiedete al demone in esecuzione quale account usa invece di fidarvi del file di unit, poi confrontate la risposta con ciò che l’unit imposta. Una discrepanza è la prima cosa da risolvere, perché ogni controllo di permessi successivo gira come chi il processo è davvero. Poi percorrete il percorso componente per componente; l’attraversamento viene valutato a ogni livello, quindi un file leggibile dentro una directory non attraversabile resta illeggibile. Il modo finale del file è l’ultima domanda, non la prima.

Gli spazi dei nomi e le sandbox di servizio aggiungono confini che proprietà e bit di modo non descrivono. Un percorso visibile nella vostra shell può mancare o essere di sola lettura dentro un chroot, uno spazio dei nomi di montaggio o un’unit che nasconde le directory personali. I moduli di sicurezza aggiungono un altro strato, quindi un file che sembra leggibile può comunque essere negato quando viene aperto.

ps -o user:12,pid,args -C openvpn
systemctl show -p User -p Group -p ProtectHome -p RootDirectory [email protected]
sudo -u openvpn namei -l /etc/openvpn/ccd/alice

Una lettura riuscita nella shell dell’amministratore non verifica nessuna di quelle condizioni combinate. Eseguite il controllo con l’account del demone, con lo stesso spazio dei nomi e la stessa sandbox, oppure accettate che il risultato descriva la vostra shell e non il server. Il terzo comando è la versione economica di quel test: stampa il modo di ogni componente e fallisce al primo che l’account del demone non riesce ad attraversare.

Concedete la scrittura di esecuzione in una directory propria

La lettura è solo metà dell’inventario. Uno script ausiliario può dover creare un file di stato, un plugin può dover scrivere stato accanto alla sua configurazione, e queste scritture non sono coperte dal rendere scrivibile l’albero di configurazione. Date alla directory specifica il permesso di scrittura che la sua funzione richiede, con un proprietario e un modo che sapete spiegare. Preferite l’accesso in sola lettura per tutto ciò che viene solo letto.

Tenete i permessi della chiave privata separati dai file di politica. Una chiave che deve essere riletta dopo un riavvio ha un requisito diverso da un file client letto a ogni connessione, e un solo modo permissivo per entrambi concede più accesso di quanto il problema chieda. Un account demone dedicato con proprietà ristretta è più facile da verificare di un gruppo ampio. Quando la chiave deve sopravvivere ai riavvii, persist-key elimina la rilettura invece di ampliare la directory.

Decidete dall’evento che potete riprodurre

Un tunnel attivo prova un solo percorso nel codice. L’evento che ha bisogno del file è l’unico test che copre l’apertura che vi interessa, sia essa una nuova connessione client, un file di revoca sostituito, un riavvio morbido consentito o un riavvio pianificato. Scegliete l’evento, eseguitelo e tenete il primo errore invece dell’ultimo.

Per un riavvio morbido, un segnale e il registro dell’unit mostrano se la chiave è stata riletta. Inviate il segnale, poi leggete le ultime righe scritte dall’unit:

systemctl kill -s SIGUSR1 [email protected]
journalctl -u [email protected] -n 40 --no-pager

Non concludete che un demone compromesso non possa più modificare file solo perché i privilegi sono stati abbassati. Ciò che può ancora fare dipende dalle credenziali rimaste, dalle sue capacità, dalle directory in cui può scrivere e da ogni descrittore scrivibile che detiene ancora. La riduzione dei privilegi restringe l’autorità, e l’inventario delle aperture di esecuzione mostra quanto. Scrivete quel confine accanto alla configurazione perché la persona successiva non debba riscoprirlo.

Articoli correlati