GNU/Linux >> Tutoriels Linux >  >> Linux

Quelle est la sécurité de l'idiome `ssh … "$(typeset -f Foo); Foo" ?

Supposons qu'une fonction shell foo est défini dans la session shell en cours. Puis la commande

typeset -f foo

affiche le code source de cette fonction. Cela signifie que, au moins en principe, on peut exécuter cette fonction sur un hôte distant via ssh comme indiqué ci-dessous :

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

(Pour les besoins de cette question, supposons que toutes les commandes et les chemins de système de fichiers mentionnés par foo sont disponibles dans <REMOTE-HOST> . Supposons également que bash est la coque aux deux extrémités.)

Mon instinct est qu'il serait extrêmement fragile de trouver aveuglément du code source généré automatiquement comme celui-ci, mais je n'ai pas été en mesure de trouver un exemple de fonction foo où cet idiome échoue.

Ma question est :à quel point cet idiome est-il sûr ? Si ce n'est pas sûr, quelqu'un peut-il me donner un exemple concret qui illustre comment cela échoue ? (La question de la sécurité comprend les éléments suivants :est-ce que bash garantir que de telles utilisations de typeset -f sont en sécurité ?)

NB : Dans ce post, je ne cherche pas d'alternatives; Je veux juste comprendre les propriétés de cet idiome particulier.

EDIT :a précisé que bash est la coquille aux deux extrémités.

Réponse acceptée :

Ce n'est pas sûr si le code n'est pas interprété dans la même locale que celle où il a été généré (ou si la locale nom est le même mais la définition de cette locale diffère entre l'hôte du client ssh et l'hôte du serveur).

L'encodage des caractères et l'appartenance des caractères dans le blank sont particulièrement importants. , alpha et alnum catégories.

Par exemple, le α caractère (lettre grecque minuscule alpha) dans le jeu de caractères BIG5 est codé comme 0xa3 0x5c, 0x5c étant en ASCII (et tous les jeux de caractères y compris BIG5).

Donc, si vous avez un foo fonction définie dans ce jeu de caractères comme :

foo() {
  echo α
}

typeset -f le sortira comme tel, mais s'il est interprété dans une locale différente comme C, ce 0xa3 0x5c ne sera pas considéré comme un α mais comme un caractère 0xa3 inconnu suivi d'une barre oblique inverse. Cela peut être exploité comme avec :

$ 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: `}'

Le foo() { echo α;}; echo gotcha; } est devenu foo() { echo <0xa3>\; }; echo gotcha; } lorsqu'il est interprété dans les différents paramètres régionaux.

Autres problèmes :

Le à Le caractère en UTF-8 est codé comme 0xc3 0xa0. En iso8859-1 et plusieurs autres iso8859 jeux de caractères, 0xa0 est le caractère espace insécable. Sur certains systèmes, ce caractère est inclus dans le vide classe de caractères, donc honorée par bash en tant que délimiteur de jeton dans sa syntaxe.

Connexes :Linux - L'autorisation de fichier s'exécute uniquement ?

Solaris est l'un de ces systèmes où U+00A0 est considéré comme un blanc :

$ 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

Découvrez comment :

nawk -v x=àBEGIN... 1

a été interprété comme :

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

Notez que si la fonction a été définie dans une locale où 0xa0 n'était pas un blanc ou où 0xa3 0x5c était alpha, typeset -f le produira toujours de la même manière même s'il est appelé dans une locale où il s'agit d'un blanc (produisant une sortie différente lorsqu'il est interprété)

$ 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)'

Plus généralement, la sortie de typeset , alias , export -p , set , locale sont tous signifiés pour convenir à la réintroduction dans un shell, mais en plus de ces problèmes de paramètres régionaux, diverses implémentations sont connues pour avoir plusieurs problèmes, et je ne serais pas surpris s'il y en avait encore beaucoup plus.

Donc, oui, je suis d'accord que vous avez raison de considérer cela comme dangereux, et c'est une bonne idée de ne les utiliser que dans un contexte où vous savez d'où proviennent les données qui sont sorties. Par exemple, dans le cas de typeset -f foo , ne l'utilisez que sur un foo fonction que vous ont défini (et évitez d'y utiliser des caractères non ASCII).


Linux
  1. Le but de .bashrc et comment ça marche ?

  2. Comment arrêter le script Loop Bash dans le terminal ?

  3. Est-ce que Rsync ~/foo Target/foo est identique à Rsync ~/foo/ Target/foo/?

  4. Comment obtenir le Tty dans lequel Bash est en cours d'exécution ?

  5. Comment le shell BASH charge ses fichiers de configuration sous Linux

Comment utiliser la commande Bash let {avec exemples}

Comment utiliser la commande de lecture Bash

Comment obtenir le statut de sortie d'une boucle dans bash

Comment définir la couleur de l'invite de commande dans Bash ?

Comment trouver l'index d'un mot dans une chaîne en bash ?

Quel est l'équivalent du cat -n de Bash dans PowerShell ?