Desarrollo del controlador de cifrado de archivos con restricción de acceso por proceso

publicado en: drivers | 0

En este artículo se describe el esquema y los detalles de aplicación de un controlador para el cifrado de archivos en vuelo basado en el enfoque del minifiltro del sistema de archivos. La solución descrita también prevé la restricción por proceso del acceso a los archivos cifrados.

Es un buen ejemplo de una solución de desarrollo que puede utilizarse para construir un sistema de protección de datos. Puede aprender más sobre las tecnologías de seguridad que Apriorit desarrolla para varios proyectos. También eche un vistazo a nuestras competencias de desarrollo de drivers.

Windows incrustó mecanismos de encriptación

Ventajas del sistema sugerido, en comparación con las soluciones estándar

EFS (Sistema de cifrado de archivos) y Bitlocker son soluciones de cifrado estándar para Windows.

BitLocker proporciona una encriptación completa de la partición a nivel de sector. El controlador de BitLocker (fvevol.sys) se encuentra debajo del controlador ntfs.sys en la pila del sistema de archivos. Cifra y descifra automáticamente los bloques de datos escritos y leídos de la unidad física por NTFS. Por lo tanto, la unidad física NTFS parece no estar cifrada, pero si se intenta leer los datos en bruto desde ella pasando por encima de NTFS, se recibirá un dato cifrado [ Win Internals 6th. Parte2, Gestión de almacenamiento, página 173 ].

Cabe señalar que la aplicación más segura de BitLocker proporciona cifrado de la manera más eficaz: utiliza el coprocesador criptográfico del Módulo de Plataforma de Confianza 1.2, que existe en muchos ordenadores personales modernos. BitLocker todavía puede funcionar en PCs sin TMP, pero requiere la conexión de una memoria flash USB para cargar el PC, o salir del modo de hibernación (en este caso la implementación no proporciona protección contra la desconexión y el reinicio) [ Win Internals 6th. Part2, Storage Management, page 164] .

Obviamente, esta solución no permite asegurar los datos del usuario de aplicaciones maliciosas, que se ejecutan en el entorno de Windows, y tampoco evita la fuga de datos al transferir entre aplicaciones y subirlos a Internet.

El Sistema de Cifrado de Archivos (EFS) es un mecanismo estándar de NTFS que proporciona cifrado para partes separadas de la unidad lógica. El EFS funciona de forma transparente para las aplicaciones. El cifrado del EFS se basa en la contraseña específica de la cuenta. Los datos se cifran y descifran automáticamente cuando se accede a ellos por las aplicaciones que se ejecutan en la sesión del usuario que tiene permiso para descifrarlos.

Por lo tanto, el EFS tampoco permite asegurar los datos del usuario de aplicaciones maliciosas, que se ejecutan en la sesión del usuario que tiene el permiso para descifrar los datos. Y este mecanismo no permite prevenir la fuga de datos mientras se suben a Internet. Para resolver este problema, es necesario desarrollar un controlador de kernel personalizado. Esto resultará en una solución que proporcione un cifrado transparente de los objetos selectivos del sistema de archivos.

De manera similar a la EFS, la solución propuesta cifrará/descifrará los datos de acceso automáticamente. Sin embargo, la ventaja de este enfoque radica en el hecho de que la protección de los datos se lleva a un nivel de sesión de usuario. Se proporciona mediante el sistema de normas que dividen los procesos en permitidos y prohibidos. Así, mientras se leen los datos en la misma sesión de usuario, algunas aplicaciones recibirán datos desencriptados y otras, encriptados.

Uso de controladores de minifiltros para el cifrado de archivos

Principio general de los conductores de los minifiltros y su conexión con las unidades

El principio operativo del sistema de cifrado de archivos basado en el controlador del minifiltro radica en el hecho de que el controlador se conecta a las particiones de sistema seleccionadas, incluidas las unidades de sistema extraíbles, y filtra/visualiza todas las operaciones en los objetos del sistema de archivos, que se encuentran en esas particiones.

Minifilter driver scheme for file encryption

Así, no importa qué operación de archivo realice una aplicación, el controlador del minifiltro la verá y podrá cambiar sus parámetros. Por ejemplo, puede bloquear la apertura de archivos o el inicio de aplicaciones; redirigir la apertura a otro archivo; cifrar/descifrar o simplemente comprobar los datos mientras los lee/escribe en el archivo.

El controlador puede guardar información específica para cada partición, y luego usarla para cada operación. Por ejemplo, esta característica puede utilizarse para establecer diferentes parámetros de cifrado para cada partición. El controlador puede utilizar una lógica diferente para cada partición del sistema.

La información específica de una partición u otro objeto del sistema de archivos se encuentra en el objeto llamado contexto .

El principio de la conexión del controlador a una partición y la arquitectura del controlador del minifiltro son funciones estándar del marco del minifiltro de Windows. Por lo tanto, estos tipos de controladores son utilizados por otro software, por ejemplo, los antivirus.

Variando los parámetros de la conexión del controlador a una partición, podemos hacer que los controladores antivirus, que también están conectados a la partición, puedan recibir datos encriptados.

Para filtrar las operaciones de los archivos, el controlador del minifiltro registra las llamadas para cada operación del sistema de archivos. Estas llamadas son llamadas por el sistema cuando se ejecuta la operación específica.

Esquema general de cifrado en minifiltros

Sin restricción de acceso por proceso

Para iniciar el desarrollo del controlador del minifiltro de cifrado, necesitamos entender el esquema general de cifrado, empleado en la solución y cómo funciona la conexión a los manejadores de lectura/escritura.

Para cifrar los datos del usuario, el conductor del minifiltro tiene que registrar los manejadores de lectura/escritura – IRP_MJ_READ y IRP_MJ_WRITE, respectivamente. Puede realizarse mediante los métodos estándar proporcionados por el marco.

Hay varios tipos de operaciones de lectura y escritura en los sistemas de archivos:

  • Lectura en caché desde un archivo – el controlador del sistema de archivos lee los datos desde la caché. Si la caché no tiene datos, el administrador de la caché lee los datos del archivo a la caché y luego devuelve los datos leídos al sistema de archivos.
  • El controlador del sistema de archivos lee los datos directamente de la unidad. Si esta operación es iniciada por el Administrador de Caché, entonces los datos se mueven a сache para el archivo, y si es iniciada por la aplicación, entonces los datos no se mueven al caché para el archivo.
  • Lectura rápida de IO – los datos se leen directamente de la caché, y no se crea IRP.
  • Los datos se escriben en la memoria intermedia en сache. El gestor de caché no garantiza que los datos se escriban en un archivo en el disco a la vez.
  • La escritura de IO de paginación – los datos se escriben directamente en el archivo de una unidad. Si esta operación es iniciada por el Administrador de la Caché, entonces la descarga tiene lugar, y si es iniciada por una aplicación, entonces los datos se escriben en el archivo y no se mueven a la caché.
  • Escritura IO rápida – los datos se escriben directamente en la caché, evitando el sistema de archivos.

El administrador de caché suele utilizar operaciones de lectura/escritura de IO de paginación para leer los datos al caché o descargar los datos del caché al archivo. Así, después de la lectura de IO de paginación, los datos se mueven al caché, y después de la escritura de IO de paginación, los datos se escriben directamente en el archivo de la unidad.

NOTA: Según la experiencia de trabajo con el minifiltro, y el controlador de filtro del sistema de archivos para el cifrado, siempre debe haber datos descifrados en la caché. De lo contrario, hay casos de uso en que la aplicación puede recibir datos cifrados y descifrados al mismo tiempo.

Por ejemplo, si hay datos cifrados en el caché y la aplicación ha realizado la asignación de archivos, entonces la aplicación se referirá directamente a la región del caché, donde se encuentran los datos del archivo. Por lo tanto, el minifiltro no recibirá y descifrará las operaciones de lectura. Para manejar este caso, se utilizan ganchos en las funciones Nt* en los controladores de filtro del sistema de archivos para la arquitectura x86. Pero este enfoque está prohibido para los sistemas Windows x64.

Después de conectarse a una partición y registrar los handlers (IRP_MJ_READ y IRP_MJ_WRITE), el driver del minifiltro ve todos los tipos de operaciones anteriores (excepto FastIO). Pero el cifrado de datos del minifiltro para cada IO de buscapersonas que se escribe desde el Administrador de caché y el descifrado para cada IO de buscapersonas que se lee desde el Administrador de caché es suficiente para implementar el cifrado de archivos transparentes comunes sin restricción de acceso por proceso.

Por lo tanto, siempre habrá datos desencriptados en todas las aplicaciones y en la caché, y siempre habrá un dato encriptado en el archivo de una unidad.

Complicación del esquema en caso de restricción de acceso por proceso

La restricción del acceso a los procesos hace más complicado el desarrollo del controlador de cifrado de archivos sobre la marcha. La seguridad de los datos de la sesión de usuario significa que sólo una gama limitada de aplicaciones tiene acceso a los datos desencriptados. Otras aplicaciones deberían recibir datos encriptados mientras intentan leerlos desde un archivo.

Así, la lógica de la encriptación/desencriptación de datos por el minifiltro se hace más complicada.

El esquema simplificado de las acciones que deben ser realizadas por el minifiltro:

  1. Lectura en caché solicitada por la aplicación bloqueada.

File system driver: cached read requests for blocked app

  1. Lectura en caché solicitada por solicitud permitida.

File system driver: cached read requests for allowed app

  1. Lectura no almacenada en caché por aplicación bloqueada.

File system driver: non-cached read requests for blocked app

  1. No se lee en caché por aplicación permitida.

File system driver: non-cached read requests for allowed app

Durante la manipulación de las operaciones en el minifiltro se determina si el proceso está permitido o bloqueado. Para ello, se puede utilizar el contexto vinculado a cada FileObject. Este contexto se crea en un manejador en la operación de abrir/crear archivo. En este momento se conoce claramente el proceso que abre el archivo de destino. La información sobre el proceso puede almacenarse en este contexto. El contexto puede ser eliminado durante la operación de cierre del FileObject.

NOTA: Hay una característica muy importante en el trabajo de Cache Manager. Es el hecho de que las operaciones de paginación IO de un archivo pueden realizarse en el contexto de cualquier proceso del sistema, incluidos los procesos que no están relacionados con el archivo. Estas operaciones suelen ser realizadas por el proceso de servicio SISTEMA. El Administrador de caché utiliza uno de los FileObjects abiertos a un archivo y todas las operaciones de Paging IO se realizan a este FileObject. En este caso, el contexto del FileObject sirve para recibir información sobre el proceso que abrió el archivo y por lo tanto trabajó con él.

Además, será importante utilizar contextos por archivo.

NOTA: Para la arquitectura de minifiltros para sistemas operativos más antiguos que Windows Vita, estos contextos se implementan mediante contextos Per-Stream.

Como se desprende del nombre, este contexto está directamente vinculado al archivo de una unidad, independientemente de la cantidad de FileObjects abiertos. Para todos los FileObjects, abiertos para el archivo específico, este contexto es el único, y puede ser recibido a través de cualquier FileObject. Este contexto será eliminado por el sistema cuando se cierre el último FileObject.

NOTA: El contexto por archivo está relacionado con la estructura FCB en el controlador de cifrado del sistema de archivos, y como esta estructura existe hasta que cualquier FileObject abierto existe, entonces el contexto también lo hace.

En este contexto se almacenará información como, por ejemplo, si el archivo está cifrado, su tamaño descifrado, el indicador de modificación del archivo y otros datos que se utilizan para la aplicación del cifrado.

Problemas con esta arquitectura de solución

El desarrollo de controladores de cifrado de archivos mediante el enfoque de minifiltros tiene una gran desventaja, que el desarrollador inexperto puede no ser consciente de ello.

Mientras se utiliza el mapeo de archivos, los procesos a los que se les prohíbe descifrar el archivo siguen teniendo acceso a los datos descifrados de este archivo. Esto sucede porque en caso de mapeo de archivos la aplicación obtiene acceso directamente a la sección del caché, donde está la vista del archivo. Así pues, el minifiltro no puede detectar las operaciones de mapeo de archivos. Sin hacer cambios en la arquitectura de la solución de cifrado, este problema puede resolverse utilizando los ganchos de las funciones de mapeo de archivos. En el SO x64, sólo pueden ser ganchos en modo de usuario. Este enfoque implica procesos, y no es nativo y conduce a un gran número de posibles problemas de aplicación, que son muy difíciles de prever. Se está complicando por la imperfección de los motores de gancho disponibles por ahora y la necesidad de considerar una enorme cantidad de matices con la implementación de ganchos.

La solución más nativa para un sistema operativo (en términos de diseño) utiliza un controlador de minifiltro personalizado junto con un controlador de sistema de archivos personalizado.

Concepto: dos vistas del archivo encriptado, caches de encriptación y desencriptación para el mismo

Principio general de participación de la caché en la labor de una aplicación

Cuando la aplicación lee los datos del archivo, en el caso de la lectura regular en caché, estos datos son tomados de un caché por el sistema de archivos. Si no hay datos de destino en el caché, entonces al principio estos datos se colocan en el caché, y luego el sistema de archivos los devuelve a la aplicación. En el caso de la escritura normal en caché, los datos son escritos en el caché por el sistema de archivos, y luego en algún momento el Administrador de Caché envía estos datos a la unidad.

Cuando una aplicación utiliza el mapeo de archivos para trabajar con el archivo, obtiene acceso directamente a las secciones de la caché, donde se encuentra la vista de este archivo. Otra aplicación puede abrir este archivo en el mismo momento y realizar operaciones de caché con él. En este caso, ambas aplicaciones tienen acceso a la misma vista del archivo en la caché. Así pues, si una aplicación está permitida y otra no, la prohibida también tendrá acceso a los datos desencriptados. Puede evitar la fuga de datos utilizando los ganchos de modo de usuario, como se ha mencionado anteriormente. En los ganchos es necesario implementar una lógica particular para las aplicaciones prohibidas que trabajan con el mapeo de archivos. Esta lógica asignará su sección de memoria y colocará allí los datos cifrados, y luego devolverá esta sección a la aplicación.

División de caché para aplicaciones permitidas y prohibidas

Es posible otra arquitectura, en la que la vista de los archivos de las aplicaciones permitidas y prohibidas se divide en dos vistas separadas para cada uno de los tipos de aplicaciones. Sólo es posible si una vista coincide con un archivo de la unidad y otra con otro archivo. Por lo tanto, deben existir dos archivos diferentes, pero todas las aplicaciones deben ver sólo un archivo en su ubicación original. En el caso de las aplicaciones permitidas, todas las solicitudes deben redirigirse a otro archivo (desencriptado), que se encuentra en otra parte de la unidad.

Diagram of minifilter driver logic

Diagrama. No hay redireccionamiento al archivo desencriptado para aplicación prohibida

Diagram of minifilter driver logic

Diagrama. Redirección de operaciones a un archivo desencriptado para la aplicación permitida

En la arquitectura del sistema operativo Windows, la redirección «invisible» de las solicitudes de un archivo a otro se implementa mediante controladores de minifiltros. En este enfoque, el controlador del minifiltro intercepta una operación específica y la redirige «invisiblemente» a otro archivo. Sin embargo, por motivos de seguridad de los datos, es inaceptable almacenar un archivo desencriptado en una unidad. Por ello, este archivo puede almacenarse en la unidad de forma cifrada y ser descifrado durante las operaciones de lectura/escritura.

Almacenar dos archivos idénticos es extremadamente inconveniente, porque estos dos archivos deben sincronizarse constantemente, y el usuario puede simplemente eliminar el archivo confundiéndolo con un duplicado del archivo original, o simplemente con un archivo desconocido.

Es posible eliminar la necesidad de utilizar el segundo archivo de la unidad añadiendo un controlador especial de sistema de archivos a la arquitectura de la solución. Este controlador se monta como una unidad local separada ordinaria y se comporta en consecuencia: muestra los archivos y permite acceder a ellos. Pero es una unidad lógica virtual, por lo que lee archivos de cualquier otro catálogo en otra unidad local. En esta arquitectura de la solución, este controlador accede al archivo de usuario original encriptado de la unidad. La palabra «acceso» significa que el controlador muestra este archivo en su unidad local, y para cada operación de archivo realiza la misma al archivo original. Pero en este caso, el controlador descifrará y cifrará las operaciones de lectura/escritura al archivo original. Por lo tanto, si una aplicación fuera redirigida a este controlador, recibiría datos descifrados de los archivos que muestra este controlador.

File system driver: redirection

Diagrama. Redirección del acceso al archivo original al controlador del sistema de archivos

Implementación de la idea: controlador de redireccionamiento + controlador de sistema de archivos virtual

Como se muestra en el diagrama, el controlador del minifiltro, que redirige accesos específicos a los archivos, y el controlador del sistema de archivos, que recibe las redirecciones, deberían utilizarse para poner en práctica la idea. Resulta que, cuando la aplicación accede a cualquier archivo, esta operación puede ser redirigida «implícitamente» a otro archivo.

Qué es la redirección y cómo funciona

Antes de realizar las operaciones de lectura/escritura, es necesario abrir primero el archivo. La redirección del acceso al archivo consiste en lo siguiente: el controlador del minifiltro visualiza las operaciones de apertura del archivo y las redirecciona a otro archivo mediante mecanismos estándar para los filtros del sistema de archivos. A continuación, todas las demás operaciones de la sesión de apertura y cierre de archivos se realizan automáticamente con el archivo al que se ha redirigido y, por lo tanto, se realizan a través del controlador del sistema de archivos al que se ha redirigido.

Tareas de redireccionamiento

El redactor debe interceptar las operaciones de archivos abiertos y detectar si este archivo está cifrado y si la aplicación puede descifrarlo.

Si el archivo está cifrado y se permite que una aplicación lo descifre, el controlador de redireccionamiento redirige el archivo que se abre al controlador del sistema de archivos.

Tareas del conductor del FS

El controlador de FS proporciona características estándar del sistema de archivos, aunque no trabaja directamente con los datos de una unidad física, sino que lee y escribe datos en otro archivo de cualquier otra partición. Esto significa que, a través de la API estándar para trabajar con archivos en modo de kernel, el controlador de FS realiza operaciones de archivo recibidas de la aplicación con ese archivo. Este controlador es un dispositivo de volumen virtual, por lo que debe montarse como un dispositivo de volumen. Sin embargo, el controlador no debería asignar una letra de unidad al dispositivo de volumen, por lo que el usuario no podría tener un acceso directo a este volumen desde las aplicaciones.

El controlador debería mostrar el archivo desencriptado a la aplicación, por lo tanto, se debería implementar en él una lógica que desencripte/encripte los datos durante la lectura/escritura a archivo y permita mostrar el archivo de tamaño correcto a la aplicación.

Mostrar un tamaño de archivo correcto es una característica importante de este controlador, porque el tamaño del archivo cifrado puede diferir del tamaño del descifrado.

NOTA: Para un manejo más fácil del archivo cifrado, se suele añadir un encabezado. Esto resulta en la necesidad de control de sesgo durante operaciones de lectura/escritura al archivo cifrado en el controlador.

Algunas ideas sobre una implementación del controlador del sistema de archivos.

Construir un conductor en base a FASTFAT

WDK proporciona ejemplos de desarrollo de controladores de sistemas de archivos de encriptación utilizando FASTFAT. Este controlador puede convertirse en la base del controlador de la arquitectura de la solución del sistema de archivos descrito anteriormente.

Es necesario dejar en el controlador la capa de gestión de los objetos lógicos de FS (estructuras FCB, CCB), así como la caché, el acceso compartido al archivo y la gestión de OpLocks. Se debe eliminar la capa que gestiona los archivos y directorios de datos directamente en la unidad física, todo lo relativo al dirent, y todas las operaciones del driver enviadas a los dispositivos que se encuentran debajo de ella en la pila del sistema de archivos.

Dado que el controlador recopila datos de otro archivo de la unidad lógica, debe incluir una lógica que abra este archivo cuando la solicitud de apertura provenga de la aplicación y lo mantenga abierto hasta que la solicitud de cierre llegue al controlador.

Según la regla «el controlador debe mostrar el archivo desencriptado», se debe agregar la siguiente lógica al controlador:

  • cifrado/descifrado de datos durante operaciones de lectura/escritura no almacenadas en caché;
  • durante las operaciones de especificación y obtención del tamaño del archivo, corrigiendo el tamaño para que el controlador especifique el tamaño de los datos cifrados como el tamaño del archivo, y devuelva el tamaño de los datos descifrados.

Para que esta unidad lógica sea inaccesible para otras aplicaciones, no debe informar al Mount Manager sobre el dispositivo durante su montaje.

El controlador de redireccionamiento necesita conocer la ruta nativa оf del dispositivo de volumen para poder redirigir las operaciones a la unidad lógica virtual. Por eso el controlador del sistema de archivos debe informar al controlador del redirector sobre esta ruta. Para ello, es necesario crear un dispositivo de control en el controlador del sistema de archivos, a través del cual sería posible solicitar el nombre.

Mejora: sistema de archivos en modo de usuario

El controlador del sistema de archivos puede mejorarse para que el procesamiento de cada operación solicitada se realice en el servicio de modo de usuario. Para ello, los comandos que contienen parámetros y resultados de retorno deben ser enviados entre el servicio y el controlador.

NOTA: este intercambio de datos puede organizarse mediante el mecanismo del Modelo de Llamada Invertida que está bien descrito por la OSR. Mediante este mecanismo, en cada operación del sistema de archivos, que proviene de una aplicación, el conductor envía al servicio un comando específico correspondiente a esta operación. Junto con este comando, el controlador enviará todos estos parámetros de operación y esperará a que el servicio devuelva los resultados. Entonces el controlador enviará este resultado como resultado del procesamiento de la operación solicitada por una aplicación. Utilizando todos los parámetros de la operación, que fueron enviados por el conductor, el servicio realiza las acciones necesarias y devuelve el resultado al conductor. Esta arquitectura es análoga a FUSE, que se utiliza en sistemas de tipo Unix.

Esa mejora permite pasar todas las operaciones de procesamiento al modo de usuario y evitar el desarrollo del código del núcleo. Esto hace que el cambio de la lógica de procesamiento de operaciones sea más flexible y rápido.

La mejora también permite:

  • utilizando las bibliotecas de cifrado liberadas;
  • almacenando las claves en servidores protegidos;
  • validación de firmas digitales;
  • usando la interfaz gráfica;
  • usando diferentes lenguajes de programación;
  • trayendo la lógica a la dll y actualizándola sin reiniciar el sistema;
  • almacenando archivos en almacenes de nubes.

Por lo tanto, todas las oportunidades posibles que tienen las aplicaciones en modo de usuario se dejan abiertas.

Echa un vistazo a un tutorial sobre los controladores del filtro del sistema de archivos en nuestro blog.

Lea un tutorial sobre el Disco Virtual para Windows y obtenga las fuentes del código.

Aprenda sobre las tecnologías Apriorit listas para integrar: SDK de encriptación de archivos sobre la marcha

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *