Consenti agli utenti regolari di SSH utilizzando una chiave privata che non possono leggere


8

Diciamo che ho una serie di macchine (chiamate qui le macchine dei clienti) in cui solo un piccolo elenco di persone (chiamato il personale di supporto) è autorizzato a SSH, usando solo un account per macchina (l'account di accesso al supporto).

Il personale di supporto deve solo accedere alle macchine dei clienti utilizzando le chiavi. Inoltre, il personale di supporto può evolversi, quindi a chi lascia il personale di supporto non è consentito accedere a nessuna macchina del cliente. Pertanto, è vietato alle persone del personale leggere le chiavi private utilizzate per accedere alle macchine dei clienti. Inoltre, è vietato modificare il authorized_keysfile sui computer dei clienti.

Per realizzare quella configurazione, ho avuto l'idea di utilizzare un proxy SSH a cui lo staff di supporto accederà (con autenticazione LDAP, ma questo è un altro problema) e che contiene le chiavi private.

La domanda è: come posso consentire al personale di supporto di utilizzare la chiave privata SSH senza poterla leggere?

Credo che devo fare in modo che un demone funzioni come root sul computer proxy che accetti la richiesta di un utente e apra una sessione SSH per loro, ma non ho idea di come farlo. Qualche idea?


Modificata la domanda perché "macchine client" può essere difficile da capire (non significa il contrario del server).
Raspbeguy,

È un sacco di audace e la maggior parte sembra estranea. È fonte di distrazione. Pensi in futuro che potresti usare molto meno audace? Grazie.
DW,

Presumo che la restrizione authorized_keys si riferisca solo a cambiamenti dinamici (ad es. Quando un nuovo membro dell'assistenza si unisce / esce), poiché è necessaria una configurazione iniziale nella macchina del cliente.
Ángel,

Risposte:


6

Vorrei suggerire un paio di opzioni.

  1. Proteggi la chiave ssh e richiedi l'uso da parte del sudotuo team di supporto. Puoi farlo in modo trasparente con un wrapper. Chiama il wrapper, diciamo, /usr/local/bin/ssh-supporte contiene qualcosa del genere (non testato):

    #!/bin/bash
    export PATH=/usr/local/bin:/usr/bin:/bin
    export IFS=$' \t\n'
    export SUSER=ssupport
    
    # Restart if not running under sudo
    test "X$1" != 'X-S' && exec sudo -u "$SUSER" /usr/local/bin/ssh-support -S "$@"
    shift
    export SHOME="$(getent passwd "$SUSER" | cut -d: -f6)"
    
    # Extract single argument as hostname LABEL and validate that we have
    # an RSA private key for it. The target username, real hostname, port,
    # etc. can be defined in ~/.ssh/config for the user $SUSER (ssupport)
    label="$1"
    idfile="$SUSER/.ssh/id_rsa_for_$label"
    cgfile="$SUSER/.ssh/config"
    
    ok=true
    [[ "$label" =~ '/' ]] && { echo "Invalid label: $label" >&2; ok=; }
    [[ ! -s "$idfile" ]] && { echo "Missing identity file: $idfile" >&2; ok=; }
    [[ ! -s "$cgfile" ]] && { echo "Missing configuration file: $cgfile" >&2; ok=; }
    
    if test -n "$ok"
    then
        logger -t ssh-support "$SUDO_USER requested ssh to $label"
        exec ssh -i "$idfile" -F "$cgfile" "$label"
    fi
    exit 1

    Ciò richiederebbe una voce nel sudoersfile che consentisse agli utenti del supportgruppo di utilizzare lo strumento. Questo comando consente loro di eseguire lo ssh-supportstrumento come ssupportutente, che è necessario creare. Essa non conferisce alcun privilegi di root.

    %support ALL = (ssupport) /usr/local/bin/ssh-support

    Se sei soddisfatto del fatto che gli utenti dell'assistenza non debbano fornire la propria password per eseguire lo strumento (come richiesto sudodall'invocazione all'interno dello script stesso), puoi modificare la sudoersdefinizione in questo modo:

    %support ALL = (ssupport) NOPASSWD: /usr/local/bin/ssh-support

    Supponendo che PATHconteneresti /usr/local/bin/lo chiameresti ssh-support clientname. Supponendo anche di aver creato l' ssupportutente come /home/ssupportsi creava /home/ssupport/.ssh/id_rsa_clientnamee /home/ssupport/.ssh/id_rsa_clientname.pubcome coppia di certificati e di avere una voce host /home/ssupport/.ssh/configper clientnamequella definita dall'utente, host, porta, ecc. Per la macchina target. Probabilmente disabiliteresti esplicitamente X11 forwarding, port forwarding, ecc. Come al solito, la /home/ssupport/.sshdirectory dovrebbe essere protetta con le autorizzazioni 0700.

  2. Offri a ciascun membro dell'assistenza il proprio account utente locale e fai in modo che ogni persona utilizzi la propria chiave ssh privata per accedere ai server del client. Quando una persona lascia il gruppo di supporto, rimuovi la sua chiave ssh dai server del client. Ciò significa che non è più necessario preoccuparsi di impedire al personale di conoscere la chiave SSH privata.


La seconda opzione non è valida. Come ho detto, c'è solo un account di supporto sui server client e non è possibile aggiungere chiavi pubbliche alla configurazione di ssh, ecco le regole. In effetti, non è possibile modificare nulla sulla configurazione di ssh sui computer client.
Raspbeguy,

4
A proposito, questa risposta è un tipico esempio di (ab) utilizzo di sudo. Ho scritto un articolo sull'argomento ( dmitry.khlebnikov.net/2015/07/… ), sembra che ci sia una tendenza a provare a risolvere qualsiasi cosa usando sudo. Tuttavia, ciò indebolisce solo la sicurezza dei sistemi e non la migliora.
galaxy

1
@Raspbeguy ovviamente non lo faranno. La sudoerslinea limita l'accesso al singolo comando
roaima,

1
Passa le opzioni non selezionate a ssh con "$ @" che funziona come root! Riesco a pensare a diversi modi per eterare i file di sistema corrotti (usare -Eper aggiungere), inoltrare porte privilegiate ( -L,-R,-D) o semplicemente ottenere root ( -o PermitLocalCommand=yes -o 'LocalCommand=/bin/bash'. Il commento della galassia sull'abuso di sudo è sul posto corretto!
nkms

1
@roaima: Quindi, la tua idea sudo to root ha dei problemi, ma sono problemi diversi rispetto a quelli di cui parlava il post sul blog della galassia. Sta parlando ssh root@somewherecon le chiavi, contro ssh user@somewherepoi sudo. In realtà è davvero un buon punto. Tuttavia, l'unico modo in cui è applicabile in questo caso è ssh keyowner@localhost ssh_to_client client.example.org un'alternativa a sudo -u keyowner ssh_to_client client.example.org. Simile a sudo, SSH può limitare i comandi che un utente può eseguire. Stiamo parlando di sudo senza password a non root, non al caso d'uso di Galaxy.
Peter Cordes,

11

Quello che vuoi veramente fare è usare la CA SSH e firmare le chiavi usate da ogni persona di supporto (dovrebbero avere le loro chiavi ssh, come i passaporti) e configurare i server dei tuoi client per usare il file TrustedUserCAKeys /etc/ssh/users_ca.pubin / etc / ssh / sshd_config. In questo modo il server accetterà qualsiasi chiave firmata dalla chiave CA (a cui hai accesso) e sarai in grado di revocare le chiavi delle persone che non sono più supportate senza nemmeno toccare le chiavi autorizzate.

Una rapida ricerca di "ssh ca" ha indicato questo tutorial: https://www.digitalocean.com/community/tutorials/how-to-create-an-ssh-ca-to-validate-hosts-and-clients-with -ubuntu (scorrere fino a "Come configurare le chiavi utente") - sebbene il tutorial menzioni Ubuntu è indipendente dalla distribuzione, ma è necessaria una nuova versione di OpenSSH che supporti SSH CA

Un altro buon post di blog sull'argomento è https://ef.gy/hardening-ssh (scorrere fino a "Certificati SSH").

Prestare particolare attenzione al fatto che è possibile firmare la chiave per essere validi per un periodo di tempo limitato, quindi scadranno automaticamente!


Sarebbe una buona idea se le macchine dei clienti avessero accesso a Internet (per aggiornare la validità di una firma), il che non è sempre il caso. Ci colleghiamo a queste macchine tramite una VPN fornita dal cliente.
Raspbeguy,

Bene, questo è il più vicino possibile senza perdere una chiave con una persona che lascia la tua azienda. Ti ho fornito il meccanismo, puoi automatizzarlo, ad esempio puoi avere un ufficiale di servizio che supporta il tuo personale quando le persone lasciano la compagnia e puoi definire una procedura su come revocare le chiavi.
galaxy

1
Inoltre, puoi firmare una chiave (quella di supporto) per un periodo di tempo limitato, ad esempio puoi firmarla solo per 8 ore (per il loro turno), dopo 8 ore scadrà e il server non le lascerà entrare.
galassia

3
Per quanto riguarda la tua parte LDAP - Attualmente sto lavorando in un'azienda che gestisce centinaia di istanze e stiamo lavorando a una soluzione open source per integrare SAML 2.0 e SSH CA. L'idea è che una persona esegua l'autenticazione tramite SSO e se autorizzata ottiene la firma delle chiavi per un periodo di tempo definito (ad es. 5 minuti). Tutto questo è abbastanza trasparente per l'utente e viene implementato usando ProxyCommand di ~ / .ssh / config.
galaxy

2

Ci sono un paio di risposte diverse che coinvolgono uno script wrapper per ssh invocato tramite sudo o setuid-eseguibile (ad alcuni account non root per scopi speciali ). Come dice nkms , passare attraverso tutti gli argomenti a ssh consente all'utente di fare cose arbitrarie con i tasti ssh che stiamo cercando di proteggere. L'altro estremo che alcuni hanno escogitato è quello di consentire solo un nome host.

L'OP afferma che gli amministratori devono essere in grado di caricare le cose.

Potresti avere due differenti wrapper fixed-args-to-ssh. Uno per una shell di login, un altro per scp. Nessun argomento fornito dall'utente diverso dal nome host (e dal nome file da caricare).

O uno script wrapper che si utilizza getoptper analizzare opzioni molto limitate e collegare le cose in un comando ssh per lo più fisso. Ignorare (o errori) su opzioni non riconosciute sarebbe la strada da percorrere.

Non provare a filtrare le opzioni ssh "pericolose", basta scrivere un wrapper che può fare due cose: login interattivo o caricare un file (nomi di file locali e remoti). Devi ancora disinfettare lì, suppongo.

In realtà, è ancora facile sbagliarsi. Devi trovare un modo per impedire all'utente di fornire il file contenente i tasti ssh come file locale. Quindi stai ancora cercando di pensare a tutto ciò che deve essere vietato, invece di iniziare dal non consentire nulla. Sarebbe un inizio per assicurarsi che i nomi dei file non contengano alcuno @o :.


L'idea del wrapper è davvero la soluzione, ma ciò implica una violazione della sicurezza che deve essere colmata.
Raspbeguy,

Sono stupito di come le persone reinventino la ruota quando non ce n'è bisogno. La funzionalità SSH CA è stata introdotta in OpenSSH esattamente per ragioni e situazioni come la domanda originale. La mia soluzione non ha utilizzato alcun wrapper e non ha ottenuto esattamente ciò che è stato chiesto, tuttavia, per qualche motivo @Raspbeguy ha deciso di seguire la strada del fai-da-te con implicazioni di sicurezza discutibili. :)
galaxy

@galaxy: sì, la tua soluzione SSH CA è sicuramente la migliore, a meno che tu non abbia un requisito assoluto che non puoi apportare una modifica una tantum ai sistemi remoti per configurare il loro sshd per usarlo. Sembra perfetto e facile da ottenere.
Peter Cordes,

@galaxy: la tua soluzione è davvero elegante, ma non applicabile nel mio caso, come ti ho detto prima. L'idea mi piace molto, ne ho parlato con il mio capo ma è ancora impossibile. Non c'è bisogno di arrabbiarsi.
Raspbeguy,

1
@Raspbeguy, non sono arrabbiato, semplicemente non capisco perché la tua azienda vuole sacrificare la propria sicurezza e implementare qualcosa usando il "nastro adesivo" quando c'è un modo corretto per farlo. E il tuo commento è stato che sarebbe stata una buona soluzione, ma non ti è piaciuto non poter automatizzare la revoca - e ti ho fornito anche la soluzione (firmando le chiavi solo per il turno). Comunque, hai scelto la tua risposta, andiamo avanti :)
galaxy

1

Se si configura un server proxy SSH, è possibile disporre che la shell (in /etc/passwd) degli utenti non sia impostata su una shell come bash, ma su un semplice script che non consente l'accesso alla shell. Invece, richiederebbe un nome host di destinazione ( read target), quindi exec ssh "support@$target".

Si noti che l'utilizzo di un proxy come questo potrebbe rendere difficile l'utilizzo di strumenti come il scptrasferimento di file da / verso i computer dei clienti. Questo può essere un problema o un vantaggio!


Questa idea di wrapper-script è simile all'idea di @ roaima. Stai dando accesso ad esso con ssh, ma sudofunziona anche. La sua risposta suggerisce di utilizzare l'utente root locale, ma funzionerebbe anche un utente non root. Vedi i miei commenti sulla sua risposta per una discussione al riguardo. (La mia ssh keyowner@localhostidea è la stessa della tua idea.)
Peter Cordes,

@Peter - assolutamente giusto: root è assolutamente l'utente sbagliato per questo!
Toby Speight,

Supporta i ragazzi a caricare le cose, quindi questa soluzione potrebbe non funzionare.
Raspbeguy,

@Raspbeguy: ha pubblicato una risposta che risolve questo problema. Utilizzare in combinazione con l'installazione non root di roaima sudo.
Peter Cordes,

0

Il personale di supporto si collega sempre tramite quella macchina proxy e solo da essa, in modo che i client possano semplicemente autenticare la macchina proxy utilizzando HostbasedAuthentication .

Supponiamo che sia la macchina proxy supporters.pce fornisci supporto acustomer.pc

customer.pc avrà HostbasedAuthentication sì in /etc/ssh/ssd_config, supporters.pc elencato in /etc/ssh/shosts.equive la sua chiave pubblica in /etc/ssh/ssh_known_hosts.

Quando il personale di supporto ssh customer.pcaccederà a support@supporters.pc e si esibirà , genererà ssh-keysign (8) (che deve essere impostato), che gestirà la firma della chiave con il file che non puoi leggere e fornire prova a supporters.pc che la connessione proviene effettivamente da supporters.pc . Poiché customer.pc si fida di supporters.pc , il membro del personale viene registrato come supporto .


Questa è una soluzione terribile dal punto di vista della sicurezza poiché se si sta concedendo l'accesso a una macchina nel suo complesso e si perde la responsabilità di chi ha fatto cosa. La fiducia machine-to-machine dovrebbe essere bandita dal mondo moderno in cui la sicurezza IT ha iniziato a emergere come argomento piuttosto caldo.
galaxy

@galaxy, dall'OP la mia comprensione è che lo stanno già facendo sostanzialmente. La fiducia in quella macchina è nelle specifiche . Si noti in particolare che "utilizzano solo un account per computer (l'account di accesso al supporto)" è possibile che stiano utilizzando un account condiviso in customer.pc, ma si collegano al server come proprio utente. Cambiare i permessi di ssh e ssh-keygen per forzare un supporto sudo -u ssh ... lo risolverebbe e aggiungerebbe anche una voce di registro.
Ángel,

0

Utilizzare un file binario wrapper

Per questo particolare caso d'uso (vedere la nota importante di seguito), una possibilità è quella di creare un utente (diciamo support-ssh) specificamente per queste connessioni SSH in uscita, quindi installare un piccolo binario wrapper che esegua /usr/bin/ssh.

  • Non copiare + chmod il file sshbinario stesso, perché non ti ricorderai di copiarlo ogni volta che applichi gli aggiornamenti di sicurezza.
  • E non utilizzare rootcome utente con più privilegi, per motivi di cui mi fido sono ovvi.

Questa è un'alternativa funzionalmente equivalente all'utilizzo sudoper elevare i privilegi a quello support-sshdell'account con i seguenti compromessi:

  • Questo è più piccolo e più sottile di sudo, quindi c'è meno rischio di errore di configurazione che si apre più del previsto.
  • È responsabilità dell'utente codificarlo correttamente: farlo solo se si è estremamente cauti e (idealmente) si ha esperienza di codifica critica per la sicurezza.
  • Può essere personalizzato per essere più specifico di sudo(ma più codice scrivi, più devi controllare per motivi di sicurezza).

Il file binario del wrapper deve essere impostato HOMEsulla support-sshhome directory dell'utente, in modo che sshraccolga la ssh_configchiave appropriata e privata. Ma l'utente che invoca non dovrebbe essere autorizzato a leggere ~support-ssh/.ssh/o al suo contenuto.

Il wrapper potrebbe essere semplice come:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    setenv("HOME", "/home/support-ssh", 1);
    /* allow only a single, non-option argument */
    if (argc!=2 || *argv[1]=='-') {
        fprintf(stderr, "Usage: %s <hostname>", argv[0]);
        exit(EXIT_FAILURE);
    }
    execv("/usr/bin/ssh", argv);
    return EXIT_FAILURE;
}

Potresti voler essere più restrittivo e verificare che l'argomento argv[1]si trovi in ​​un set di nomi host consentiti. O meno restrittivo e consenti (un sottoinsieme di) argomenti di opzioni. Si potrebbe desiderare di sostituire completamente le variabili d'ambiente (ma mantenere quelli importanti come TERM, LC_*, ecc); notare che LD_LIBRARY_PATHe LD_PRELOADsono particolarmente pericolosi.

Un programma wrapper simile potrebbe essere fornito scpse necessario.

Una nota sull'applicabilità

Questa risposta affronta le circostanze specifiche della domanda, in cui gli utenti sono contrattualmente obbligati a seguire le procedure e vi sono sanzioni (ad esempio il licenziamento) per la loro violazione. Suppone che tu voglia impedire ai dipendenti di copiare casualmente le chiavi private in giro, piuttosto che impedire a un determinato aggressore di ottenere accesso non autorizzato.

Ritengo che la sicurezza sia raggiunta attraverso difese sia tecniche che non tecniche e che l'equilibrio raggiunto qui o utilizzando sudosia appropriato per la situazione presentata.


Passi argomenti non controllati a ssh in esecuzione come un altro utente, vedi il mio commento sulla risposta sopra. Riesco ancora a leggere la chiave ... e non vorrei contare su rigidi controlli degli argomenti, ssh non è pensato per essere eseguito in quel modo.
nkms,

@nkms - Ho reso il wrapper più restrittivo. Può essere reso più aperto, se necessario, ma hai ragione a bloccare le cose se non diversamente richiesto, piuttosto che viceversa.
Toby Speight,

@TobySpeight: sì, sembra buono. Ho inserito la maggior parte di ciò che ho detto nei commenti nella mia risposta.
Peter Cordes,

1
Sarebbe meglio usare sudo che un wrapper binario. Contrariamente a quanto asserisci, l'uso di sudo è molto meno rischioso rispetto al lancio del tuo. Il Sudo ha impostazioni predefinite sicure. Quanto sei sicuro di non aver dimenticato di rimuovere una variabile d'ambiente che influenzerebbe ssh?
Gilles 'SO- smetti di essere malvagio' il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.