Subvertir el indicador de ejecución en sistemas Linux. ¿Por qué es esto posible?

23

Mientras leía esto , encontré el siguiente exploit:

% cp /usr/bin/id ~
% chmod -x ~/id
% ls -al ~/id
-rw-r--r-- 1 edd edd 22020 2012-08-01 15:06 /home/edd/id
% ~/id
zsh: permission denied: /home/edd/id
% /lib/ld-linux.so.2 ~/id
uid=1001(edd) gid=1001(edd) groups=1001(edd),1002(wheel)

Este fragmento muestra que podemos eludir trivialmente los permisos de ejecución del sistema de archivos como un usuario normal sin privilegios. Ejecuté esto en un Ubuntu 12.04.

Si bien el cargador de Linux es un objeto compartido de acuerdo con el archivo (1), también tiene un punto de entrada que le permite ejecutarse directamente. Cuando se ejecuta de esta manera, el cargador de Linux actúa como un intérprete para los archivos binarios ELF.

Sin embargo, en mi máquina OpenBSD, este exploit no es efectivo, porque no puede ejecutar el cargador como un programa. La página del manual de OpenBSD dice: "ld.so es en sí mismo un objeto compartido que el núcleo carga inicialmente".

Pruebe esto en Solaris 9 y obtendrá un segfault. No estoy seguro de lo que sucede en otros lugares.

Mis preguntas son por lo tanto:

  • ¿Por qué el cargador de Linux (cuando se ejecuta directamente) no verifica los atributos del sistema de archivos antes de interpretar un binario ELF?
  • ¿Por qué implementar un mecanismo diseñado para no permitir la ejecución de archivos, si se deja de lado tan trivialmente? ¿Me he perdido algo?
Edd Barrett
fuente
1
No hay una buena razón, pero si alguna vez has logrado eliminar el sistema libc(lo hice una vez, actualizando una caja Arch), estarás agradecido por esta pequeña peculiaridad.
nuevo123456
1
@ new123456 oh dios, el canal de IRC después de esa actualización fue doloroso.
Rob
Es el cargador , no el enlazador.
Deja de dañar a Monica el

Respuestas:

33

El objetivo del executepermiso no es evitar la ejecución en general . Es (1) decirle a los programas qué archivos están destinados a ser ejecutados, y (2) evitar la ejecución como un usuario privilegiado , cuando se especifica el bit setuid (etc.).

El hack de enlazador es menos explotador de lo que parece. Puede ejecutar cualquier archivo no ejecutable que tenga permisos para leer aún más fácilmente:

$ cp unexecutable_file ~/runme
$ chmod +x ~/runme
$ ~/runme

Vea esta discusión en el foro de Arch Linux .

En resumen:

Marcar archivos que deben ejecutarse

Cuando escribe un script de shell, puede marcarlo como ejecutable con chmod +x. Esto insinúa a su shell que pretende que sea ejecutable (de lo contrario, por lo que sabe el shell, es solo otro archivo de texto sin formato). El shell puede mostrarlo en la pestaña de finalización cuando escribe ./Tab.

Del mismo modo: los something.ddirectorios (p init.d. Ej. ) Contienen scripts de shell de inicio o control que los demonios suelen ejecutar automáticamente. Es posible que desee poner un comentario o un archivo README en el directorio como un archivo de texto sin formato. O quizás desee deshabilitar temporalmente uno de los scripts. Puede hacerlo borrando el bit de ejecución para ese archivo en particular. Esto le dice al demonio que lo salte.

Prevenir la ejecución privilegiada

El setuidbit significa que cuando ejecuta el archivo, se ejecuta como un usuario específico (por ejemplo, root).

La publicación del foro lo explica bien:

Desea que un ejecutable sea setuid para algún usuario, pero solo quiere que las personas de un grupo específico puedan ejecutarlo como setuid. Todavía pueden ejecutarlo copiando, pero el indicador setuid se pierde, por lo que lo ejecutarán como ellos mismos, en lugar del usuario que poseía el archivo original.

Caracol mecánico
fuente
2
Gracias: pasé por alto el hecho de que el usuario puede copiar cualquier archivo que pueda leer y, por lo tanto, elegir permisos arbitrarios.
Edd Barrett
¿Qué tal archivos con permiso de ejecución pero sin permiso de lectura?
Lie Ryan
@LieRyan ¿Qué hay de ellos?
Vuelva a instalar Mónica el
@BrendanLong: Obviamente no puedes copiarlos, así que no puedes cambiar sus permisos. (Pero por qué querría hacerlo, no puedo decir: lo único que podría hacer con la copia de todos modos es dejar caer el permiso de ejecución)
MSalters
9

Si tiene acceso de lectura a un archivo, siempre puede hacer una copia del mismo.

Si puede hacer una copia personal, siempre puede marcar esa copia como ejecutable.

Esto no explica el comportamiento de ld-linux pero sí indica que puede no ser una escapatoria de seguridad muy útil.

Si desea una seguridad más estricta, considere SELinux

RedGrittyBrick
fuente
Esto es muy cierto.
Edd Barrett
Era solo una pregunta conceptual. Supongo que también podrías configurar nonexec en los sistemas de archivos.
Edd Barrett
2

Mirando la pregunta un poco diferente: como dice Mechanical Snail, el permiso de ejecución en un archivo no tiene la intención de evitar la ejecución. Sin embargo, la opción de sistema de archivos "noexec" impide la ejecución, y no es tan fácil de eludir (no es compatible con todos los sistemas de archivos, pero ciertamente con los más populares de Linux). Si el administrador quisiera evitar que los usuarios ejecuten sus propios programas, podrían especificar la opción noexec en los directorios home y tmp, y en cualquier otra donde los usuarios puedan crear archivos.

$ mount -o noexec /dev/sdd1 /test
$ cd /test
$ cp /usr/bin/id .
$ ./id
-bash: ./id: Permission denied

Aparentemente, era posible eludir la opción noexec usando el truco del cargador mencionado en la pregunta, pero eso se solucionó en el kernel algunas versiones atrás.

Desde http://linux.die.net/man/8/mount :

noexec

No permita la ejecución directa de ningún binario en el sistema de archivos montado. (Hasta hace poco, era posible ejecutar binarios de todos modos utilizando un comando como /lib/ld*.so / mnt / binary. Este truco falla desde Linux 2.4.25 / 2.6.0.)

Randy Orrison
fuente