Dans un langage de programmation, j'exécute une simple commande shell
cd var; echo > create_a_file_here
avec var étant une variable qui contient une chaîne (espérons-le) d'un répertoire à l'endroit où je veux créer le fichier "create_a_file_here". Maintenant, si quelqu'un voit cette ligne de code, il est possible de l'exploiter en affectant par exemple:
var = "; rm -rf /"
Les choses peuvent devenir assez laides. Une façon d'éviter le cas ci-dessus serait peut-être de rechercher dans la chaîne dans var des caractères spéciaux comme ';' avant d'exécuter la commande shell, mais je doute que cela couvre tous les exploits possibles.
Est-ce que quelqu'un connaît un bon moyen de s'assurer que "cd var" ne change qu'un répertoire et rien d'autre?
shell-script
shell
ES___
la source
la source
var
comme argument. Par exemple , appelersh
avec des arguments-c
,'cd "$1"; echo > create_a_file_here'
,'sh'
,var
travaux et n'a pas besoin de changements àvar
. L''sh'
argument est transmis sous la forme$0
.sh
ou créez-vous votre propre langage de programmation avec une syntaxe similaire mais qui se développevar
au lieu de vous obliger à écrirecd "$var"
? Ou est-cebash
avecshopt -s cdable_vars
? Oh, je pense que vous voulez dire qu'un autre programme bifurque un shell pour exécuter ces commandes. Alors citez justevar
, mais assurez-vous qu'il n'inclut pas de caractère de citation lui-même ...s='"'; echo "$s"
impressions"
.var=untrusted string
dans le programme parent, toutvar
comme une variable d'environnement qui est déjà définie lors de l'appelsh
. Ensuite, il vous suffit de le citer chaque fois que vous le développez, ce qui est possible de manière fiable. Ah, je vois que cette idée fait déjà partie de la réponse de Stéphane>. <Réponses:
Si je comprends bien,
var
c'est une variable dans votre langage de programmation.Et dans votre langage de programmation, vous demandez à un shell d'interpréter une chaîne qui est la concaténation de
"cd "
, le contenu de cette variable et"; echo > create_a_file_here"
.Si alors, oui, si le contenu de
var
n'est pas étroitement contrôlé, c'est une vulnérabilité d'injection de commande.Vous pouvez essayer de citer correctement le contenu de la variable¹ dans la syntaxe du shell afin qu'il soit garanti d'être passé comme un seul argument au
cd
builtin.Une autre approche consisterait à transmettre le contenu de cette variable d'une autre manière. Un moyen évident serait de passer cela dans une variable d'environnement. Par exemple, en C:
Cette fois, le code que vous demandez au shell d'interpréter est fixe, nous devons toujours l'écrire correctement dans la syntaxe du shell (ici supposé être un shell compatible POSIX):
-P
pourcd
faire simplechdir()
--
marquer la fin des options pour éviter les problèmes devar
démarrage-
(ou+
dans certains shells)CDPATH
la chaîne vide au cas où elle se trouverait dans l'environnementecho
commande qu'en cas decd
succès.Il y a (au moins) un problème restant: s'il l'
var
est-
, il ne se place pas dans le répertoire appelé-
mais dans le répertoire précédent (tel que stocké dans$OLDPWD
) et ilOLDPWD=- CDPATH= cd -P -- "$DIR"
n'est pas garanti de le contourner. Vous auriez donc besoin de quelque chose comme:¹ Notez que faire un
n'est pas la voie à suivre, vous ne feriez que déplacer le problème.system(concat("cd \"", var, "\"; echo..."));
Par exemple, un
var = "$(rm -rf /)"
serait toujours un problème.Le seul moyen fiable de citer du texte pour des shells de type Bourne est d'utiliser des guillemets simples et de prendre également en charge les guillemets simples qui peuvent apparaître dans la chaîne. Par exemple, tournez a
char *var = "ab'cd"
àchar *escaped_var = "'ab'\\''cd'"
. C'est, remplacer tout'
à'\''
et envelopper le tout à l' intérieur'...'
.Cela suppose encore que cette chaîne entre guillemets n'est pas utilisé dans les apostrophes inverses, et vous auriez encore besoin de la
--
,-P
,&&
,CDPATH=
...la source
Solution simple: n'appelez pas le shell depuis votre programme. Du tout.
Votre exemple ici est trivial, changer le répertoire et créer des fichiers devrait être facile dans n'importe quel langage de programmation. Mais même si vous avez besoin d'exécuter une commande externe, il n'est généralement pas nécessaire de le faire via le shell.
Ainsi, par exemple en Python, au lieu d'exécuter
os.system("somecmd " + somearg)
, utilisezsubprocess.run(["somecmd", somearg])
. En C, au lieu desystem()
, utilisezfork()
etexec()
(ou trouvez une bibliothèque qui le fait).Si vous devez utiliser le shell, citez les arguments de la ligne de commande ou passez-les dans l'environnement, comme dans la réponse de Stéphane . De plus, si vous vous inquiétez des caractères spéciaux, la bonne solution consiste à ne pas filtrer (liste noire) les caractères potentiellement dangereux, mais à ne garder que les caractères connus pour être sûrs (liste blanche).
N'autorisez que les personnages dont vous connaissez les fonctions, de cette façon il y a moins de risque de manquer quelque chose. Le résultat final pourrait être que vous décidez seulement d'autoriser
[a-zA-Z0-9_]
, mais cela pourrait suffire pour faire le travail. Vous pouvez également vérifier que votre environnement local et votre jeu d'outils n'incluent pas de lettres accentuées commeä
etö
dans cela. Ils ne sont probablement pas considérés comme spéciaux par aucun shell, mais encore une fois, il vaut mieux être sûr qu'ils passent ou non.la source
[a-zA-Z0-9]
n'inclut pas des choses commeà
dont le codage pourrait également être mal interprété par certains shells (commebash
) dans certains paramètres régionaux.Dans un langage de programmation, il devrait y avoir de meilleures façons de faire que d'exécuter des commandes shell. Par exemple, le remplacement
cd var
par l'équivalent de votre langage de programmationchdir (var);
devrait garantir que toute supercherie avec la valeur devar
se traduit uniquement par une erreur "Répertoire introuvable" plutôt que par des actions involontaires et éventuellement malveillantes.Vous pouvez également utiliser des chemins absolus plutôt que de changer de répertoire. Concaténez simplement le nom du répertoire, la barre oblique et le nom de fichier que vous souhaitez utiliser.
En C, je pourrais faire quelque chose comme:
Votre langage de programmation peut sûrement faire quelque chose de similaire?
la source