GNU/Linux >> Tutoriels Linux >  >> Linux

Est-il possible d'utiliser `find -exec Sh -c` en toute sécurité ?

J'essaie d'utiliser find à echo 0 dans certains fichiers, mais apparemment cela ne fonctionne qu'avec sh -c :

find /proc/sys/net/ipv6 -name accept_ra -exec sh -c 'echo 0 > {}' ;

Mais en utilisant sh -c avec find -exec me met très mal à l'aise parce que je soupçonne des problèmes de citation. J'ai un peu bidouillé et apparemment mes soupçons étaient justifiés :

  • Ma configuration de test :

    [email protected] ~ % cd findtest 
    [email protected] ~/findtest % echo one > file with spaces
    [email protected] ~/findtest % echo two > file with 'single quotes'
    [email protected] ~/findtest % echo three > file with "double quotes"
    [email protected] ~/findtest % ll
    insgesamt 12K
    -rw-rw-r-- 1 martin martin 6 Sep 17 12:01 file with "double quotes"
    -rw-rw-r-- 1 martin martin 4 Sep 17 12:01 file with 'single quotes'
    -rw-rw-r-- 1 martin martin 4 Sep 17 12:01 file with spaces
    
  • Utilisation de find -exec sans sh -c semble fonctionner sans problème - aucune citation nécessaire ici :

    [email protected] ~ % find findtest -type f -exec cat {} ;
    one
    two
    three
    
  • Mais quand j'utilise sh -c {} semble nécessiter une sorte de citation :

    [email protected] ~ % LANG=C find findtest -type f -exec sh -c 'cat {}' ;
    cat: findtest/file: No such file or directory
    cat: with: No such file or directory
    cat: spaces: No such file or directory
    cat: findtest/file: No such file or directory
    cat: with: No such file or directory
    cat: single quotes: No such file or directory
    cat: findtest/file: No such file or directory
    cat: with: No such file or directory
    cat: double quotes: No such file or directory
    
  • Les guillemets doubles fonctionnent tant qu'aucun nom de fichier ne contient de guillemets doubles :

    [email protected] ~ % LANG=C find findtest -type f -exec sh -c 'cat "{}"' ;
    one
    two
    cat: findtest/file with double: No such file or directory
    cat: quotes: No such file or directory
    
  • Les guillemets simples fonctionnent tant qu'aucun nom de fichier ne contient de guillemets simples :

    [email protected] ~ % LANG=C find findtest -type f -exec sh -c "cat '{}'" ;
    one
    cat: findtest/file with single: No such file or directory
    cat: quotes: No such file or directory
    three
    

Je n'ai pas trouvé de solution qui fonctionne dans tous les cas. Y a-t-il quelque chose que je néglige ou utilise sh -c dans find -exec intrinsèquement dangereux ?

Réponse acceptée :

Ne jamais intégrer {} dans le code shell ! Cela crée une vulnérabilité d'injection de commande. Notez que pour cat "{}" , il ne s'agit pas seulement de " caractères, , ` , $ sont également un problème (considérez par exemple un fichier appelé ./$(reboot)/accept_ra )¹.

Ici, vous voudriez passer les noms de fichiers en tant qu'arguments séparés à sh (pas dans le code argument), et le sh script en ligne (le code argument) pour y faire référence à l'aide de paramètres positionnels :

find . -name accept_ra -exec sh -c 'echo 0 > "$1"' sh {} ;

Ou, pour éviter d'exécuter un sh par fichier :

find . -name accept_ra -exec sh -c 'for file do
  echo 0 > "$file"; done' sh {} +

Il en va de même pour xargs -I{} ou zsh 's zargs -I{} . N'écrivez pas :

En relation:Linux - Linux équivalent au "Shake to Find Cursor" de Mac?

<list.txt xargs -I{} sh -c 'cmd > {}'

Ce qui serait une vulnérabilité d'injection de commande de la même manière qu'avec find ci-dessus, mais :

<list.txt xargs sh -c 'for file do cmd > "$file"; done' sh

Ce qui a aussi l'avantage d'éviter d'exécuter un sh par fichier et l'erreur lorsque list.txt ne contient aucun fichier.

Avec zsh zargs , vous voudrez probablement utiliser une fonction plutôt que d'invoquer sh -c :

do-it() cmd > $1
zargs ./*.txt -- do-it

Notez que dans tous les exemples ci-dessus le second sh ci-dessus va dans le $0 du script en ligne . Vous devriez utiliser quelque chose de pertinent ici (comme sh ou find-sh ), pas des choses comme _ , - , -- ou la chaîne vide, comme valeur dans $0 est utilisé pour les messages d'erreur du shell :

$ find . -name accept_ra -exec sh -c 'echo 0 > "$1"' inline-sh {} ;
inline-sh: ./accept_ra: Permission denied

GNU parallel fonctionne différemment. Avec elle, vous ne faites pas voulez utiliser sh -c comme parallel exécute déjà un shell et essaie de remplacer {} avec l'argument cité dans la bonne syntaxe pour le shell.

<list.txt PARALLEL_SHELL=sh parallel 'cmd > {}'


Linux
  1. Comment utiliser autofs pour monter des partages NFS

  2. Comment utiliser la commande Tar sous Linux

  3. Comment utiliser chmod pour modifier l'autorisation d'un fichier ?

  4. Possible d'utiliser un .dll sous Linux

  5. Pourquoi utiliser shm_open ?

Comment utiliser la commande Linux diff

Comment utiliser le modèle Jinja2 dans Ansible Playbook

Comment utiliser la commande Truncate sous Linux

Comment utiliser la commande lsof sous Linux

Comment utiliser gzip sous Linux ?

Comment utiliser la commande shred Linux