GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Ist es möglich, `find -exec Sh -c` sicher zu verwenden?

Ich versuche, find zu verwenden zu echo 0 in einige Dateien, aber anscheinend funktioniert das nur mit sh -c :

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

Aber mit sh -c mit find -exec macht mich sehr unruhig, weil ich Zitierprobleme vermute. Ich habe ein wenig daran herumgefummelt und anscheinend war mein Verdacht berechtigt:

  • Mein Testaufbau:

    [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
    
  • Verwenden von find -exec ohne sh -c scheint ohne Probleme zu funktionieren – hier kein Zitieren nötig:

    [email protected] ~ % find findtest -type f -exec cat {} ;
    one
    two
    three
    
  • Aber wenn ich sh -c verwende {} scheint eine Art Zitieren zu erfordern:

    [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
    
  • Doppelte Anführungszeichen funktionieren, solange kein Dateiname doppelte Anführungszeichen enthält:

    [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
    
  • Einfache Anführungszeichen funktionieren, solange kein Dateiname einfache Anführungszeichen enthält:

    [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
    

Ich habe keine Lösung gefunden, die in allen Fällen funktioniert. Übersehe ich etwas oder verwende sh -c in find -exec von Natur aus unsicher?

Akzeptierte Antwort:

Betten Sie niemals {} ein im Shell-Code! Dadurch entsteht eine Command-Injection-Schwachstelle. Beachten Sie das für cat "{}" , es geht nicht nur um den " Zeichen, , ` , $ sind ebenfalls ein Problem (man denke zum Beispiel an eine Datei namens ./$(reboot)/accept_ra )¹.

Hier möchten Sie die Dateinamen als separate Argumente an sh übergeben (nicht im Code -Argument) und sh Inline-Skript (der code Argument), um mit Positionsparametern darauf zu verweisen:

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

Oder um zu vermeiden, dass ein sh ausgeführt wird pro Datei:

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

Dasselbe gilt für xargs -I{} oder zsh ‘s zargs -I{} . Schreiben Sie nicht:

Verwandte:Linux – Linux-Äquivalent zu Macs „Shake to Find Cursor“?

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

Das wäre eine Command Injection Schwachstelle, genauso wie bei find oben, aber:

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

Das hat auch den Vorteil, dass ein einziges sh nicht ausgeführt wird pro Datei und den Fehler bei list.txt enthält keine Datei.

Mit zsh ‘s zargs , möchten Sie wahrscheinlich eine Funktion verwenden, anstatt sh -c aufzurufen :

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

Beachten Sie, dass in allen obigen Beispielen das zweite sh oben geht in den $0 des Inline-Skripts . Sie sollten dort etwas Relevantes verwenden (wie sh oder find-sh ), nicht Dinge wie _ , - , -- oder die leere Zeichenfolge als Wert in $0 wird für die Fehlermeldungen der Shell verwendet:

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

GNU parallel funktioniert anders. Damit tun Sie nicht sh -c verwenden möchten als parallel führt bereits eine Shell aus und versucht, {} zu ersetzen mit dem angegebenen Argument in der richtigen Syntax für die Shell.

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


Linux
  1. So verwenden Sie autofs zum Mounten von NFS-Freigaben

  2. So verwenden Sie den Tar-Befehl unter Linux

  3. Es ist möglich, eine .dll unter Linux zu verwenden

  4. Ist es möglich, / in einem Dateinamen zu verwenden?

  5. Warum shm_open verwenden?

So verwenden Sie den Linux-diff-Befehl

So verwenden Sie die Jinja2-Vorlage im Ansible Playbook

So verwenden Sie den Truncate-Befehl unter Linux

So verwenden Sie den Befehl lsof unter Linux

Wie verwende ich gzip unter Linux?

So verwenden Sie den Linux-Befehl shred