Enmascaramiento de datos
Quizás no pase todo el tiempo, pero quien en alguna ocasión no se ha encontrado con la necesidad de tener que enmascarar los datos que se muestran a los usuarios y mostrar, por ejemplo, jua…@…com en lugar del email real del usuario. Si llevamos esta necesidad a una base de datos veremos que hacer que para algunos usuarios (o roles) algunos datos se vean enmascarados mientras que para otros no, puede volverse una tarea compleja que involucrará desarrollo, administración y consumirá tiempo y recursos.
Lo que le da sentido a todo lo que detallaremos a continuación es que esta posibilidad se encuentra disponible en SQL Server 2016 en forma nativa y se conoce como Enmascaramiento dinámico de datos, Dynamic Data Masking o simplemente a a través de sus siglas DDM
DDM en SQL Server 2016
En este artículo vamos a comentar de que se trata todo esto y como funciona.
Para quien no haya leído nada hasta ahora sobre DDM, en este punto seguramente se estará haciendo varias preguntas, vamos entonces a ir tratando de develar de a poco y con ejemplos cada una de estas preguntas.
Sin más preámbulos, este es el momento de dejar el primer ejemplo para ir adentrándonos en el tema, vamos a comenzar creando una tabla de la siguiente forma:
CREATE TABLE dbo.Ejemplo ( Email varchar(255) NULL, Email_Mascara varchar(255) MASKED WITH (FUNCTION = 'default()') NULL ) ON [PRIMARY] GO INSERT INTO Ejemplo (Email,Email_Mascara) values ('juanperez@mailejemplo.com','juanperez@mailejemplo.com')
Viendo el código no cabe duda de que la columna Email_Mascara está siendo enmascarada (a diferencia de la columna Email que la agregamos solo para fines comparativos), seeguramente tampoco tendremos dudas de que MASKED WITH (FUNCTION = ‘default()’) es quién está definiendo que la columna se enmascarará
¿Pero qué es lo que estamos definiendo exactamente con esta declaración?
Básicamente en este ejemplo estamos declarando que la columna Email_Mascara se enmascare con un valor, ¿Con qué valor? con un valor «por defecto» que dependerá del tipo de datos de la columna a enmascarar y que está definido por SQL Server, no es de sorprender entonces que SQL Server utilice un valor determinado para cada tipo de dato, a continuación se muestra la lista completa:
- char, nchar, varchar, nvarchar, text, ntext:
XXXX o un número menor de X si el tamaño del campo es inferior a 4 caracteres - bigint, bit, decimal, int, money, numeric, smallint, smallmoney, tinyint, float, real:
0 - date, datetime2, datetime, datetimeoffset, smalldatetime, time:
01.01.2000 00:00:00.0000000 - binary, varbinary, image:
0 (ASCII)
¿Que pasará entonces al consultar la tabla recién creada?¿Que pasará con el campo enmascarado? para quien se haya hecho estas preguntas seguramente en este momento se apurará a hacer un SELECT para ver qué pasa, si lo hace se encontrará con el siguiente resultado:
¿Qué sucedió? La máscara no funcionó, esperabamos ver un XXXX en el campo enmascarado, pero el campo se vé perfectamente. Es esperable que el resultado no se entienda y es por que un detalle que había omitido hasta ahora es que la documentación de DDM define lo siguiente:
”El enmascaramiento dinámico de datos (DDM) limita la exposición de información confidencial ocultándolos a los usuarios sin privilegios”
Entonces el panorama comienza a aclararse un poco, de alguna forma SQL Server tiene que determinar cuales usuarios verán la información enmascarada y cuales no, SQL Server define que para los usuarios con privilegios esta columna funcionará como una columna convencional mientras que para usuarios sin privilegios la columna se enmascarará y como hasta ahora estábamos utilizando un usuario Owner sobre esta base de datos con el cual creamos la tabla, insertamos datos y los consultamos es claro que no vamos a ver la columna enmascarada, estamos en el caso de un usuario con privilegios.
El próximo paso será entonces utilizar un usuario sin privilegios y ver qué pasa, en nuestro caso vamos a agregar un usuario d a la base y solo le vamos a dar permisos de lectura y escritura:
Y si repetimos la consulta para nuestro usuario d veremos que la máscara definitivamente funciona:
Una segunda pregunta que podríamos hacernos es cómo será la escritura de datos cuando hay campos enmascarados involucrados para usuarios sin privilegios, entonces si intentamos modificar algunos datos con el usuario d veremos que podemos hacerlo sin problemas (ya que el usuario d tiene permisos de escritura).
También observaremos que al consultar los datos, los campos seguirán viéndose enmascarados para d aunque este usuario haya sido quien insertó o modificó estos datos que ahora no puede ver.
Para resumir, por el momento hemos visto el uso de una máscara, y como la misma se comporta en base a los privilegios del usuario que realiza las consultas, no hicimos los ejemplos para otros tipos de datos, pero los resultados que se obtendrán se corresponderán con la definición que dejamos unas líneas arriba, estoy seguro que no nos encontraremos con sorpresas con esto.
Un punto a considerar es que hay algunas restricciones para utilizar DDM, el enmascaramiento de datos dinámicos no es posible para los siguientes tipos de columnas:
- Columnas cifradas (siempre cifradas)
- FILESTREAM
- COLUMN_SET o una columna dispersa que forme parte de un conjunto de columnas.No se puede configurar una máscara en una columna calculada, pero si esta última depende de otra con una máscara, entonces la columna calculada devolverá datos enmascarados.
- Una columna con enmascaramiento de datos no puede ser una clave para un índice FULLTEXT.
Si nos sentimos satisfechos con esta funcionalidad, nos alegraremos de saber que aún hay más, si volvemos a revisar la definición de la columna enmascarada que utilizamos previamente: MASKED WITH (FUNCTION = ‘default()’) por todo lo comentado previamente, entenderemos claramente que hace allí la palabra ‘default’, pero seguramente también hayamos notado que si conjuntamente con la definición de una mascara estamos asociando una función, eso puede significar que hay más de una función que puede asociarse a la máscara y que cambiando la funcion podremos cambiar la forma en que la columna es enmascarada, esto es efectivamente así. Hasta ahora hemos utilizado la máscara conocida como DEFAULT pero existen tres tipos más: Email, Aleatorio y Cadena personalizada, veremos cada una de ellas a continuación:
Enmascarará campos de texto y les aplicará una máscara específica para emails
Definición:
......MASKED WITH (FUNCTION = 'email()')
Ejemplo:
Aleatorio
Enmascarará campos numéricos devolviendo un valor aleatorio entre un rango definido
Definición:
......MASKED WITH (FUNCTION = 'random([start range], [end range])')
Ejemplo:
Cadena personalizada
Enmascarará campos de texto, dejando sin enmascarar una cantidad de caracteres a izquierda, definida por un parámetro llamado prefijo (prefix) y una cantidad de caracteres a derecha definida por el parámetro subfijo (suffix). en la parte central el campo enmascarado se llenará con el valor pasado en el parámetro relleno(padding)
Definición:
......MASKED WITH (FUNCTION = 'partial(prefix,[padding],suffix)')
Ejemplo:
Permiso UNMASK
Previamente habíamos comentado que los usuarios con privilegios podrán ver los campos enmascarados y los usuarios sin privilegios no podrán, esto es cierto pero es una visión reducida de la realidad, SQL Server utiliza el permiso UNMASK para definir este comportamiento por lo que un administrador podría ajustarlo, para nuestros ejemplos si le damos permisos al usuario d de la siguiente forma:
GRANT UNMASK TO d
Notaremos que la máscaras sobre los campos han desaparecido para el usuario d
Consideraciones finales y conclusiones
El enmascaramiento de datos es una práctica necesaria en varios escenarios, SQL Server 2016 incluye en forma nativa varias funciones que proveen esta funcionalidad, lo que permite unificar formatos de máscaras, minimizar el esfuerzo de desarrollo, testing y asegurar que los datos enmascarados no se van a mostrar quien no se desea que los vean, pero hay que tener bien claro que esta NO es una característica de seguridad, ya que si bien con DDM podemos evitar que se muestren datos de nuestra base de datos, DDM los va a ocultar pero no los va a proteger y esto significa que algunas técnicas para intentar acceder a la información enmascarada, como por ejemplo intentar descubrir valores enmascarados a través del filtrado con WHERE y fuerza bruta van funcionar, por lo que debemos entender DDM es una característica que debe complementarse con las opciones de seguridad que proporciona SQL Server para que los datos queden resguardados, aunque de todas formas es un complemento muy bienvenido.
Espero que este artículo haya sido de utilidad o como una introducción al DDM, hasta la próxima!!!