GNU/Linux >> Linux Esercitazione >  >> Linux

È possibile utilizzare `find -exec Sh -c` in modo sicuro?

Sto cercando di utilizzare find a echo 0 in alcuni file, ma apparentemente funziona solo con sh -c :

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

Ma usando sh -c con find -exec mi fa sentire molto a disagio perché sospetto di citare problemi. Ci ho giocato un po' e a quanto pare i miei sospetti erano giustificati:

  • La mia configurazione di prova:

    [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
    
  • Usando find -exec senza sh -c sembra funzionare senza problemi – non è necessario citare qui:

    [email protected] ~ % find findtest -type f -exec cat {} ;
    one
    two
    three
    
  • Ma quando utilizzo sh -c {} sembra richiedere una sorta di citazione:

    [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
    
  • Le virgolette doppie funzionano fintanto che nessun nome di file contiene virgolette doppie:

    [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
    
  • Le virgolette singole funzionano fintanto che nessun nome di file contiene virgolette singole:

    [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
    

Non ho trovato una soluzione che funzioni in tutti i casi. C'è qualcosa che sto trascurando o sto usando sh -c in find -exec intrinsecamente pericoloso?

Risposta accettata:

Non incorporare mai {} nel codice della shell! Ciò crea una vulnerabilità di iniezione dei comandi. Nota che per cat "{}" , non si tratta solo del " caratteri, , ` , $ sono anche un problema (considera ad esempio un file chiamato ./$(reboot)/accept_ra )¹.

Qui, vorresti passare i nomi dei file come argomenti separati a sh (non nel codice argomento) e il sh script inline (il codice argomento) per farvi riferimento usando parametri posizionali:

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

Oppure, per evitare di eseguire un sh per file:

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

Lo stesso vale per xargs -I{} o zsh 's zargs -I{} . Non scrivere:

Correlati:Linux – Linux equivalente a "Shake to Find Cursor" di Mac?

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

Che sarebbe una vulnerabilità di iniezione di comandi allo stesso modo di find sopra, ma:

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

Che ha anche il vantaggio di evitare di eseguire un sh per file e l'errore quando list.txt non contiene alcun file.

Con zsh 's zargs , probabilmente vorrai usare una funzione invece di invocare sh -c :

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

Nota che in tutti gli esempi sopra il secondo sh sopra va nello script inline $0 . Dovresti usare qualcosa di rilevante lì (come sh o find-sh ), non cose come _ , - , -- o la stringa vuota, come valore in $0 viene utilizzato per i messaggi di errore della shell:

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

GNU parallel funziona in modo diverso. Con esso, non vuoi usare sh -c come parallel esegue già una shell e tenta di sostituire {} con l'argomento citato nella sintassi corretta per la shell.

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


Linux
  1. Come utilizzare autofs per montare condivisioni NFS

  2. Come utilizzare il comando Tar in Linux

  3. Usare _roff per sottolineare le parole?

  4. Come usare chmod per modificare i permessi dei file?

  5. È possibile utilizzare / in un nome file?

Come usare il comando diff di Linux

Come utilizzare il modello Jinja2 in Ansible Playbook

Come usare il comando Tronca in Linux

Come usare il comando lsof in Linux

Come usare gzip in Linux?

Come utilizzare il comando shred Linux