6 - Manejo de ficheros

[editar]
Tutorial creado por Mononeurona.org. Extraido de: http://www.mononeurona.org/index.php?idp=535
08 de Noviembre de 2005
La gestión de ficheros es siempre una tarea delicada, ya que se presta a ataques locales de "race condition". Se produce una "race condicion" cuando varios procesos están compitiendo por un recurso, y entre dos operaciones de uno de ellos se le cuela otro que cambia las características del recurso. Supongamos, por ejemplo, el caso siguiente:

if(access("/path/del/fichero",W_OK)
0) open(...);
El código anterior verifica que el usuario que ejecuta el programa tenga acceso de escritura al fichero en cuestión. Si es el caso, el open lo abre para escritura y graba en él.

Existe, sin embargo, una "race condition". Supongamos que un usuario malicioso crea un fichero válido, ejecuta el código anterior y, entre el "access()" y el "open()", borra el fichero y crea un enlace, pongamos, a "/etc/passwd". Las consecuencias pueden ser catastróficas. Evidentemente hace falta mucha casualidad para que las manipulaciones del usuario tengan lugar en el momento oportuno, pero no hay nada que le impida crear un proceso que lo intente repetidamente hasta tener éxito. A un ordenador no le cuesta nada intentarlo durante una semana seguida.

Es por ello que "access()" es una función anticuada que no debería ser utilizada nunca, y menos en procesos SUID. En su lugar deben utilizarse funciones como "stat()","lstat()" y "fstat()", como se verá dentro de un momento. Lamentablemente estas funciones carecen de la propiedad de "access()" que permite validar el acceso en función del usuario real del proceso, no del usuario efectivo. Ello la hace muy conveniente en procesos SUID.

La forma correcta de manejar un fichero es la siguiente:

  • Apertura de un fichero ya existente, como lectura o como "append":
lstat()
Vemos si es aceptable (enlace simbólico, dispositivo, fichero regular, etc).
open()
fstat()
Comparar el "lstat()" con el "fstat()". Si son diferentes es que alguien ha tocado el fichero mientras tanto.
  • Creación de un fichero nuevo:
open(O_CREAT|O_EXCL)
  • Truncado de un fichero:
lstat()
Vemos si es aceptable (enlace simbólico, dispositivo, fichero regular, etc).
open()
fstat()
Comparar el "lstat()" con el "fstat()". Si son diferentes es que alguien ha tocado el fichero mientras tanto.
ftruncate()
  • Borrado de un fichero:
La forma más sencilla consiste en
setegid(GID real)
seteuid(UID real)
unlink()
seteuid(UID privilegiado)
setegid(GID privilegiado)

En cualquier caso es preciso verificar que el usuario real (no el efectivo) del proceso tenga permiso para efectuar esa operación. Se puede hacer un "setegid()", "seteuid()" al usuario real antes de la operación y volver a usuario SUID de nuevo, de la misma forma, una vez validado el acceso. Otra posibilidad es crear una "pipe", hacer un "fork()" y que sea el hijo, previos "setgid()" y "setuid()", quien acceda al fichero. Ello es especialmente importante si en el "path" hay directorios, ya que de otra forma se nos obligaría a verificar componente a componente. Ese es precisamente el reciente problema de seguridad de los servidores web bajo Windows NT y el "::$DATA".

En los sistemas no POSIX que no tienen la opción de "saved uid/gid" se puede utilizar la llamada

setreuid(geteuid(),getuid());

para intercambiar el usuario real y efectivo.

Como regla general, nunca crees o leas ficheros en directorios en los que pueda escribir todo el mundo. Y cuando crees ficheros, hazlo con los privilegios más restringidos que sea posible. Debemos recordar también que la verificación del acceso se realiza en el "open()", no en los "read()" y "write()". Ello permite, por ejemplo, abrir un fichero mientras somos privilegiados, despojarnos de los privilegios y seguir escribiendo en él.
[editar]

Sé el primero en opinar


Tutoriales relacionados con '¿Cómo Escribir Programas Seguros?'

En este artículo vamos a intentar dar algunos consejos para la programación segura en C.... Más »
El objetivo de este documento es enseñar las bases de la instalación de un cortafuegos... Más »
Esta guía no es un documento general de seguridad. Esta guía está específicamente orientada a... Más »
Documento con fundamentos teóricos de control de accesos en redes telemáticas; se tratan temas como... Más »
Bienvenidos al manual de HTML de Indaya.A través de todos estos capítulos vamos a descubrir... Más »

Autor y licencia de '¿Cómo Escribir Programas Seguros?'


Tutorial de Mononeurona.org. Extraido de: http://www.mononeurona.org/index.php?idp=535 CopyLeft
Este contenido ha sido recopilado por el equipo de Wikilearning. Todo el contenido recopilado se ha obtenido respetando y comunicando en nuestro site la licencia de cada fuente.
Wikilearning tiene permiso expreso por escrito de los autores para publicar los contenidos que ha extraído de otras webs, incluyendo su uso comercial.