Voici la commande que j'ai utilisée pour vérifier le shell Shellshock dans mon shell bash:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Quelqu'un peut-il s'il vous plaît expliquer la commande en détail?
Voici la commande que j'ai utilisée pour vérifier le shell Shellshock dans mon shell bash:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Quelqu'un peut-il s'il vous plaît expliquer la commande en détail?
Réponses:
Cette réponse est un dérivé d'un article original du magazine Fedora par Matthew Miller, sous licence Creative Commons Attribution-Share Alike 4.0 .
Laissez-moi expliquer:
env x='() { :;}; echo OOPS' bash -c :
Ceci imprimera “OOPS” sur un système vulnérable, mais se fermera silencieusement si bash a été corrigé.
env x='() { :;}; echo OOPS' bash -c "echo this is a test"
Ceci imprimera “OOPS” sur un système vulnérable, mais imprimera “this is a test”
si bash a été corrigé.
Et vous avez probablement entendu dire que cela a quelque chose à voir avec les variables d'environnement. Mais pourquoi le code des variables d’environnement est-il exécuté? Eh bien, ce n'est pas censé l'être - mais, à cause d'une fonctionnalité que je serais tenté d'appeler un peu trop intelligente pour son propre bien, il y a de la place pour un défaut. Bash est ce que vous voyez comme une invite de terminal, mais c’est aussi un langage de script qui permet de définir des fonctions. Vous faites ça comme ça:
$ Ubuntu() { echo "Ubuntu is awesome."; }
et alors vous avez une nouvelle commande. Gardez à l'esprit que l' echo
ici n'est pas encore exécuté; c'est enregistré comme ce qui se passera lorsque nous exécuterons notre nouvelle commande. Ce sera important dans une minute!
$ Ubuntu
Ubuntu is awesome.
Utile! Mais, disons, pour une raison quelconque, nous devons exécuter une nouvelle instance de bash, en tant que sous-processus, et vouloir exécuter ma nouvelle commande impressionnante dans ce contexte. L'instruction bash -c somecommand
fait exactement ceci: exécute la commande donnée dans un nouveau shell:
$ bash -c Ubuntu
bash: Ubuntu: command not found
Ooh. Triste. L'enfant n'a pas hérité de la définition de fonction. Mais cela fait partie de l’environnement - une collection de paires clé-valeur qui ont été exportées à partir du shell. (Ceci est un concept complet. Si vous ne le connaissez pas encore, faites-moi confiance pour le moment.) Et il s'avère que bash peut également exporter des fonctions. Alors:
$ export -f Ubuntu
$ bash -c Ubuntu
Ubuntu is awesome.
Ce qui est bien beau - sauf que le mécanisme par lequel ceci est accompli est en quelque sorte louche . Fondamentalement, comme il n’existe pas de magie Linux / Unix pour exécuter des fonctions dans des variables d’environnement, la fonction d’exportation crée en réalité une variable d’environnement ordinaire contenant la définition de la fonction. Ensuite, lorsque le second shell lit l'environnement «entrant» et rencontre une variable dont le contenu ressemble à une fonction, il l'évalue.
En théorie, cela est parfaitement sûr car, rappelez-vous, définir une fonction ne l' exécute pas . Sauf que - et c'est pourquoi nous sommes ici - il y avait un bogue dans le code où l'évaluation ne s'est pas arrêtée lorsque la fin de la définition de la fonction a été atteinte. Cela ne fait que commencer.
Cela ne se produirait jamais lorsque la fonction stockée dans une variable d’environnement est légitimement créée, avec export -f
. Mais pourquoi être légitime? Un attaquant peut créer n'importe quelle ancienne variable d'environnement, et si cela ressemble à une fonction, les nouveaux shell bash penseront que c'est le cas!
Donc, dans notre premier exemple:
env x='() { :;}; echo OOPS' bash -c "echo this is a test"
La env
commande exécute une commande avec un jeu de variables donné. Dans ce cas, nous définissons x
quelque chose qui ressemble à une fonction. La fonction est juste une simple :
, qui est en fait une simple commande qui est définie comme ne rien faire. Mais ensuite, après le semi-colon
signe de la fin de la définition de la fonction, il y a une echo
commande. Ce n'est pas censé être là, mais rien ne nous empêche de le faire.
Ensuite, la commande donnée pour fonctionner avec ce nouvel environnement est un nouveau shell bash, toujours avec une commande “ echo this is a test
” ou “ne rien faire :
”, après quoi il se fermera de manière totalement inoffensive.
Mais - oups! Lorsque ce nouveau shell démarre et lit l'environnement, il passe à la x
variable et, puisqu'il ressemble à une fonction, il l'évalue. La définition de la fonction est chargée de manière inoffensive - puis notre charge utile malveillante est également déclenchée. Donc, si vous exécutez ce qui précède sur un système vulnérable, vous serez de “OOPS”
nouveau imprimé. Ou bien, un attaquant pourrait faire bien pire que simplement imprimer des choses.
env
n'est pas nécessaire. Vous pouvez obtenir le même résultat (réussite / échec selon que Bash a été mis à jour) en utilisant la commande sans elle: x='() { :;}; echo OOPS' bash -c "echo this is a test"
. En effet, le fait de faire précéder une commande avec une affectation de variable transmet cette variable et sa valeur dans l' bash -c "..."
environnement de la commande ( dans ce cas).
env
nécessaire ou non est déterminé par le shell à partir duquel on effectue le test, pas par le shell en cours de test. (C’est peut-être la même chose. Même dans ce cas, nous testons la façon dont bash traite son propre environnement.) Les shells de type Bourne acceptent la NAME=value command
syntaxe; Coquilles de type C (par exemple csh
, tcsh
) ne le font pas. Le test est donc un peu plus portable env
(au prix de créer parfois une confusion sur son fonctionnement).
Dans sa version non corrigée,bash
il stocke les définitions de fonctions exportées sous forme de variables d’environnement.
Enregistrer une fonction en x
tant que,
$ x() { bar; }
$ export -f x
Et vérifiez sa définition comme,
$ env | grep -A1 x
x=() { bar
}
Donc, on pourrait exploiter cela en définissant ses propres variables d'environnement et les interpréter comme des définitions de fonctions. Par exemple, env x='() { :;}'
serait traité comme
x() { :;
}
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
de man env
,
env
- exécuter un programme dans un environnement modifié.
:
ne rien faire mais quitte avec le statut de sortie 0
. voir plus
Lorsqu'une nouvelle instance de bash non corrigée est lancée en tant que bash -c "echo this is a test"
, la variable d'environnement construite est traitée comme une fonction et chargée. En conséquence on obtient la sortie
vulnérable c'est un test
Remarque: l'écho en dehors de la définition de la fonction a été exécuté de manière inattendue lors du démarrage de bash. La définition de la fonction est juste une étape pour obtenir l'évaluation et l'exploitation, la définition de la fonction elle-même et la variable d'environnement utilisée sont arbitraires. Le shell examine les variables d'environnement, voit x, ce qui donne l'impression qu'il respecte les contraintes sur la définition d'une fonction, et évalue la ligne en exécutant involontairement aussi l'écho (qui peut être n'importe quelle commande, malveillante ou non). . Voir aussi cette
env test='() { echo "anything"; }' bash -c "echo otherthing"
vous verrez à la sortie otherthing
. Cela est corrigé dans le patch. Sentez-vous libre si je ne suis toujours pas clair.
unpatched bash
vous pouvez appeler la fonction telle qu'elle est définie, mais dans un correctif, bash
la définition elle-même n'y figure pas.
echo vulnerable
) n'est pas exécuté. Notez que dans les derniers patchs, la fonction transmise doit avoir un préfixe spécifique ( env 'BASH_FUNC_x()'='() { :;}; echo vulnerable' bash -c "echo this is a test"
). Certains correctifs plus récents peuvent utiliser %%
au lieu du premier ()
.