bash - ¿Cómo funciona CVE-2014-7169? Desglose del código de prueba
exploit shellshock-bash-bug (2)
Con una versión de bash que ha sido parcheada para shellshock
$ bash --version
GNU bash, version 3.2.52(1)-release (x86_64-apple-darwin12)
Copyright (C) 2007 Free Software Foundation, Inc.
$ env x=''() { :;}; echo vulnerable'' bash -c "echo this is a test"
bash: warning: x: ignoring function definition attempt
bash: error importing function definition for `x''
this is a test
Otro exploit similar aún funciona y se le ha asignado CVE-2014-7169
$ env X=''() { (a)=>/' bash -c "echo date"; cat echo
bash: X: line 1: syntax error near unexpected token `=''
bash: X: line 1: `''
bash: error importing function definition for `X''
Thu Sep 25 12:47:22 EDT 2014
$ ls echo
echo
Buscando un desglose de esto también.
El bicho
CVE-2014-7169 es un error en el analizador de bash. El analizador de Bash usa una variable eol_ungetc_lookahead
para ungetc caracteres a través de líneas. Esa variable no se restableció correctamente desde la función reset_parser
, que se llama, por ejemplo, en algunos errores de sintaxis. Usando ese error, es posible inyectar un carácter en el inicio de la siguiente línea de entrada de bash.
Por lo tanto, el código de prueba fuerza un error de sintaxis, usando (a)=
o la function aa
, agrega el carácter de redireccionamiento a la siguiente línea >
, y agrega una continuación de línea /
, que conduce a cualquiera de las dos versiones del código de prueba:
() { (a)=>/
() { function a a>/
Cuando se ejecuta bash, procesa variables del entorno, encuentra que la variable X
es una función exportada y la evalúa para importar la función. Pero la evaluación falla con un error de análisis, dejando el carácter >
en la variable eol_ungetc_lookahead
. Luego, cuando se analiza la echo date
argumento del comando, antepone el carácter >
, lo que lleva a >echo date
, que ejecuta la date
redirigida a un archivo llamado echo
.
Su relación con el error anterior.
El error anterior es obviamente muy diferente al error original de shellshock. En realidad hay varios problemas:
- Bash evalúa completamente una variable que se parece a una función exportada (comienza con los cuatro caracteres
() {
). CVE-2014-6271. - Bajo algunas condiciones, es posible inyectar un carácter en una variable ungetc, que se añadirá a la siguiente línea de entrada. CVE-2014-7169.
- Bash permite que cada variable de entorno se trate como una función exportada, siempre que comience con los cuatro caracteres
() {
. CVE-2014-6271, CVE-2014-7169, todas las demás CVE en las que se activa un error en el analizador de bash. - Hay una pila limitada para la redirección de aquí-doc, y no hay verificación de desbordamiento. CVE-2014-7186, que lleva a la corrupción de la memoria, y probablemente se puede aprovechar para la ejecución de código arbitrario.
- Hay una pila limitada para estructuras de control anidadas (
select
/for
/while
), con comprobaciones de desbordamiento. Esa pila todavía está corrompida. CVE-2014-7187.
Las correcciones
- El primer parche restringe a bash para evaluar una definición de función única en cada variable que se parece a una función exportada.
- El segundo parche restablece correctamente
eol_ungetc_lookahead
enreset_parser
. - El tercer parche cambia la forma en que se exportan las funciones: ahora se exportan en variables denominadas
BASH_FUNC_functionname%%
.
Superficie de ataque
El gran problema aquí ha sido que cada variable de entorno podría usarse como un vector para el ataque. Normalmente, los atacantes no pueden controlar variables de entorno arbitrarias, de lo contrario ya hay otros ataques conocidos (piense en LD_PRELOAD
, PATH
, IFS
, ...).
sudo
no se ve afectado porque elimina las funciones bash exportadas del entorno, como lo menciona Gilles en security.SE .
ssh
se ve afectado. Las instalaciones típicas de sshd solo permiten que un conjunto limitado de variables de entorno se exporten según lo configurado en AcceptEnv en sshd_config
, por ejemplo: LANG
y LC_*
. Incluso con este enfoque agresivo de listas blancas, en shell shock cualquier variable podría ser un vector de ataque.
No solo cada variable de entorno era un vector de ataque potencial, sino que también expusieron un analizador de> 6000 líneas.
Lecciones reaprendidas
system
, popen
, y otros son potencialmente peligrosos. No solo debe tener cuidado con sus argumentos: incluso cuando los argumentos se fijan en tiempo de compilación, el entorno es un posible vector de ataque. Use fork()/execve()
, preferiblemente con un ambiente limpio (pero al menos restrinja el ambiente a las variables incluidas en la lista blanca, preferiblemente con sus valores verificados con la cordura). Recuerde que un sistema de buena calidad hace lo que se supone que debe hacer, mientras que un sistema seguro hace lo que se supone que debe hacer y nada más . Invocar un shell completo hace que hacer nada más un poco más difícil.
La complejidad es el enemigo de la seguridad. En estos días puedes encontrar fácilmente personas que recomiendan conchas más simples. La mayoría de los shells están libres de shellshock al no ser compatibles con las funciones exportadas. A la inversa, bash ha recibido muchas características de seguridad a lo largo de los años (es necesario invocarla con -p
para evitar que se le caigan los privilegios en el inicio, desinfecta IFS, ...), así que no asuman que estoy abogando por cambiar de shell Esto es más de un consejo general.
Vale la pena volver a leer algunos extractos del antiguo capítulo "Programación segura para Linux y UNIX HOWTO" de David Wheeler sobre variables de entorno .
§5.2.3 ¶1:
Para los programas setuid / setgid seguros, se debe extraer cuidadosamente la lista corta de variables de entorno necesarias como entrada (si corresponde). Luego, se debe borrar todo el entorno, y luego se restablece un pequeño conjunto de variables de entorno necesarias a valores seguros. Realmente no hay una mejor manera de hacer llamadas a programas subordinados; no hay un método práctico de enumerar `` todos los valores peligrosos ''''.
§5.2.3 ¶6:
Si realmente necesita valores proporcionados por el usuario, verifique primero los valores (para asegurarse de que los valores coincidan con un patrón de valores legales y que estén dentro de una longitud máxima razonable).
Agitando mis manos mucho, sospecho que el nuevo exploit hace lo siguiente:
- La barra invertida ayuda a omitir el parche original, por lo que la cadena aún se evalúa.
- El
>
combina conecho
como una redirección de salida para el shellbash
- Dado que la evaluación utiliza la
echo
para definir la función, la única parte del argumento-c
que queda por ejecutar es ladate
, cuya salida va a unecho
nombre de archivo en lugar de a la salida estándar.
Es lo mejor que se me ocurre antes de leer la fuente de bash
, pero sospecho que la barra invertida facilita algún tipo de desbordamiento de búfer que permite que la cadena de entorno y el argumento de -c
se fusionen.