2012-04-10 15 views
16

Estoy escribiendo una colección de utilidades en bash que tiene una biblioteca común. Cada secuencia de comandos que escribo debe tener un bloque de código que determine la ruta de acceso de la biblioteca en relación con el ejecutable. No es el código real, sino un ejemplo:¿Puedo confiar en las variables de mi entorno?

#!/bin/bash 

DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 
. $DIR/../lib/utilities/functions 

En lugar de un preámbulo que trata de buscar la biblioteca, tuve la brillante idea de utilizar una variable de entorno para indicar la ubicación bibliotecas.

#!/bin/bash 

. $TOOLS_LIBRARY_PATH 

Podría utilizar un programa de envoltura para establecer esa variable de entorno, o podría establecerlo en mi propio camino. Puede haber mejores formas de organizar un conjunto de herramientas bash, pero la pregunta es:

¿Puedo confiar en las variables de mi entorno?

Esta es una de esas preguntas que nunca he pensado realmente acerca de eso. Cuando se programa en otros idiomas, las rutas se usan para buscar bibliotecas (por ejemplo, LD_LIBRARY_PATH, PYTHONPATH, PERLLIB, RUBYLIB, CLASSPATH, NODE_PATH), pero nunca he tenido que detenerme y pensar en cómo podría ser inseguro.

De hecho, LD_LIBRARY_PATH tiene Why LD_LIBRARY_PATH is bad para desalentar su uso. Las variables de entorno de ruta de biblioteca de Ruby y Perl se ignoran si se invocan sus mecanismos de seguridad, $SAFE y -T (taint mode), respectivamente.

Mis pensamientos hasta ahora ...

  • El usuario puede configurar TOOLS_PATH_LIBRARY a una biblioteca de su elección, pero la utilidad se ejecutará bajo su UID. Simplemente podrían ejecutar su biblioteca maliciosa directamente con bash.
  • Mis herramientas sudo algunas cosas. Alguien podría establecer su TOOLS_PATH_LIBRARY a algo que aproveche esto. Pero las herramientas no se ejecutan a través del sudo, solo invocan sudo aquí y allá. El usuario debería ser un sudoer en cualquier caso, simplemente podría llamar al sudo directamente.
  • Si no puedo confiar en TOOLS_PATH_LIBRARY, entonces no puedo confiar en PATH. Todas las invocaciones de programa deben usar rutas absolutas.
  • He visto programas shell que usan alias para programas que son absolutos, de modo que en lugar de llamar a ls, use una variable, como LS=/bin/ls. Según lo que he leído, esto es para proteger a los usuarios de la redefinición de los valores predeterminados del programa como alias. Ver: PATH, functions and security. Bash scripting best practices. .
  • Perl's taint mode trata todas las variables de entorno como "contaminadas", lo cual es un presentimiento, por lo que estoy tratando de razonar sobre los riesgos del medio ambiente.
  • No es posible que un usuario cambie el entorno de otro, a menos que ese usuario sea root. Por lo tanto, solo me preocupa que un usuario cambie su propio entorno para escalar privilegios. Veo: Is there a way to change another process's environment variables?

he rubber ducked esto en una respuesta de tipo, pero todavía voy a publicarlo, ya que no es una respuesta fácil.

Actualización: ¿Cuáles son los problemas de seguridad que rodean el uso de variables de entorno para especificar rutas a bibliotecas y ejecutables?

+5

Por supuesto que no se puede. No puedes confiar en nada, nunca. Pero si no asumes que es correcto, ¿dónde estás? No puedes hacer nada. –

+0

Si puede resolver todos los directorios sin variables adicionales, hágala así, sea amable con sus usuarios directos. Pero también deje la puerta trasera en forma de variable de entorno para ser amable con los que se van a integrar con su biblioteca.Supongamos que las variables están configuradas correctamente (vea el comentario de Chris Morgan para "por qué"). – bobah

+1

Bonita publicación, has identificado muchos problemas. Interesante, pero parece que estás al borde de la parálisis del análisis (como dice Chris). La seguridad se trata de capas, ¿verdad? Si no puede confiar en sus usuarios, necesita más capas para evitar que le disparen en el pie. Las personas pueden obtener un doctorado en cuestiones de seguridad, y aún así obtener su MilSpec o sistemas de seguridad bancaria ser pirateados, por lo que tendrá que averiguar dónde se compensa el tiempo transcurrido entre la preparación de un archivo adjunto frente a la probabilidad de éxito es adjuntar para su proyecto actual, sus usuarios legítimos y otras partes interesadas. Buena suerte. – shellter

Respuesta

1

Respuesta corta:

Suponiendo que el usuario es capaz de ejecutar programas y el código de su propia elección de todos modos, usted no tiene que confiar en cualquier cosa que se alimentan, incluyendo el medio ambiente. Si la cuenta es limitada de alguna manera (sin acceso a shell, sin escritura a sistemas de archivos que permiten la ejecución), eso puede cambiar la imagen, pero mientras tus scripts solo hagan cosas que el usuario podría hacer ella misma, ¿por qué protegerse contra maliciosos? ¿interferencia?respuesta


más larga:

Hay por lo menos dos emisiones distintas a considerar en términos de problemas de seguridad:

  • ¿Qué y quién nos necesitamos para protegerse contra?
    • (cuestión estrechamente relacionada: ¿Qué puede hacer realidad nuestro programa y lo que podría potencialmente romper?)
  • ¿Cómo lo hacemos?

Si y mientras su programa se ejecuta bajo el ID de usuario del usuario que inicia el programa y proporciona todas las entradas (es decir, el único que puede montar cualquier ataque), solo hay situaciones excepcionales en las que tiene sentido en absoluto para endurecer el programa contra los ataques. Me viene a la mente la protección anticopia y el compartir puntajes altos, pero ese grupo de cosas no solo se preocupa por las entradas, sino probablemente aún más al evitar que el usuario lea el código y la memoria. Ocultar el código de un script de shell sin algún tipo de truco de suid/sgid no es nada que yo sepa hacer; lo mejor que podría pensar sería oscurecer el código.

En esta situación, cualquier cosa que el usuario pueda engañar al programa, también podría hacerlo sin la ayuda de la herramienta, por lo que tratar de "proteger" contra los ataques de este usuario es irrelevante. Tu descripción no parece que necesites protección contra ataques.


Suponiendo que usted necesita protección, simplemente no se puede depender de variables de entorno - y si no consigue restablecer las cosas como LD_LIBRARY_PATH y LD_PRELOAD, incluso herramientas de llamada con rutas absolutas como /bin/id o /bin/ls no le dará una respuesta fiable , a menos que esa herramienta esté compilada estáticamente. Esta es la razón por la cual sudo tiene env_reset activado por defecto y por qué ejecutar programas suid debe ignorar ciertas variables de entorno. Tenga en cuenta que esto significa que su punto de que TOOLS_PATH_LIBRARY y PATH son igualmente confiables puede ser cierto en su situación, pero no es necesariamente cierto en casos de frontera de otras situaciones: un administrador del sistema puede reiniciar PATH para el uso de sudo, pero deja pasar variables de entorno no estándar mediante.

Como se señaló anteriormente, argv[0] (o su equivalente bash ${BASH_SOURCE[0]}) no es más confiable que las variables de entorno. El usuario no solo puede hacer una copia o enlace simbólico de su archivo original; execve o bash's exec -a foo bar permite poner cualquier cosa en argv[0].

+0

No, esto ayuda. Esto aborda lo que estoy preguntando. Tal vez pondré más historia de fondo en mi próxima pregunta. No estoy tratando de ocultar código o proteger datos. Tuve la brillante idea de usar una variable de entorno como ruta de acceso a una biblioteca, escribirla y luego pensé que se parecía mucho a 'eval'. Pensé, esto tiene que ser un agujero de seguridad de la cara. Cuanto más pensaba en eso, más pensaba que no. Ahora estoy pensando que no. –

+0

Entonces, lo que dices es: "Si y mientras tu programa se ejecute bajo el ID de usuario del usuario que inicia el programa y proporciona toda la información (es decir, el único que puede montar cualquier ataque)" entonces ** no tienes que confiar ** en el medio ambiente. –

+0

Suponiendo que el usuario pueda ejecutar los programas y el código de su elección de todos modos, sí. Si la cuenta es limitada de alguna manera (sin acceso a shell, sin escritura a sistemas de archivos que permiten la ejecución), eso puede cambiar la imagen, pero mientras tus scripts solo hagan cosas que el usuario podría hacer ella misma, ¿por qué protegerse contra maliciosos? ¿interferencia? –

3

Si bien existen mecanismos en varios programas para evitar la modificación de las variables de entorno, la conclusión es que no, no se puede confiar en las variables de entorno. La preocupación de seguridad es muy básica:

Cada vez que un usuario puede cambiar lo que se espera que se ejecute, surge la posibilidad de que explote una vulnerabilidad.

En punto, echa un vistazo a CVE-2010-3847. Con eso, un atacante desfavorecido con acceso de escritura a un sistema de archivos que contenga un setuid o binarios setgid podría usar este defecto para escalar sus privilegios. Implica una variable de entorno modificada por el usuario.

CVE-2011-1095 es otro ejemplo, y no implica binarios SUID. Haga una búsqueda en google de "entorno de entorno glibc" para ver los tipos de cosas que las personas podían hacer con las modificaciones de las variables de entorno. Bastante astuto

Sus preocupaciones realmente se reducen a su declaración de:

El usuario podría fijar TOOLS_PATH_LIBRARY a una biblioteca de su elección, pero la utilidad se ejecutará bajo su UID. Podrían simplemente ejecutar su biblioteca maliciosa directamente con bash.

Frase clave aquí - ejecutar su biblioteca maliciosa. Esto supone que su biblioteca también es propiedad de su UID.

Aquí es donde un marco de seguridad le hará mucho bien. Uno que he escrito que se centra exclusivamente en este problema se puede encontrar aquí:

https://github.com/cormander/tpe-lkm

El módulo se detiene execve/mmap/mprotect pide a los archivos que se puede escribir, o no propiedad de un usuario de confianza (raíz) . Siempre que no puedan poner código malicioso en un archivo/directorio propiedad del usuario de confianza, no podrán explotar el sistema de esta manera.

Si está utilizando binarios SUdo o sudo que incluyen esas variables, puede considerar habilitar las opciones "paranoico" y "estricto" para evitar que incluso el usuario root confíe en los binarios que no son propiedad de la raíz.

Debo mencionar que este método de ejecución confiable de rutas protege la ejecución directa con binarios y bibliotecas compartidas. Hace poco (si acaso) contra los lenguajes interpretados, ya que analizan bytecode y no lo ejecutan directamente. Por lo tanto, aún necesita cierto grado de cuidado con PYTHONPATH, PERLLIB, CLASSPATH, etc. y utilice los mecanismos de seguridad del lenguaje que mencionó.

+0

CVE-2010-3847 implica un SUID binario, ya que el OP no tiene ninguno de sus propios códigos SUID (la fijación 'sudo' está fuera de su alcance, ya que cualquier ataque de sudo dentro de su código puede explotarse tan fácilmente desde afuera) , No creo que esto pueda ser un riesgo? –

+0

@DouglasLeeder: ese fue solo un ejemplo. Incluí CVE-2011-1095 también. La lista sigue y sigue, simplemente no puedo recordarlos a todos fuera de mi cabeza. –

+0

"Cada vez que un usuario puede cambiar lo que se espera que se ejecute, surge la posibilidad de que explote una vulnerabilidad". - Creo que tienes que agregar 'en un nivel de seguridad diferente', de lo contrario el usuario altera el comando que está escribiendo carece de eso. –

0

Nunca se puede confiar en el entorno de otra persona.

¿Por qué no crear simplemente un nuevo usuario que contenga todo este código importante? Luego, puede obtener la información directamente desde /etc/passwd o usar la sintaxis ~foo para buscar el directorio de inicio del usuario.

# One way to get home directory of util_user 
DIR=$(/usr/bin/awk -F: '$1 == "util_user" {print $6}' /etc/passwd) 

# Another way which works in BASH and Kornshell 
[ -d ~util_dir ] && DIR=~util_dir 


# Make sure DIR is set! 
if [ -z "$DIR" ] 
then 
    echo "Something's wrong!" 
    exit 
fi 
Cuestiones relacionadas