GNU/Linux >> Tutoriales Linux >  >> Linux

¿Es posible usar `find -exec Sh -c` de forma segura?

Estoy tratando de usar find a echo 0 en algunos archivos, pero aparentemente esto solo funciona con sh -c :

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

Pero usando sh -c con find -exec me hace sentir muy inquieto porque sospecho problemas de cotización. Jugué un poco con él y aparentemente mis sospechas estaban justificadas:

  • Mi configuración de prueba:

    [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 sin sh -c parece funcionar sin problemas; no es necesario citar aquí:

    [email protected] ~ % find findtest -type f -exec cat {} ;
    one
    two
    three
    
  • Pero cuando estoy usando sh -c {} parece requerir algún tipo de cita:

    [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
    
  • Las comillas dobles funcionan siempre que ningún nombre de archivo contenga comillas dobles:

    [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
    
  • Las comillas simples funcionan siempre que ningún nombre de archivo contenga comillas 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
    

No he encontrado una solución que funcione en todos los casos. ¿Hay algo que estoy pasando por alto o estoy usando sh -c? en find -exec intrínsecamente inseguro?

Respuesta aceptada:

Nunca inserte {} en el código de shell! Eso crea una vulnerabilidad de inyección de comandos. Tenga en cuenta que para cat "{}" , no se trata solo del " caracteres, , ` , $ también son un problema (considere, por ejemplo, un archivo llamado ./$(reboot)/accept_ra )¹.

Aquí, le gustaría pasar los nombres de los archivos como argumentos separados a sh (no en el código argumento), y el sh secuencia de comandos en línea (el código argumento) para referirse a ellos usando parámetros posicionales:

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

O, para evitar ejecutar un sh por archivo:

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

Lo mismo se aplica a xargs -I{} o zsh 's zargs -I{} . No escribas:

Relacionado:Linux:¿linux equivalente a "Agitar para encontrar el cursor" de Mac?

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

Lo cual sería una vulnerabilidad de inyección de comando de la misma manera que con find arriba, pero:

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

Lo que también tiene la ventaja de evitar ejecutar un sh por archivo y el error cuando list.txt no contiene ningún archivo.

Con zsh los zargs , probablemente querrá usar una función en lugar de invocar sh -c :

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

Tenga en cuenta que en todos los ejemplos anteriores, el segundo sh anterior entra en el $0 del script en línea . Deberías usar algo relevante allí (como sh o find-sh ), no cosas como _ , - , -- o la cadena vacía, como el valor en $0 se utiliza para los mensajes de error del shell:

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

GNU parallel funciona de manera diferente. Con él, no quiero usar sh -c como parallel ya ejecuta un shell e intenta reemplazar {} con el argumento citado en la sintaxis correcta para el shell.

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


Linux
  1. Cómo usar autofs para montar recursos compartidos NFS

  2. Cómo usar el comando Tar en Linux

  3. ¿Cómo usar chmod para cambiar el permiso del archivo?

  4. Posible usar un .dll en Linux

  5. ¿Por qué usar shm_open?

Cómo usar el comando diff de Linux

Cómo usar la plantilla Jinja2 en Ansible Playbook

Cómo usar el comando Truncar en Linux

Cómo usar el comando lsof en Linux

¿Cómo usar gzip en Linux?

Cómo usar el comando shred de Linux