Come usare sudo via SSH senza esporre la password

Usa ssh -t user@server 'sudo command' e digita la password al prompt: SSH la cifra come tutto il resto della sessione. La fuga nasce dal mettere la password in un comando, perché ssh server 'echo pass | sudo -S command' la mostra nell'elenco dei processi di entrambe le macchine e può finire nella cronologia della shell. Per l'automazione, usa una regola NOPASSWD per un solo comando esatto.

Aggiornata il . Eseguito con sudo 1.9.16 e OpenSSH 10.0 su Debian 13 in un container usa e getta, da un client OpenSSH 10.3 su macOS.

La password di sudo viaggia in chiaro?

Non sulla rete. Tutto in una sessione SSH è cifrato, compreso ciò che digiti al prompt di sudo. La password viene decifrata sul server, come deve essere perché sudo la controlli, quindi un server compromesso può catturarla. È un motivo per non riusare quella password altrove.

Il modo normale: ssh -t

sudo ha bisogno di un terminale per chiedere una password, e un comando remoto di default non ne riceve uno:

$ ssh user@server 'sudo whoami'
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
sudo: a password is required

L'errore suggerisce -S, ed è qui che si sbaglia. La soluzione semplice è -t, che chiede un terminale:

ssh -t user@server 'sudo whoami'

Ottieni il prompt normale, niente viene mostrato a schermo e niente finisce in una riga di comando.

Cosa trapela con sudo -S

Ecco lo schema da evitare:

ssh user@server 'echo mypassword | sudo -S systemctl restart myapp'

La password ora fa parte di un comando, quindi compare in tre posti:

  • L'elenco dei processi sul server. Mentre il comando girava, un altro account senza privilegi sul server di prova ha visto questo con un semplice ps: user bash -c echo mypassword | sudo -S -p "" sleep 3.
  • L'elenco dei processi sulla tua macchina. L'intero testo è un argomento di ssh, quindi ps lo mostra anche lì.
  • La cronologia della tua shell locale, se l'hai digitato, e qualsiasi script o log di CI che lo contenga.

Se proprio devi dare la password a sudo da uno script

Leggi la password senza eco e inviala dallo standard input, così non diventa mai un argomento:

read -rs SUDO_PW
printf '%s\n' "$SUDO_PW" | ssh user@server 'sudo -S -p "" whoami'
unset SUDO_PW

printf è un builtin della shell, quindi non avvia un processo che ps possa mostrare. Nella stessa prova l'altro account vedeva solo sudo -S -p sleep 3. -p "" toglie il prompt dall'output. Qui sudo usa lo standard input per la password, quindi il comando remoto non deve aspettarsi input proprio.

Per l'automazione: NOPASSWD per un solo comando esatto

Uno script non dovrebbe contenere affatto una password. Consenti solo ciò che gli serve:

# /tmp/deploy.sudoers
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart myapp, /usr/bin/journalctl -u myapp -n 100 --no-pager

Controlla il file prima di installarlo, perché un file sudoers rotto può chiuderti fuori da sudo:

sudo visudo -cf /tmp/deploy.sudoers
sudo install -m 0440 -o root -g root /tmp/deploy.sudoers /etc/sudoers.d/deploy
sudo visudo -c

Poi usalo, con -n così una mancata corrispondenza fallisce subito e non resta in attesa di una password:

$ ssh deploy@server 'sudo -n /usr/bin/systemctl restart myapp'
$ ssh deploy@server 'sudo -n /usr/bin/systemctl stop myapp'
sudo: a password is required

Elenca ciò che un account può eseguire con sudo -l. Quattro trappole:

  • Un comando senza argomenti nella regola consente qualsiasi argomento. Con il solo /usr/bin/id nella regola, nel nostro test hanno funzionato sia sudo -n /usr/bin/id sia sudo -n /usr/bin/id -u. Scrivi gli argomenti che intendi.
  • I nomi di file con un punto vengono ignorati. /etc/sudoers.d/deploy.conf non ha avuto effetto nel nostro test, mentre lo stesso file chiamato deploy ha funzionato.
  • Alcuni comandi possono avviare una shell. Editor, pager, find -exec e tar possono eseguire altri programmi come root, quindi consentirne uno può equivalere a consentire tutto. Per questo la regola qui sopra ha --no-pager: senza, journalctl può aprire un pager.
  • I caratteri jolly corrispondono anche agli spazi. Il manuale di sudoers avverte che i caratteri jolly negli argomenti corrispondono a qualsiasi carattere, spazi compresi, quindi possono corrispondere a più argomenti di quelli previsti.

Per quanto tempo sudo si ricorda di te

Per impostazione predefinita sudo non richiede la password per 5 minuti, e il ricordo è separato per ogni terminale. Nella prova, una sessione ssh -t ha eseguito un secondo sudo -n whoami senza richiesta. Per terminarlo prima, esegui sudo -k. Per chiedere la password ogni volta a un solo account, aggiungi questo con visudo:

Defaults:deploy timestamp_timeout=0

Una shell di root lasciata aperta è dove capitano più sviste. Vedi come evitare errori sui server di produzione.

sudo -A e askpass

Con -A, sudo esegue il programma indicato in SUDO_ASKPASS e legge la password dal suo output:

SUDO_ASKPASS=$HOME/bin/askpass sudo -A whoami

Tiene la password fuori dall'elenco dei processi, ma l'helper deve ottenerla da qualche parte. Su un server senza sessione grafica, di solito significa un file, come nel nostro test, quindi il segreto ora sta su disco. Una regola NOPASSWD ristretta è in genere la risposta migliore.

Ansible

Usa --ask-become-pass (-K) per ricevere una richiesta, oppure tieni ansible_become_password in un file cifrato con Ansible Vault. Non passarla con -e sulla riga di comando, perché finisce nell'elenco dei processi e nella cronologia come qualsiasi altro argomento.

Una regola NOPASSWD per pochi comandi non funziona con Ansible. La sua documentazione dice che l'escalation dei privilegi non può essere limitata a certi comandi, perché i moduli vengono eseguiti da un file temporaneo il cui nome cambia ogni volta. Suggerisce di usare un account separato senza questo vincolo.

Domande

La password di sudo passa in chiaro su SSH?

No. Tutto quello che passa in una sessione SSH è cifrato, compreso ciò che digiti al prompt di sudo. Viene decifrata sul server, che deve controllarla.

Perché ssh dice che serve un terminale per leggere la password?

Un comando remoto di base non riceve un terminale, e sudo ne ha bisogno per chiedere la password. Aggiungi -t, come in ssh -t user@server 'sudo command'.

NOPASSWD è sicuro per gli script?

È più sicuro di una password salvata quando la regola indica un solo comando preciso con i suoi argomenti. Evita editor, pager e altri programmi che possono avviare una shell.

Fonti

Altro in Mettere in sicurezza un server

Tutte le guide