Aquí está el comando que he usado para verificar mi bash shell para el error Shellshock:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
¿Alguien puede explicar el comando en detalles?
Aquí está el comando que he usado para verificar mi bash shell para el error Shellshock:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
¿Alguien puede explicar el comando en detalles?
Respuestas:
Esta respuesta es un derivado de un artículo original en la Revista Fedora de Matthew Miller, licenciado bajo la licencia Creative Commons Attribution-Share Alike 4.0 .
Dejame explicar:
env x='() { :;}; echo OOPS' bash -c :
Esto imprimirá "OOPS" en un sistema vulnerable, pero saldrá silenciosamente si se ha parcheado bash.
env x='() { :;}; echo OOPS' bash -c "echo this is a test"
Esto imprimirá "OOPS" en un sistema vulnerable, pero imprimirá “this is a test”
si bash ha sido parcheado.
Y probablemente haya escuchado que tiene algo que ver con las variables de entorno. Pero, ¿por qué se ejecuta el código en las variables de entorno? Bueno, no se supone que lo sea, pero, debido a una característica que me siento tentada a llamar demasiado inteligente por su propio bien, hay espacio para un defecto. Bash es lo que se ve como un indicador de terminal, pero también es un lenguaje de script y tiene la capacidad de definir funciones. Lo haces así:
$ Ubuntu() { echo "Ubuntu is awesome."; }
y luego tienes un nuevo comando. Tenga en cuenta que el echo
aquí todavía no se ejecuta; simplemente se guarda como lo que sucederá cuando ejecutemos nuestro nuevo comando. ¡Esto será importante en un minuto!
$ Ubuntu
Ubuntu is awesome.
¡Útil! Pero, digamos, por alguna razón, necesitamos ejecutar una nueva instancia de bash, como un subproceso, y queremos ejecutar mi nuevo comando increíble bajo eso. La declaración bash -c somecommand
hace exactamente esto: ejecuta el comando dado en un nuevo shell:
$ bash -c Ubuntu
bash: Ubuntu: command not found
Oh. Triste. El niño no heredó la definición de la función. Pero sí es inherente al entorno: una colección de pares clave-valor que se han exportado desde el shell. (Este es un concepto completamente diferente; si no está familiarizado con esto, confíe en mí por ahora). Y resulta que bash también puede exportar funciones. Asi que:
$ export -f Ubuntu
$ bash -c Ubuntu
Ubuntu is awesome.
Lo cual está muy bien, excepto que el mecanismo por el cual esto se logra es algo dudoso . Básicamente, dado que no hay magia de Linux / Unix para realizar funciones en variables de entorno, la función de exportación en realidad solo crea una variable de entorno regular que contiene la definición de la función. Luego, cuando el segundo shell lee el entorno "entrante" y encuentra una variable con contenido que parece una función, la evalúa.
En teoría, esto es perfectamente seguro porque, recuerde, definir una función en realidad no la ejecuta . Excepto, y es por eso que estamos aquí, hubo un error en el código donde la evaluación no se detuvo cuando se llegó al final de la definición de la función. Simplemente sigue yendo.
Eso nunca sucedería cuando la función almacenada en una variable de entorno se haga legítimamente con export -f
. Pero, ¿por qué ser legítimo? Un atacante puede inventar cualquier variable de entorno antigua, y si parece una función, ¡los nuevos shells bash pensarán que sí!
Entonces, en nuestro primer ejemplo:
env x='() { :;}; echo OOPS' bash -c "echo this is a test"
El env
comando ejecuta un comando con un conjunto de variables dado. En este caso, estamos configurando x
algo que parece una función. La función es solo una :
, que en realidad es un comando simple que se define como no hacer nada. Pero luego, después de lo semi-colon
que señala el final de la definición de la función, hay un echo
comando. Se supone que eso no debe estar allí, pero no hay nada que nos impida hacerlo.
Entonces, el comando dado para ejecutarse con este nuevo entorno es un nuevo shell bash, nuevamente con un comando " echo this is a test
" o "no hacer nada :
", después del cual saldrá, completamente inofensivo.
Pero - ¡Uy! Cuando ese nuevo shell se inicia y lee el entorno, llega a la x
variable y, como parece una función, la evalúa. La definición de la función se carga de forma inofensiva, y luego también se activa nuestra carga maliciosa. Por lo tanto, si ejecuta lo anterior en un sistema vulnerable, se le devolverá la “OOPS”
impresión. O, un atacante podría hacer mucho peor que simplemente imprimir cosas.
env
no es necesario. Se puede obtener el mismo resultado (pasa / no pasa, dependiendo de si se ha actualizado Bash) utilizando el comando sin ella: x='() { :;}; echo OOPS' bash -c "echo this is a test"
. Esto se debe a que preceder un comando con una asignación de variable pasa esa variable y su valor al bash -c "..."
entorno del comando ( en este caso).
env
el shell desde el que se ejecuta la prueba determina si es necesario o no , no el shell que se está probando. (Estos pueden ser los mismos. Incluso entonces, estamos probando cómo bash procesa su propio entorno). Los shells de estilo Bourne aceptan la NAME=value command
sintaxis; Los depósitos de estilo C (p. Ej. csh
, tcsh
) No. Entonces, la prueba es un poco más portátil env
(a costa de crear a veces confusión sobre cómo funciona).
En la versión no parcheadabash
, almacena definiciones de funciones exportadas como variables de entorno.
Almacenar una función x
como,
$ x() { bar; }
$ export -f x
Y verifique su definición como,
$ env | grep -A1 x
x=() { bar
}
Entonces uno podría explotar esto definiendo sus propias variables de entorno e interpretándolas como definiciones de funciones. Por ejemplo env x='() { :;}'
sería tratado como
x() { :;
}
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
De man env
,
env
- ejecutar un programa en un entorno modificado.
:
no haga nada más que salidas con estado de salida 0
. ver mas
Cuando se inicia una nueva instancia de bash sin parches bash -c "echo this is a test"
, la variable de entorno creada se trata como una función y se carga. En consecuencia, uno obtiene la salida
vulnerable esto es una prueba
Nota: El eco fuera de la definición de la función se ejecutó inesperadamente durante el inicio de bash. La definición de la función es solo un paso para que la evaluación y la explotación sucedan, la definición de la función en sí y la variable de entorno utilizada son arbitrarias. El shell observa las variables de entorno, ve x, que parece que cumple con las restricciones que conoce sobre cómo se ve una definición de función, y evalúa la línea, ejecutando involuntariamente también el eco (que podría ser cualquier comando, malicioso o no) . Ver también esto
env test='() { echo "anything"; }' bash -c "echo otherthing"
verás en la salida otherthing
. Eso se corrige en el parche. siéntase libre si aún no estoy claro.
unpatched bash
puede llamar a la función como está definida, pero en un parche bash
la definición en sí no está allí.
echo vulnerable
) no se ejecuta. Tenga en cuenta que en los últimos parches, la función pasada debe tener un prefijo específico ( env 'BASH_FUNC_x()'='() { :;}; echo vulnerable' bash -c "echo this is a test"
). Se pueden usar algunos parches más recientes en %%
lugar del primero ()
.