¿Cómo roba vim los archivos propiedad de root?

39

Sea testigo de lo siguiente:

sh-3.2$ mkdir testcase
sh-3.2$ cd testcase
sh-3.2$ sudo touch temp
sh-3.2$ ls -al
total 0
drwxr-xr-x   3 glen  staff  102 19 Dec 12:38 .
drwxr-xr-x  12 glen  staff  408 19 Dec 12:38 ..
-rw-r--r--   1 root  staff    0 19 Dec 12:38 temp

sh-3.2$ echo nope > temp
sh: temp: Permission denied

sh-3.2$ vim temp
# inside vim
itheivery
# press [ESC]
:wq!
# vim exits

sh-3.2$ ls -al
total 8
drwxr-xr-x   3 glen  staff  102 19 Dec 12:38 .
drwxr-xr-x  12 glen  staff  408 19 Dec 12:38 ..
-rw-r--r--   1 glen  staff    7 19 Dec 12:38 temp

¡De alguna manera, vim ha tomado este archivo propiedad de root y lo ha cambiado a un archivo propiedad del usuario!

Esto solo parece funcionar si el usuario posee el directorio, pero aún así parece que no debería ser posible. ¿Alguien puede explicar cómo se hace esto?

Glenjamin
fuente

Respuestas:

51

Usted, glenes el propietario del directorio (vea el .archivo en su listado). Un directorio es solo una lista de archivos y tiene permiso para modificar esta lista (por ejemplo, agregar archivos, eliminar archivos, cambiar la propiedad para volver a ser suya, etc.). Es posible que no pueda alterar el contenido del archivo directamente, pero puede leer y desvincular (eliminar) el archivo en su conjunto y agregar nuevos archivos posteriormente. 1 Solo presenciando el antes y el después, puede parecer que el archivo ha sido alterado.

Vim utiliza archivos de intercambio y los mueve bajo el agua, lo que explica por qué parece escribir en el mismo archivo que en su shell, pero no es lo mismo. 2

Entonces, lo que hace Vim se reduce a esto:

cat temp > .temp.swp          # copy file by contents into a new glen-owned file
echo nope >> .temp.swp        # or other command to alter the new file
rm temp && mv .temp.swp temp  # move temporary swap file back

1 Esta es una diferencia importante en el manejo de permisos de archivos entre Windows y Unices. En Windows, por lo general, uno no puede eliminar archivos para los que no tiene permiso de escritura.

2 actualización: como se señaló en los comentarios, Vim no lo hace de esta manera para cambiar la propiedad, ya que el número de inodo en el temparchivo no cambia (aparece ls -liantes y después). Usando stracepodemos ver exactamente lo que vimhace. La parte interesante está aquí:

open("temp", O_WRONLY|O_CREAT|O_TRUNC, 0664) = -1 EACCES (Permission denied)
unlink("temp")                               = 0
open("temp", O_WRONLY|O_CREAT|O_TRUNC, 0664) = 4
write(4, "more text bla\n", 14)              = 14
close(4)                                     = 0
chmod("temp", 0664)                          = 0

Esto muestra que solo se desvincula , pero no cierra el descriptor de archivo temp. Simplemente sobrescribe todo su contenido ( more text bla\nen mi caso). Supongo que esto explica por qué el número de inodo no cambia.

gertvdijk
fuente
3
FWIW puede verificar que esto esté sucediendo ejecutando ls -ilantes y después ... si tempel número de inodo cambió, sabe que es un archivo diferente con el mismo nombre.
Inútil
3
Se podría agregar que rm en realidad no elimina el archivo, sino que solo elimina un enlace al archivo, y el archivo no se elimina antes de que el número de enlaces disminuya a 0. rm simplemente elimina la entrada al archivo en el directorio. Si la raíz tiene otro enlace (enlace duro) al archivo en otro directorio, el usuario no puede eliminar el archivo.
gerrit
1
@Inútil, lo intenté, ¡y el número no cambió aunque el propietario y la marca de tiempo cambiaron!
amyassin
1
@amyassin Tienes razón! He actualizado mi respuesta con un extracto extraño que lo explica.
gertvdijk
1
Como nota a un lado de su nota sobre los permisos de Windows vs. Unix, si desea un comportamiento similar al de Windows en Unix, puede crear un directorio propiedad de root (u otro usuario que debería tener permisos universales para eliminar / cambiar el nombre / etc.) y configurar el adhesivo bit en el directorio Entonces, los usuarios solo podrán eliminar sus propios archivos.
Matthew Crumley
16

antes de:

-rw-r--r-- 1 root staff 0 19 Dec 12:38 temp

después:

-rw-r--r-- 1 glen staff 7 19 Dec 12:38 temp

El vim no rompe la barrera del permiso. Solo eche un vistazo a la información del archivo que aparece en la lista cuidadosamente y luego podría descubrir que vim realmente eliminó el archivo original (porque tiene permiso para eliminar el archivo aunque no puede cambiar su contenido) y luego creó un nuevo archivo propio ( ver que el propietario ya no es 'root').

Y mientras edita el archivo original en vim, le advierte que está cambiando un archivo de solo lectura. Entonces, cuando escribe el comando :wq!(forzar la operación), lo que vim solo puede hacer es eliminar el archivo existente y crear un nuevo archivo que tenga el mismo nombre.

Espero que ayude.

ymfoi
fuente
1

Use la -iopción de lspara ver el número de inodo, que es un identificador único (dentro del sistema de archivos) de un archivo u otro objeto.

Verá que el archivo fue reemplazado por un objeto diferente: el número de inodo probablemente cambiará.

Ver el mismo número de inodo no es prueba de nada: se puede reciclar un número de inodo. Si eliminamos el último enlace a un archivo y luego creamos un nuevo archivo, podríamos obtener uno con el mismo número de inodo. Pero eso no puede suceder si el archivo antiguo se elimina después de crear el nuevo. Por ej mv file file.tmp; touch file; rm file.tmp. Sospecho que vim realmente hace algo análogo a esto echo new_content > tmpfile; mv tmpfile file. La mvoperación se traducirá en una renamellamada al sistema, por lo que la asignación de números de inodo depende de cómo el sistema de archivos implementa un cambio de nombre que desvincula un destino.

Kaz
fuente