¿La función de importación de la función de shell bash genera inevitablemente un problema de escalamiento de privilegios?

13

Incluso sin el problema inmediato de ejecución de código de los comandos finales Shellshock , ¿en qué medida la característica de las funciones de importación de bash del entorno genera una vulnerabilidad integral de escalamiento de privilegios?

Para ser claros, hay muchos programas setuid, y algunos de ellos llamarán directa o indirectamente a los scripts, o usarán la llamada system(3) , que en la mayoría de los sistemas Linux pasa por bash . La pregunta es hasta qué punto, asumiendo que los sistemas tienen dichos setuid binarios instalados , esta característica de bash permite la escalada de privilegios locales.

  • Por ejemplo, si llamar a una secuencia de comandos, ¿permite anular las incorporaciones? Si es así, puede dar lugar a una escalada de privilegios en combinación con un ejecutable setuid y la llamada system(3) , anulando, por ejemplo, ls , cd o algo inocuo?
  • ¿Un vector de escalada de este tipo requeriría que se llame un script (en cuyo caso uno podría potencialmente anular ls o cualquier comando utilizado por el script que no utilizó una ruta completa)?
  • ¿Es posible que las funciones importadas se usen en cualquier momento por la ruta de ejecución normal de /bin/sh -c ARGUMENTS incluso cuando el primer argumento no es un script?
  • ¿Podría simplemente dar a una variable de entorno el mismo nombre que el primer argumento para system ?
  • Si es así, ¿significa que cada llamada a system(3) por un ejecutable de setuid, en un sistema donde /bin/sh es bash, es un vector de escalamiento de privilegios?
pregunta Ben 29.09.2014 - 13:07
fuente

4 respuestas

6

Estas pruebas se ejecutan en un sistema no parcheado:

# ls='() { echo NO; }' bash -c 'ls'
NO

el * comodín es obligatorio o Perl reemplazará la llamada al sistema con una combinación de fork / exec

# ls='() { echo NO; }' perl -e 'system("ls *");'
NO

Sin embargo, ls no es un componente:

# type ls
ls is hashed (/bin/ls)
# type echo
echo is a shell builtin

Así que intentemos anular el eco incorporado ("comando" sobrepasa el incorporado para evitar la recursión):

# echo='() { command echo NO; }' bash -c 'echo YES'
NO

Hasta ahora hemos demostrado que:

  1. puede anular un incorporado
  2. y no requiere un script para ser llamado
  3. incluso cuando el primer argumento no es un script
  4. cada llamada a "sistema" es un vector, que otorga privilegios a la persona que llama

Creo que el "sistema" y el "popen" desnudos están podridos, creo que la mayoría de los usos de estos no se molestan en escapar de los metanacteres de la shell en los datos del usuario.

Tengo esta invocación cuando quiero que el shell produzca canales o use shell incorporados, pero aún requiere fork / exec:

exec("sh", "-c", "\"$0\" \"$1\" | tee -a \"$2\"", ...);

La técnica hace que bash se refiera a los argumentos de los comandos -c, siendo $ 0 el primer argumento de este tipo, o "-" se puede usar como relleno:

exec("sh", "-c", "\"$1\" \"$2\" | tee -a \"$3\"", "--", ...);

Esta prueba se ejecuta en un sistema parchado:

$ env "BASH_FUNC_ls()=() { echo NO ; }" bash -c 'ls'
NO

que muestra claramente que este problema no tiene nada que ver con el shell shock.

Si bien los autores de scripts o herramientas de uso de scripts deberían saber validar las aportaciones del usuario y validar / limpiar el entorno (ya que contiene las aportaciones de los usuarios), algunas partes del entorno deben conservarse, y pueden Siempre será fácil ver cuáles podrían ser;

XAUTHORITY, DBUS_SESSION_BUS_ADDRESS, XDG_SESSION_DESKTOP, SSH_AUTH_SOCK son algunas y es posible que otras variables de entorno importantes aún no se hayan inventado

se llama "entorno" por una razón. Es posible que el PATH se pueda sanear, pero el primer comando emitido a system () se puede volver a plantar

La página de manual de sudoedit escribe:

Running shell scripts via sudo can expose the same kernel bugs that make
setuid shell scripts unsafe on some operating systems (if your OS has a
/dev/fd/ directory, setuid shell scripts are generally safe).

Sin embargo, esto no será cierto para los scripts de shell bash de setuid a menos que se nieguen a importar todas las funciones de bash

    
respondido por el Sam Liddicott 29.09.2014 - 15:30
fuente
2

"¿Puede esto dar lugar a una escalada de privilegios en combinación con un ejecutable setuid ...?"

No puede tener scripts setuid en GNU, así que asumamos que un binario setuid llama directamente a un script Bash. Tenga en cuenta antes de comenzar que este es un diseño extremadamente deficiente y es recomendado explícitamente por GNU y nuevamente en el manual setuid . También tenga en cuenta que ld eliminará las variables de entorno más infames y que en GNU / Linux no es posible inyectar código en un proceso setuid o obtener un volcado de él (a menos que sea root). Por lo tanto, los ataques basados en el entorno requieren un binario setuid mal escrito.

Shellshock no desempeña ningún papel en la explotación de estos binarios de setuid. Si el binario sigue las recomendaciones de cordura, no llamará a ningún script de shell, no llamará al sistema y se asegurará de que todas las llamadas de exec* que se estén realizando no estén influenciadas por variables de entorno no confiables, no será vulnerable a ninguna escalada de privilegios por diseño. Si el binario setuid no valida la entrada no confiable, de todos modos será vulnerable.

La razón por la que no debe configurar o iniciar un shell no es porque el entorno elegido por el usuario no confiable se trasladaría al nuevo shell (que depende totalmente de las prácticas de programación), sino porque si cometió algún error, permitiría un ataque de diputado confundido con un alcance ilimitado en lugar de solo permitir operaciones específicas: el sistema solo se vería comprometido con un alcance más amplio extensión que en cualquier otro escenario.

Al llamar a un binario de setuid con un entorno similar a Shellshock desde Bash, su instancia de Bash procesará los primitivos de Bash adicionales con su privilegios, no los privilegios del binario de setuid llamado más adelante, lo que ya debería asumir un entorno hostil de todos modos.

"¿Este vector de escalada requeriría que se llame un script?"

Shellshock implica que Bash se invoca con un entorno que está bajo el control de un principal que tiene privilegios más bajos que el que invoca a Bash en primer lugar.

Si nadie está invocando Bash, su carga de Shellshock es inútil ya que no se procesará (al igual que un exploit OpenSSL no funciona en Microsoft Word).

"¿Es posible que las funciones importadas se utilicen en cualquier momento en la ruta de ejecución normal de / bin / sh -c ARGUMENTS incluso cuando el primer argumento no es un script?"

Si el argumento es un script de shell y /bin/sh apunta a Bash, entonces Bash puede ser explotado. Sin embargo, no hay estrictamente ningún interés en hacer esto, ya que está usando sus propios privilegios para ejecutar el comando. No obtiene ningún privilegio (a menos que asuma una configuración de SELinux o AppArmor en la que tenga más privilegios al usar /bin/sh -c que llamar directamente a algo; dicha configuración se rompería y no sería intencional).

Si el argumento es un binario, se llama al binario. ¿Utiliza Microsoft Word funciones de un Firefox que se ejecuta simultáneamente? No. Lo mismo es cierto aquí: el cargador cargará el código binario y ejecutará el binario, no ejecutará el código con errores de otro binario. El único escenario en el que podría cambiar el comportamiento de un binario es a través de la inyección de código y no puede hacer inyecciones de código en procesos de setuid.

"¿Podría simplemente dar a una variable de entorno el mismo nombre que el primer argumento del sistema?"

Sí, pero el sistema no lee una variable de entorno, ejecuta un comando. Las variables de entorno son solo un diccionario de nombre: pares de cadenas. No reemplazan todos los textos que se usarán en el futuro, independientemente de la semántica. Un programa debe hacer un uso explícito de una variable de entorno al leerlo y decidir preocuparse por él.

"Si es así, ¿significa que cada llamada al sistema (3) por un ejecutable setuid, en un sistema donde / bin / sh es bash, es un vector de escalamiento de privilegios?"

Absolutamente no. Una llamada a system por un binario de setuid es solo una mala idea porque si hubiera una vulnerabilidad, las consecuencias serían ridículamente perjudiciales. Una llamada a system en un SO que usa Bash no cambia nada al hecho de que las escaladas de privilegios requieren dos principios: Shellshock causaría una escalada de privilegios solo cuando un principal con privilegios más altos decide llamar a Bash con un entorno no verificado proporcionado por un principal con privilegios más bajos .

En la mayoría de los casos, una llamada de sistema de este tipo ya no sería deseable porque existen varias formas distintas a Shellshock en las que tal configuración podría volverse incorrecta, y las precauciones que se deben tomar para evitar los ataques de agentes confusos existentes también evitarían el Shellshock. / p>     

respondido por el Steve DL 29.09.2014 - 17:42
fuente
2

Si su binario id (set | u | g) conserva su id [ug] real, la respuesta es no.

Cuando e [ug] id! = real [ug] id, y no se invoca en modo privilegiado ( -p ), bash elimina sus privilegios:

Bash shell.c:main()

  if (running_setuid && privileged_mode == 0)
    disable_priv_mode ();

Cuando se ejecuta en modo privilegiado, o cuando bash está parcheado para no soltar privilegios cuando se llama como / bin / sh (por ejemplo: Debian tiene un parche de este tipo , para evitar romper los programas de id de conjuntos [ug] antiguos, como UUCP), bash no importa funciones del entorno. Bash comprueba si está ejecutando set [ug] id, o en modo privilegiado ( -p ), y no importa funciones del entorno si es así.

Bash shell.c:main()

  /* Initialize internal and environment variables.  Don't import shell
     functions from the environment if we are running in privileged or
     restricted mode or if the shell is running setuid. */
#if defined (RESTRICTED_SHELL)
  initialize_shell_variables (shell_environment, privileged_mode||restricted||running_setuid);
#else
  initialize_shell_variables (shell_environment, privileged_mode||running_setuid);
#endif

Bash variables.c:initialize_shell_variables()

  /* If exported function, define it now.  Don't import functions from
 the environment in privileged mode. */
  if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
    
respondido por el ninjalj 30.09.2014 - 20:38
fuente
-1

Sí !

La prueba de que la función de exportación de bash es solo un riesgo es bastante simple:

/bin/bash
SHELL=/bin/bash
export SHELL
ls() { echo executing /tmp/booby_trapped_ls ; }
declare -fx ls
perl -e 'system ("ls *") ;'
    
respondido por el daniel Azuelos 29.09.2014 - 17:02
fuente

Lea otras preguntas en las etiquetas