GNU/Linux >> Linux Esercitazione >  >> Linux

Quanto è sicuro l'idioma `ssh … “$(typeset -f Foo); Foo"`?

Supponiamo che qualche funzione di shell foo è definito nella sessione della shell corrente. Quindi il comando

typeset -f foo

stampa il codice sorgente di questa funzione. Ciò significa che, almeno in linea di principio, è possibile eseguire questa funzione su un host remoto tramite ssh come mostrato di seguito:

ssh <REMOTE-HOST> "$(typeset -f foo); foo"

(Ai fini di questa domanda, supponiamo che tutti i comandi e i percorsi del file system menzionati da foo sono disponibili in <REMOTE-HOST> . Inoltre, supponiamo che bash è il guscio su entrambe le estremità.)

Il mio istinto è che reperire ciecamente del codice sorgente generato automaticamente come questo sarebbe estremamente fragile, ma non sono stato in grado di trovare un esempio di una funzione foo dove questo idioma non riesce.

La mia domanda è:quanto è sicuro questo idioma? Se non è sicuro, qualcuno può farmi un esempio concreto che illustri come fallisce? (La questione della sicurezza include quanto segue:fa bash garantire che tali usi di typeset -f sono al sicuro?)

NB: In questo post non cerco alternative; Voglio solo capire le proprietà di questo particolare idioma.

EDIT:chiarito che bash è il guscio su entrambe le estremità.

Risposta accettata:

Non è sicuro se il codice non viene interpretato nella stessa lingua di quella in cui è stato generato (o se la locale nome è la stessa, ma la definizione di tale locale è diversa tra l'host client ssh e l'host server).

Particolarmente importante è la codifica dei caratteri e l'appartenenza dei caratteri al blank , alpha e alnum categorie.

Ad esempio, il α il carattere (lettera greca minuscola alfa) nel set di caratteri BIG5 è codificato come 0xa3 0x5c, 0x5c è in ASCII (e tutti i set di caratteri incluso BIG5).

Quindi, se hai un foo funzione definita in quel set di caratteri come:

foo() {
  echo α
}

typeset -f lo emetterà come tale, ma se interpretato in una locale diversa come C, quel 0xa3 0x5c non verrebbe preso come α ma come un carattere 0xa3 sconosciuto seguito da una barra rovesciata. Può essere sfruttato come con:

$ env LC_ALL=zh_TW.big5 $'BASH_FUNC_foo%%=() { echo xa3\\;}; echo gotcha; }' bash -c 'typeset -f foo' | bash
gotcha
bash: line 5: syntax error near unexpected token `}'
bash: line 5: `}'

Il foo() { echo α;}; echo gotcha; } è diventato foo() { echo <0xa3>\; }; echo gotcha; } se interpretato nella diversa locale.

Altri problemi:

Il à il carattere in UTF-8 è codificato come 0xc3 0xa0. In iso8859-1 e molti altri iso8859 set di caratteri, 0xa0 è il carattere di spazio unificatore. Su alcuni sistemi, quel carattere è incluso nel vuoto classe di caratteri, così onorata da bash come delimitatore di token nella sua sintassi.

Correlati:Linux – Solo per l'esecuzione dell'autorizzazione file?

Solaris è uno di questi sistemi in cui U+00A0 è considerato uno spazio vuoto:

$ env $'BASH_FUNC_foo%%=() { nawk -v x=àBEGIN'{system("echo gotcha")}' 1;}' bash -c 'typeset -f foo; echo foo'  | ssh solaris LC_ALL=en_GB.ISO8859-1 bash
gotcha

Guarda come:

nawk -v x=àBEGIN... 1

è stato interpretato come:

nawk -v x=<0xc3> 'BEGIN{system("...")}' 1

Nota che se la funzione è stata definita in una locale in cui 0xa0 non era uno spazio vuoto o dove 0xa3 0x5c era alfa, typeset -f lo restituirà lo stesso anche se chiamato in una locale in cui è uno spazio vuoto (producendo un output diverso quando interpretato)

$ LC_ALL=zh_TW.big5 bash -c $'f() { echo xa3x5c$(uname); }; export LC_ALL=C; typeset -f f | bash'
bash: line 3: syntax error near unexpected token `('
bash: line 3: `    echo �$(uname)'

Più in generale, l'output di typeset , alias , export -p , set , locale sono tutti intesi per essere adatto per il reinserimento in una shell, ma oltre a questi problemi di localizzazione, è noto che varie implementazioni hanno diversi problemi e non sarei sorpreso se ce ne fossero ancora molti di più.

Quindi, sì, sono d'accordo che hai ragione a considerarlo pericoloso ed è una buona idea usarli solo nel contesto in cui sai da dove provengono i dati che vengono generati. Ad esempio, nel caso di typeset -f foo , usalo solo su un foo funzione che tu hanno definito (ed evita di utilizzare caratteri non ASCII al suo interno).


Linux
  1. Rsync ~/foo Target/foo è uguale a Rsync ~/foo/ Target/foo/?

  2. Come ottenere il Tty in cui è in esecuzione Bash?

  3. Come faccio a conoscere il nome del file di script in uno script Bash?

  4. Come posso richiamare l'argomento del precedente comando bash?

  5. Come aggiungere un'icona al prompt di bash

Come utilizzare il comando Bash let {con esempi}

Come utilizzare il comando di lettura Bash

Come ottenere lo stato di uscita un ciclo in bash

Come trovare l'indice di una parola in una stringa in bash?

Come modificare la risoluzione di Bash per una VM Debian?

Come cambiare rapidamente la prima parola in un comando Bash?