2010-10-27 22 views
4

A partir d'un programme C, je veux appeler un script shell avec un nom de fichier en tant que paramètre. Les utilisateurs peuvent contrôler le nom de fichier. Le C est quelque chose comme (initialisation/vérification d'erreur omis):Existe-t-il un moyen d'empêcher sh/bash d'effectuer une substitution de commande?

sprintf(buf, "/bin/sh script.sh \"%s\"", filename); 
system(buf); 

Le dispositif cible est en fait un système embarqué donc je ne pas besoin de se soucier des utilisateurs malveillants. Évidemment, ce serait un vecteur d'attaque dans un environnement Web. Cependant, s'il y a un nom de fichier sur le système qui, par exemple, contient des backquotes dans son nom, la commande échouera parce que le shell effectuera une expansion sur le nom. Est-il possible d'empêcher la substitution de commande?

+1

Utilisez des guillemets simples '' 'à la place. Bash ne le remplacera pas. C'est à dire. 'sprintf (buf,"/bin/sh script.sh '% s' ", nom de fichier); Ensuite, tout dépend de ce que fait 'script.sh'. Vous pouvez également spécifier '-r' pour un shell restreint, mais il y a certaines limitations de ce que vous pouvez faire dans un tel shell, voir la section' RESTRICTED SHELL' de la page de manuel bash pour plus de détails. –

Répondre

0

Essayez de déclencher "unalias" dans la fonction système.

0

Depuis vous avez marqué ce que C je vais vous donner une réponse C. Vous aurez besoin d'échapper le nom de fichier - créer une nouvelle chaîne qui sera traitée correctement par le shell, de sorte que des choses comme This is a file name produit This\ is\ a\ file\ name ou bad;rm *;filename devient bad\;rm\ \*\;filename. Ensuite, vous pouvez passer cela à la coquille.

Une autre façon de contourner ce problème serait d'exécuter le shell directement avec fork et l'une des fonctions exec. Passer des arguments directement aux programmes n'entraîne pas d'expansion ou d'interprétation de la ligne de commande du shell.

0

Comme indiqué ci-dessus, vous ne devriez pas utiliser system mais fork et execv vous-même. Mais pour répondre à la question de savoir comment sécuriser les chaînes pour passer au shell (dans le cas où vous insistez pour utiliser system), vous devez échapper à la chaîne. La façon la plus simple de le faire est de remplacer chaque occurrence de ' (guillemet simple) par '\'' (guillemet simple, barre oblique inverse, guillemet simple, guillemet simple) puis d'ajouter ' (guillemet simple) au début et à la fin de la chaîne. L'autre méthode assez facile (mais généralement moins efficace) consiste à placer une barre oblique inverse avant chaque caractère, mais vous devez toujours faire quelques astuces de guillemets spéciales pour gérer les retours à la ligne, donc je préfère la première méthode.