GNU/Linux >> Tutoriales Linux >  >> Linux

¿Qué tan seguro es el idioma `ssh … “$(typeset -f Foo); Foo”`?

Supongamos que alguna función de shell foo se define en la sesión de shell actual. Entonces el comando

typeset -f foo

imprime el código fuente de esta función. Esto significa que, al menos en principio, se puede ejecutar esta función en un host remoto a través de ssh como se muestra a continuación:

ssh <REMOTE-HOST> "$(typeset -f foo); foo"

(Para los propósitos de esta pregunta, suponga que todos los comandos y rutas del sistema de archivos mencionados por foo están disponibles en <REMOTE-HOST> . Además, suponga que bash es el caparazón en ambos extremos.)

Mi instinto es que obtener a ciegas un código fuente generado automáticamente como este sería extremadamente frágil, pero no he podido encontrar un ejemplo de una función foo donde este modismo falla.

Mi pregunta es:¿Qué tan seguro es este modismo? Si no es seguro, ¿alguien puede darme un ejemplo concreto que ilustre cómo falla? (La cuestión de la seguridad incluye lo siguiente:bash garantiza que tales usos de typeset -f son seguros?)

Nota: En este post no busco alternativas; Solo quiero entender las propiedades de este idioma en particular.

EDITAR:aclaró que bash es el caparazón en ambos extremos.

Respuesta aceptada:

No es seguro si el código no se interpreta en la misma configuración regional en la que se generó (o si la configuración regional nombre es el mismo, pero la definición de esa configuración regional difiere entre el host del cliente ssh y el host del servidor).

Particularmente importante es la codificación de caracteres y la pertenencia de caracteres en el blank , alpha y alnum categorías.

Por ejemplo, el α El carácter (letra griega alfa minúscula) en el juego de caracteres BIG5 está codificado como 0xa3 0x5c, siendo 0x5c en ASCII (y todos los conjuntos de caracteres, incluido BIG5).

Así que si tienes un foo función definida en ese juego de caracteres como:

foo() {
  echo α
}

typeset -f lo generará como tal, pero si se interpreta en una configuración regional diferente como C, ese 0xa3 0x5c no se tomaría como α pero como un carácter 0xa3 desconocido seguido de una barra invertida. Eso puede ser explotado como con:

$ env LC_ALL=zh_TW.big5 $'BASH_FUNC_foo%%=() { echo xa3\\;}; echo gotcha; }' bash -c 'typeset -f foo' | bash
gotcha
bash: line 5: syntax error near unexpected token `}'
bash: line 5: `}'

El foo() { echo α;}; echo gotcha; } se convirtió en foo() { echo <0xa3>\; }; echo gotcha; } cuando se interpreta en la configuración regional diferente.

Otros problemas:

El à El carácter en UTF-8 está codificado como 0xc3 0xa0. En iso8859-1 y varios otros iso8859 conjuntos de caracteres, 0xa0 es el carácter de espacio de no separación. En algunos sistemas, ese carácter se incluye en el espacio en blanco. clase de carácter, tan respetada por bash como delimitador de token en su sintaxis.

Relacionado:Linux:¿solo se ejecuta el permiso de archivo?

Solaris es uno de esos sistemas donde U+00A0 se considera un espacio en blanco:

$ env $'BASH_FUNC_foo%%=() { nawk -v x=àBEGIN'{system("echo gotcha")}' 1;}' bash -c 'typeset -f foo; echo foo'  | ssh solaris LC_ALL=en_GB.ISO8859-1 bash
gotcha

Vea cómo:

nawk -v x=àBEGIN... 1

fue interpretado como:

nawk -v x=<0xc3> 'BEGIN{system("...")}' 1

Tenga en cuenta que si la función se definió en una configuración regional donde 0xa0 no estaba en blanco o donde 0xa3 0x5c era alfa, typeset -f seguirá generando el mismo resultado incluso si se llama en una configuración regional donde está en blanco (produciendo un resultado diferente cuando se interpreta)

$ LC_ALL=zh_TW.big5 bash -c $'f() { echo xa3x5c$(uname); }; export LC_ALL=C; typeset -f f | bash'
bash: line 3: syntax error near unexpected token `('
bash: line 3: `    echo �$(uname)'

Más generalmente, la salida de typeset , alias , export -p , set , locale todos son significados para ser adecuado para volver a ingresar a un shell, pero además de esos problemas de configuración regional, se sabe que varias implementaciones tienen varios problemas, y no me sorprendería si todavía hubiera muchos más.

Entonces, sí, estoy de acuerdo en que tiene razón al considerarlo peligroso, y es una buena idea usarlos solo en un contexto en el que sepa de dónde provienen los datos que se generan. Por ejemplo, en el caso de typeset -f foo , solo úsalo en un foo función que ha definido (y evite usar caracteres que no sean ASCII).


Linux
  1. ¿El propósito de .bashrc y cómo funciona?

  2. ¿Cómo puedo recordar el argumento del comando bash anterior?

  3. Cómo agregar un ícono al indicador de bash

  4. ¿Cómo obtengo el directorio absoluto de un archivo en bash?

  5. ¿Cómo configurar el color del símbolo del sistema en Bash?

Cómo usar el comando Bash let {con ejemplos}

Cómo usar el comando de lectura Bash

¿Cómo sé el nombre del archivo de script en un script Bash?

¿Cómo leer la penúltima línea en un archivo usando Bash?

Cómo obtener el estado de salida de un bucle en bash

¿Cuál es el equivalente de cat -n de Bash en PowerShell?