Come limitare gli utenti SSH a un set predefinito di comandi dopo il login?


88

Questa è un'idea per una sicurezza. I nostri dipendenti avranno accesso ad alcuni comandi su un server Linux ma non a tutti. Devono ad esempio avere la possibilità di accedere a un file di log ( less logfile) o avviare diversi comandi ( shutdown.sh/ run.sh).

Informazioni di base:

Tutti i dipendenti accedono al server con lo stesso nome utente: il nostro prodotto funziona con autorizzazioni utente "normali", non è necessaria alcuna "installazione". Basta decomprimerlo nella directory utente ed eseguirlo. Gestiamo diversi server dove la nostra applicazione è "installata". Su ogni macchina c'è un utente johndoe. A volte i nostri dipendenti hanno bisogno di accedere all'applicazione sulla riga di comando per accedere e controllare i file di registro o per riavviare l'applicazione manualmente. Solo alcune persone avranno accesso completo alla riga di comando.

Stiamo utilizzando l'autenticazione ppk sul server.

Sarebbe fantastico se dipendente1 potesse accedere solo al file di registro e dipendente2 potesse anche fare X ecc ...

Soluzione: come soluzione userò l' commandopzione come indicato nella risposta accettata . Creerò il mio piccolo script di shell che sarà l'unico file che può essere eseguito per alcuni dipendenti. Lo script offrirà diversi comandi che possono essere eseguiti, ma nessun altro. Userò i seguenti parametri authorized_keysda come indicato qui :

command="/bin/myscript.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
ssh-dss AAAAB3....o9M9qz4xqGCqGXoJw= user@host

Questa è una sicurezza sufficiente per noi. Grazie, comunità!


La sicurezza basata su autorizzazione ACL standard di Linux non è sufficiente? Di quali funzionalità extra hai bisogno?
James Brady

22
È un'idea orribile, Marcel.
Vinko Vrsalovic

14
@Vinko, @PEZ: ho aggiunto alcune informazioni di base. Invece di dire "idea stupida" potresti fornire commenti di valore. Qual è secondo te un'idea migliore?
Marcel

8
Continuo a non vedere nessuna scusa per avere più utenti che condividono lo stesso nome utente.
Eldelshell

3
"Il mio piccolo script di shell"? Sembra abbastanza pericoloso. A meno che tu non sia un esperto, ci sono probabilmente molti modi per sfuggire al guscio completo. Preferirei fidarmi di un programma ben scritto, sottoposto a debug e mantenuto (molti sono stati menzionati).
bortzmeyer

Risposte:


69

Puoi anche limitare le chiavi ai comandi consentiti (nel file authorized_keys).

Cioè l'utente non accede tramite ssh e quindi dispone di un insieme limitato di comandi, ma piuttosto può eseguire quei comandi solo tramite ssh (ad esempio "ssh somehost bin / showlogfile")


Sembra interessante. È possibile definire più comandi?
Marcel

12
Questo articolo offre alcune opzioni per più comandi utilizzando il file authorized_keys: linuxjournal.com/article/8257
Bash

@ rd834 ...: Grazie mille. Penso che questo mi abbia dato una "buona" soluzione ... (aggiunta alla domanda). Accetterò questa risposta come "corretta".
Marcel

11
Il libro O'Reilly SSH ha un'eccellente spiegazione di come farlo, incluso consentire più comandi impostando uno script che guarda alla variabile d'ambiente SSH_ORIGINAL_COMMAND. oreilly.com/catalog/sshtdg/chapter/ch08.html
Alex Dupuy

5
questa risposta serverfault ha un bel suggerimento su come consentire più comandi utilizzando la variabile SSH_ORIGINAL_COMMAND esportata.
MattBianco

33

sshsegue la rshtradizione utilizzando il programma shell dell'utente dal file delle password per eseguire i comandi.

Ciò significa che possiamo risolvere questo problema senza coinvolgere sshin alcun modo la configurazione.

Se non vuoi che l'utente possa avere accesso alla shell, sostituisci semplicemente la shell dell'utente con uno script. Se guardi dentro /etc/passwd, vedrai che c'è un campo che assegna un interprete dei comandi di shell ad ogni utente. Lo script viene utilizzato come shell sia per il loro login interattivo ssh user@host che per i comandi ssh user@host command arg ....

Ecco un esempio. Ho creato un utente la foocui shell è uno script. Lo script stampa il messaggio my arguments are:seguito dai suoi argomenti (ciascuno su una riga separata e tra parentesi angolari) e termina. Nel caso del registro, non ci sono argomenti. Ecco cosa succede:

webserver:~# ssh foo@localhost
foo@localhost's password:
Linux webserver [ snip ]
[ snip ]
my arguments are:
Connection to localhost closed.

Se l'utente tenta di eseguire un comando, assomiglia a questo:

webserver:~# ssh foo@localhost cat /etc/passwd
foo@localhost's password:
my arguments are:
<-c>
<cat /etc/passwd>

La nostra "shell" riceve -cun'invocazione di stile, con l'intero comando come un argomento, proprio nello stesso modo in cui /bin/shlo riceverebbe.

Quindi, come puoi vedere, quello che possiamo fare ora è sviluppare ulteriormente lo script in modo che riconosca il caso quando è stato invocato con un -cargomento, e quindi analizzi la stringa (diciamo tramite pattern matching). Quelle stringhe consentite possono essere passate alla shell reale invocando ricorsivamente /bin/bash -c <string>. Il caso di rifiuto può stampare un messaggio di errore e terminare (incluso il caso in cui -cmanca).

Devi stare attento a come scrivi questo. Consiglio di scrivere solo corrispondenze positive che consentono solo cose molto specifiche e non consentono tutto il resto.

Nota: se lo sei root, puoi comunque accedere a questo account sovrascrivendo la shell nel sucomando, in questo modo su -s /bin/bash foo. (Sostituisci la shell di scelta.) Non root non può farlo.

Ecco uno script di esempio: limita l'utente all'utilizzo solo sshper l' gitaccesso ai repository in /git.

#!/bin/sh

if [ $# -ne 2 ] || [ "$1" != "-c" ] ; then
  printf "interactive login not permitted\n"
  exit 1
fi

set -- $2

if [ $# != 2 ] ; then
  printf "wrong number of arguments\n"
  exit 1
fi

case "$1" in
  ( git-upload-pack | git-receive-pack )
    ;; # continue execution
  ( * )
    printf "command not allowed\n"
    exit 1
    ;;
esac

# Canonicalize the path name: we don't want escape out of
# git via ../ path components.

gitpath=$(readlink -f "$2")  # GNU Coreutils specific

case "$gitpath" in
  ( /git/* )
     ;; # continue execution
  ( * )
    printf "access denied outside of /git\n"
    exit 1
    ;;
esac

if ! [ -e "$gitpath" ] ; then
   printf "that git repo doesn't exist\n"
   exit 1
fi

"$1" "$gitpath"

Naturalmente, ci fidiamo che questi programmi Git git-upload-packe git-receive-packnon abbiano buchi o portelli di fuga che consentiranno agli utenti di accedere al sistema.

Ciò è inerente a questo tipo di regime di restrizione. L'utente è autenticato per eseguire codice in un determinato dominio di sicurezza e stiamo adottando una restrizione per limitare quel dominio a un sottodominio. Ad esempio, se consenti a un utente di eseguire il vimcomando su un file specifico per modificarlo, l'utente può semplicemente ottenere una shell con :!sh[Enter].


6
Seriamente, questo è MOLTO PERICOLOSO. Cosa mi impedirà di eseguire git-receive-pack '/git/';dd if=/dev/urandom of=/dev/sda?
Yeti

@ Yeti Abbiamo un foro di iniezione dei comandi qui? Questo deve essere affrontato. Inoltre, l'abuso dei modelli di file che ho perpetrato in casenon mi sembra corretto.
Kaz

1
Sì, non /bin/bash -c "$2"è sicuro (simile a come funziona SQL injection). Puoi filtrare la stringa con "virgolette magiche" come PHP. Ma il modo più semplice per garantire la sicurezza assoluta è chiamare manualmente un comando e quindi passare i parametri tra virgolette doppie. Perché la sicurezza dell'intera cosa dipende quindi dal fatto che quel comando sia l'anello più debole (più difficile da verificare). È molto interessante vedere come la tua risposta abbia 22 voti positivi, ma nessuno l'ha notato;) Aggiornerai la tua risposta?
Yeti

1
@Yeti Sì; L'ho appena fatto. Ho sostituito lo script con uno che interrompe l'argomento -c con sete quindi prende solo le prime due parole da esso. Il primo deve essere un git-comando consentito e il secondo deve essere un percorso canonizzato, confrontato con il prefisso consentito e anche verificato per l'esistenza. Riesci a pensare a un modo per rompere questo?
Kaz

1
A meno che qualcuno non crei un alias (o sovrascriva un comando) per uno qualsiasi dei comandi dati, allora no, le virgolette doppie di Bash dovrebbero essere sicure (e in caso contrario, questo è un bug in Bash).
Yeti

15

Quello che stai cercando si chiama Restricted Shell . Bash fornisce una tale modalità in cui gli utenti possono eseguire solo i comandi presenti nelle loro directory home (e non possono spostarsi in altre directory), il che potrebbe essere abbastanza buono per te.

Ho trovato questo thread molto illustrativo, anche se un po 'datato.


1
E se l'utente fa "! / Bin / sh" o qualcosa di simile dal prompt less?
PEZ

3
@Ubersoldat: Per favore, cresci e attenua l'aggressività in tutti i tuoi post. Stava chiedendo se la restrizione si applica solo ai processi bash o figli (e per rispondere alla sua domanda, si scopre che non è così).

Uno dei problemi principali con la shell limitata è che per proteggerla, è necessario utilizzare .profile o .bashrc per limitare il PERCORSO, disabilitare i builtin, ecc., Ma quei file vengono invocati solo per le shell interattive. Se un utente utilizza ssh per eseguire un comando remoto, non viene richiamato. Ciò consente a un utente con accesso ssh a un account con SHELL = / bin / rbash di fare semplicemente qualcosa come "ssh remotehost bash" per ottenere una shell non interattiva ma senza restrizioni. Hai bisogno di comandi SSH forzati come suggerito da HD, ma questo può proteggere dagli escape della shell come richiesto da PEZ (una volta che PATH è bloccato - include / bin: / usr / bin per impostazione predefinita).
Alex Dupuy

2
Lo prendo indietro, bash sarà richiamare .bashrc (non .profile) durante l'esecuzione in modo non interattivo in sshd; tuttavia, devi assicurarti di impostare PATH in modo esplicito e disabilitare i builtin e gli alias in .bashrc - anche il passaggio a una sottodirectory non in / sopra PATH o .ssh / o .bashrc è una buona idea. Avere un comando in grado di scrivere su file arbitrari creerà un problema - questi non sono sempre ovvi, ad esempio il comando sed 'w' potrebbe essere usato per sovrascrivere .bashrc e scoppiare. Una jail chroot sarà sempre più sicura se puoi usarla, e i comandi forzati ssh saranno più limitati.
Alex Dupuy

5

Perché non scrivi la tua shell di login? Sarebbe abbastanza semplice usare Bash per questo, ma puoi usare qualsiasi lingua.

Esempio in Bash

Usa il tuo editor preferito per creare il file /root/rbash.sh(può essere qualsiasi nome o percorso, ma dovrebbe essere chown root:roote chmod 700):

#!/bin/bash

commands=("man" "pwd" "ls" "whoami")
timestamp(){ date +'%Y-%m-%s %H:%M:%S'; }
log(){ echo -e "$(timestamp)\t$1\t$(whoami)\t$2" > /var/log/rbash.log; }
trycmd()
{
    # Provide an option to exit the shell
    if [[ "$ln" == "exit" ]] || [[ "$ln" == "q" ]]
    then
        exit
        
    # You can do exact string matching for some alias:
    elif [[ "$ln" == "help" ]]
    then
        echo "Type exit or q to quit."
        echo "Commands you can use:"
        echo "  help"
        echo "  echo"
        echo "${commands[@]}" | tr ' ' '\n' | awk '{print "  " $0}'
    
    # You can use custom regular expression matching:
    elif [[ "$ln" =~ ^echo\ .*$ ]]
    then
        ln="${ln:5}"
        echo "$ln" # Beware, these double quotes are important to prevent malicious injection
        
        # For example, optionally you can log this command
        log COMMAND "echo $ln"
    
    # Or you could even check an array of commands:
    else
        ok=false
        for cmd in "${commands[@]}"
        do
            if [[ "$cmd" == "$ln" ]]
            then
                ok=true
            fi
        done
        if $ok
        then
            $ln
        else
            log DENIED "$cmd"
        fi
    fi
}

# Optionally show a friendly welcome-message with instructions since it is a custom shell
echo "$(timestamp) Welcome, $(whoami). Type 'help' for information."

# Optionally log the login
log LOGIN "$@"

# Optionally log the logout
trap "trap=\"\";log LOGOUT;exit" EXIT

# Optionally check for '-c custom_command' arguments passed directly to shell
# Then you can also use ssh user@host custom_command, which will execute /root/rbash.sh
if [[ "$1" == "-c" ]]
then
    shift
    trycmd "$@"
else
    while echo -n "> " && read ln
    do
        trycmd "$ln"
    done
fi

Tutto quello che devi fare è impostare questo eseguibile come shell di login. Ad esempio, modifica il tuo /etc/passwdfile e sostituisci la tua attuale shell di login di quell'utente /bin/bashcon /root/rbash.sh.

Questo è solo un semplice esempio, ma puoi renderlo avanzato quanto vuoi, l'idea è lì. Fai attenzione a non bloccarti cambiando la shell di login del tuo e unico utente. E prova sempre simboli e comandi strani per vedere se è effettivamente sicuro.

È possibile verificare con: su -s /root/rbash.sh.

Fai attenzione , assicurati di abbinare l'intero comando e fai attenzione ai caratteri jolly! Meglio escludere Bash-simboli come ;, &, &&, ||, $, e apici inversi per essere sicuri.

A seconda della libertà che dai all'utente, non sarà molto più sicuro di così. Ho scoperto che spesso avevo solo bisogno di creare un utente che avesse accesso solo a pochi comandi rilevanti, e in tal caso questa è davvero la soluzione migliore. Tuttavia, se desideri dare più libertà, una prigione e le autorizzazioni potrebbero essere più appropriate. Gli errori sono facili e vengono notati solo quando è già troppo tardi.


Mi è piaciuto molto questo approccio. Hai idea di come possiamo gestire comandi composti da più parole come "service httpd restart"?
Farzan

2
@Farzan È possibile eseguire i comandi in una variabile, ad esempio ln="service httpd restart", con: ${ln[@]}. Assicurati comunque di pensare ai problemi di sicurezza, una whitelist per soli caratteri alfanumerici e spazi bianchi sarebbe utile in questo caso. Ma puoi anche fare:, if [[ "$ln" == "restart-httpd"];then service httpd restart;fie lavorare con comandi semplici come quello.
Yeti

/root/rbash.sh: Permission denied Ho provato anche chmod 777
Christian

@Christian, hai aggiunto /root/rbash.sha /etc/shells? Dipende dalla distribuzione. Puoi anche provare a disabilitare temporaneamente selinuxe controllare i messaggi di log per trovare indizi (guarda il timestamp) nei file in formato /var/log.
Yeti

@yeti no, è stato spiegato di aggiungere a / root :) Proverò ora.
Christian

4

Dovresti acquisire "rssh", la shell limitata

Puoi seguire le guide alle restrizioni sopra menzionate, sono tutte piuttosto autoesplicative e semplici da seguire. Comprendere i termini "chroot jail" e come implementare efficacemente le configurazioni sshd / terminal, e così via.

Dato che la maggior parte dei tuoi utenti accede ai tuoi terminali tramite sshd, dovresti anche esaminare sshd_conifg, il file di configurazione del demone SSH, per applicare determinate restrizioni tramite SSH. Stai attento, però. Comprendi bene cosa cerchi di implementare, poiché le ramificazioni di configurazioni errate sono probabilmente piuttosto disastrose.


1
Nota che pizzashack.org/rssh è un'ottima (forse la migliore) soluzione per il caso speciale in cui vuoi consentire scp / sftp / rdist / rsync / cvs (e non hai bisogno di accedere a nulla al di fuori di una prigione chroot) - tuttavia , non risolve la questione generale del poster originale, che voleva che gli utenti fossero in grado di visualizzare i file di registro ed eseguire determinati script di esecuzione / chiusura.
Alex Dupuy

2
rsshè stato rimosso da Debian Buster. Penso che la nuova piccantezza sia la corsa GNU .
Thomas

1
@Thomas, credo che rssh non sia più mantenuto e abbia un problema di sicurezza noto: sourceforge.net/p/rssh/mailman/message/36519118
Max Barraclough

2

GNU Rush potrebbe essere il modo più flessibile e sicuro per ottenere ciò:

GNU Rush è una Restricted User Shell, progettata per i siti che forniscono un accesso remoto limitato alle proprie risorse, come i repository svn o git, scp o simili. Utilizzando un sofisticato file di configurazione, GNU Rush ti dà il controllo completo sulle righe di comando che gli utenti eseguono, nonché sull'utilizzo delle risorse di sistema, come la memoria virtuale, il tempo della CPU, ecc.



0

Un altro modo di vedere questo è usare POSIX ACL, deve essere supportato dal tuo file system, tuttavia puoi avere una messa a punto dettagliata di tutti i comandi in Linux nello stesso modo in cui hai lo stesso controllo su Windows (solo senza l'interfaccia utente più bella ). collegamento

Un'altra cosa da esaminare è PolicyKit .

Dovrai fare un po 'di ricerca su Google per far funzionare tutto poiché questo non è sicuramente un punto di forza di Linux al momento.


0

[Divulgazione: ho scritto sshdo che è descritto di seguito]

Se vuoi che il login sia interattivo, configurare una shell limitata è probabilmente la risposta giusta. Ma se c'è un insieme effettivo di comandi che vuoi consentire (e nient'altro) ed è ok che questi comandi vengano eseguiti individualmente tramite ssh (ad esempio ssh user @ host cmd arg blah blah), allora un comando generico per il controllo della whitelist ssh potrebbe essere ciò di cui hai bisogno. Ciò è utile quando i comandi sono in qualche modo inseriti in script all'estremità del client e non richiede all'utente di digitare effettivamente il comando ssh.

C'è un programma chiamato sshdo per farlo. Controlla quali comandi possono essere eseguiti tramite le connessioni ssh in entrata. È disponibile per il download su:

http://raf.org/sshdo/ (leggi le pagine di manuale qui) https://github.com/raforg/sshdo/

Ha una modalità di addestramento per consentire tutti i comandi tentati e un'opzione --learn per produrre la configurazione necessaria per consentire i comandi appresi in modo permanente. Quindi la modalità training può essere disattivata e qualsiasi altro comando non verrà eseguito.

Ha anche un'opzione --unlearn per smettere di consentire comandi che non sono più in uso in modo da mantenere il privilegio minimo rigoroso quando i requisiti cambiano nel tempo.

È molto esigente su ciò che consente. Non consentirà un comando con alcun argomento. Possono essere consentiti solo comandi shell completi.

Ma supporta modelli semplici per rappresentare comandi simili che variano solo nelle cifre che appaiono sulla riga di comando (ad esempio numeri di sequenza o indicatori di data / ora).

È come un firewall o un controllo whitelist per i comandi ssh.

E supporta diversi comandi consentiti per utenti diversi.

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.