Come vengono analizzati gli argomenti della riga di comando remota di ssh


11

Ho visto le domande e le risposte sulla necessità di sfuggire al doppio degli argomenti ai comandi remoti di ssh. La mia domanda è: esattamente dove e quando viene eseguita la seconda analisi?

Se eseguo quanto segue:

$ ssh otherhost pstree -a -p

Vedo quanto segue nell'output:

  |-sshd,3736
  |   `-sshd,1102
  |       `-sshd,1109
  |           `-pstree,1112 -a -p

Il processo parent per il comando remoto ( pstree) è sshdche non sembra esserci alcuna shell che analizzi gli argomenti della riga di comando con il comando remoto, quindi non sembra che siano necessarie doppie virgolette o escape ( ma sicuramente lo è). Se invece ho prima ssh lì e ottengo una shell di login, quindi eseguo pstree -a -pvedo quanto segue nell'output:

  ├─sshd,3736
     └─sshd,3733
         └─sshd,3735
             └─bash,3737
                 └─pstree,4130 -a -p

Quindi chiaramente c'è una bashshell lì che farebbe l'analisi della riga di comando in quel caso. Ma nel caso in cui utilizzo direttamente un comando remoto, non sembra esserci una shell, quindi perché è necessaria la doppia virgoletta?

Risposte:


22

C'è sempre una shell remota. Nel protocollo SSH, il client invia al server una stringa da eseguire. Il client della riga di comando SSH accetta i suoi argomenti della riga di comando e li concatena con uno spazio tra gli argomenti. Il server accetta quella stringa, esegue la shell di accesso dell'utente e le passa quella stringa.

È impossibile bypassare la shell remota. Il protocollo non ha nulla di simile all'invio di un array di stringhe che possono essere analizzate come array argv sul server. E il server SSH non aggirerà la shell remota perché ciò potrebbe costituire una limitazione di sicurezza: l'utilizzo di un programma limitato come shell dell'utente è un modo per fornire un account limitato a cui è consentito eseguire solo determinati comandi (ad esempio un account solo rsync o un account solo git).

Potresti non vedere la shell pstreeperché potrebbe essere già sparita. Molte shell hanno un'ottimizzazione in cui se rilevano che stanno per eseguire "eseguire questo comando esterno, attendere il completamento e uscire con lo stato del comando", la shell esegue invece " execvedi questo comando esterno". Questo è ciò che sta accadendo nel tuo primo esempio. Contrasta i tre comandi seguenti:

ssh otherhost pstree -a -p
ssh otherhost 'pstree -a -p'
ssh otherhost 'pstree -a -p; true'

I primi due sono identici: il client invia esattamente gli stessi dati al server. Il terzo invia un comando shell che sconfigge l'ottimizzazione exec della shell.


2
ah! non posso credere che mi abbia battuto a rispondere alla mia domanda. L'ho capito a metà strada nel postare la domanda e ho pensato che avrei dovuto semplicemente chiedere e rispondere da solo.
solo il

10

Penso di averlo capito:

$ ssh otherhost pstree -a -p -s '$$'
init,1         
  `-sshd,3736
      `-sshd,11998
          `-sshd,12000
              `-pstree,12001 -a -p -s 12001

Gli argomenti pstreesono: mostrare gli argomenti della riga di comando, mostrare i pid e mostrare solo i processi parent del pid dato. La '$$'è una variabile speciale guscio che bash sostituirà con il proprio pid quando bash valuta gli argomenti della riga di comando. Viene citato una volta per impedire che venga interpretato dalla mia shell locale. Ma non è doppiamente citato o sfuggito per permettergli di essere interpretato dalla shell remota.

Come possiamo vedere, viene sostituito con 12001questo è il pid della shell. Possiamo anche vedere dall'output: pstree,12001che il processo con un pid di 12001 è pstree stesso. Quindi pstreeè il guscio?

Quello che raccolgo sta succedendo è che bashviene invocato e sta analizzando gli argomenti della riga di comando, ma poi invoca execper sostituirsi con il comando in esecuzione.

Sembra che lo faccia solo nel caso di un singolo comando remoto:

$ ssh otherhost pstree -a -p -s '$$' \; echo hi
init,1         
  `-sshd,3736
      `-sshd,17687
          `-sshd,17690
              `-bash,17691 -c pstree -a -p -s $$ ; echo hi
                  `-pstree,17692 -a -p -s 17691
hi

In questo caso, sto richiedendo l'esecuzione di due comandi: pstreeseguito da echo. E possiamo vedere qui che bashin effetti appare nell'albero del processo come genitore di pstree.


Sì ! + 1. È un esempio di ciò che Gilles ha posto più formalmente per primo e esemplificato per secondo. Forse dargli credito per la sua prima risposta è in ordine?
Cbhihe,

0

A supporto di ciò che hanno detto le altre risposte, ho cercato il codice che invoca i comandi sul telecomando, https://github.com/openssh/openssh-portable/blob/4f29309c4cb19bcb1774931db84cacc414f17d29/session.c#L1660 ...

1660    /*
1661     * Execute the command using the user's shell.  This uses the -c
1662     * option to execute the command.
1663     */
1664    argv[0] = (char *) shell0;
1665    argv[1] = "-c";
1666    argv[2] = (char *) command;
1667    argv[3] = NULL;
1668    execve(shell, argv, env);
1669    perror(shell);
1670    exit(1);

... che, come puoi vedere, invoca incondizionatamente shellcon il primo argomento -ce il secondo argomento command. In precedenza, la shellvariabile era impostata sulla shell di accesso dell'utente come registrato in /etc/passwd. commandè un argomento per questa funzione, e alla fine è impostato su una stringa letta alla lettera dal filo (vedi session_exec_reqnello stesso file ). Quindi, il server non interpreta affatto il comando, ma una shell viene sempre invocata sul telecomando.

Tuttavia, la parte rilevante della specifica protocollo SSH non non sembra richiedere questo comportamento; dice solo

 byte      SSH_MSG_CHANNEL_REQUEST
 uint32    recipient channel
 string    "exec"
 boolean   want reply
 string    command

Questo messaggio richiederà al server di avviare l'esecuzione del comando dato. La stringa 'command' può contenere un percorso. Devono essere prese normali precauzioni per impedire l'esecuzione di comandi non autorizzati.

Questo probabilmente perché non tutti i sistemi operativi hanno il concetto di shell da riga di comando. Ad esempio, non sarebbe stato folle per un server ssh di MacOS classico alimentare invece le stringhe di comando "exec" all'interprete AppleScript .

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.