Protegiendo las bases de datos contra accesos no autorizados

Deja un comentario

Una de las mayores preocupaciones de quienes guardan datos sensibles en bases de datos es acerca de la seguridad con que se cuenta para evitar el acceso no autorizado. Entonces ¿qué podemos decir sobre este tema?

Primero, y fundamental, que la seguridad implica tomar muchas medidas de precaución, no solamente una.

La seguridad de una Base de Datos no debe estar basada en nombres de usuarios y en contraseñas. Realmente en Firebird el intruso solamente debe conocer la contraseña del usuario SYSDBA y ya podrá hacer lo que se le antoje.

Creer que la contraseña lo es todo en cuanto a seguridad, es un gran error.

¿Por qué?

Porque el elemento más débil en la seguridad, no es la contraseña sino que es … el usuario humano.

Si el usuario permite que le vean el teclado mientras escribe la contraseña … murió la seguridad

Si el usuario escribe la contraseña en un papel que otros pueden ver … murió la seguridad

Si el usuario le dice a otra persona cual es su contraseña … murió la seguridad

Si el usuario elige una contraseña fácil de descubrir … murió la seguridad

Si el intruso puede copiar la Base de Datos en un pen-drive … murió la seguridad

Explicación:

Si alguien puede ver tu teclado mientras estás escribiendo la contraseña del usuario SYSDBA entonces te puede estar filmando (quizás a una distancia prudencial), con cualquier teléfono celular (móvil) o con esas minicámaras que se disimulan en bolígrafos, relojes, u otros aparatos. Luego, simplemente reproduce la filmación y podrá descubrir cuales teclas presionaste, y en que orden lo hiciste. Y listo, ya conoce la contraseña.

Si escribes la contraseña en un papel, archivo de texto, planilla Excel, o cualquier otro lugar donde alguien más puede leerlo, entonces ya la consiguió. Hay gente que se inventa una contraseña muy complicada, y para no olvidarla, la anota en un papel que deja en el primer cajón de su escritorio. Algo como: “contraseña de SYSDBA = euldlm67”

Mujeres sexies que actuaron de espías hay varias en la Historia, quizás la más conocida haya sido Mata Hari, quien se acostaba con los jefes del ejército enemigo para sacarles información. En una noche de juerga, sexo y borrachera, lo que menos le importará a un fulano es contarle cual es la contraseña del usuario SYSDBA a su amante. Estos casos, aunque no involucren sexo, se conocen como “Ingeniería Social” donde a la víctima se le quita información usando la psicología. Diciéndolo lo importante que es, o algunas otras frases se lo dispone a compartir esa contraseña que debería mantener en secreto.

Hay contraseñas que son muy fáciles de descubrir, entre ellas tenemos a: “123456”, “1234567”, “12345678”, “admin”, “supervisor”, “root” y unas 50 más, que son ampliamente utilizadas por una gran cantidad de personas. Cualquier aprendiz de hacker sabe que debe empezar a intentar acceder con ellas, pues muchas personas las utilizan. Si se conocen algunos datos del usuario eso también puede facilitar la obtención de la contraseña. Por ejemplo, en las mujeres es muy frecuente que usen el nombre del novio, del perro, o del hijo. En los hombres, el club de fútbol, un jugador famoso, un personaje de historieta o de ficción. Entonces, usando “Ingeniería Social” se averiguan esos nombres y listo.

Cambiando la contraseña del usuario

Sabiendo que el eslabón más débil es el usuario porque muchos no entienden la importancia de mantener la contraseña en absoluto secreto, hay que tratar de disminuir la probabilidad de que si la comunican a otra persona, por accidente o por intención, el intruso pueda conectarse a la Base de Datos.

Un método, que no es infalible pero ayuda a aumentar la seguridad es el siguiente:

  • En las aplicaciones (Contabilidad, Ventas, Producción, Sueldos, etc.) jamás se debe permitir que ingrese el usuario SYSDBA
  • En las aplicaciones (Contabilidad, Ventas, Producción, Sueldos, etc.) jamás debe permitirse que ingrese un usuario con el rol RDB$ADMIN, pues en esa Base de Datos tendrá los mismos privilegios que el usuario SYSDBA
  • La aplicación debe verificar que el usuario no sea SYSDBA y que el rol utilizado no sea RDB$ADMIN
  • Las tareas administrativas de la Base de Datos que requieren del usuario SYSDBA o de un usuario con el rol RDB$ADMIN (backup, sweep, etc.) deben realizarse a través de una aplicación diseñada para ese efecto. Nada de hacerlas en la línea de comando.
  • La contraseña que el usuario introduce en esa aplicación jamás debe ser la contraseña verdadera del usuario SYSDBA o del usuario que tiene el rol RDB$ADMIN. La aplicación debe transformar la contraseña introducida por el usuario en otra contraseña, en la verdadera contraseña. Esto es muy fácil de hacer, por ejemplo si se reemplaza cada carácter de la contraseña por el siguiente, se convertirá a “12345678” en “23456789”. La contraseña que introduce el usuario es “12345678”, la verdadera contraseña es “23456789”. Si el idiota del usuario le comunica su contraseña a otra persona, y esta otra persona quiere conectarse desde la línea de comandos como SYSDBA con la contraseña “12345678” (que es la que el usuario conoce y utiliza) no lo conseguirá, porque esa no es la verdadera contraseña. Esa es la contraseña que introduce en la aplicación, pero no es la contraseña requerida para realizar la conexión. Desde luego que el algoritmo utilizado para cambiar la contraseña no debe ser tan simple como el de este ejemplo. Un buen algoritmo puede convertir a “12345678” en algo como “X&9_7sxÇ”

Protegiendo una Base de Datos:

En entornos donde la seguridad es importante, las medidas de protección mínimas son las siguientes:

  1. La computadora donde se encuentra el Servidor no debe tener puertos USB habilitados ni grabador de CD/DVD
  2. La computadora donde se encuentra el Servidor no debe tener acceso directo a Internet
  3. La computadora donde se encuentra el Servidor debe encontrarse en una habitación aparte, la cual normalmente se encuentra cerrada con llave, y esa llave se guarda en un lugar seguro
  4. La conexión a la Base de Datos se hace siempre con alias
  5. Se registra en un archivo de log, que se guarda afuera de la Base de Datos, los datos de cada conexión: usuario, IP de su computadora, fecha de entrada, hora de entrada, fecha de salida, hora de salida
  6. Se restringe el acceso a la Base de Datos fuera de los días y horarios establecidos
  7. La contraseña que escribe el usuario en la aplicación, nunca debe ser la usada para la conexión sino que debe sometérsela a algún algoritmo que la convierta en la contraseña correcta. Un ejemplo muy sencillo: si en la aplicación el usuario escribe la contraseña “12345678” una función debe convertirla en “23456789”, que es la contraseña reconocida por la Base de Datos. De esa manera, si alguien conoce la contraseña del usuario y quiere acceder a la Base de Datos desde afuera de la aplicación no lo conseguirá porque estará intentando la conexión con una contraseña que no es la correcta.

Conclusión:

Si queremos tener bases de datos seguras lo más importante es siempre concientizar a los usuarios sobre la gran importancia de mantener el acceso restringido y que nunca deben comunicar sus contraseñas a otras personas, por ningún motivo.

Pero tipos que no entenderán aunque se les repita mil veces siempre existirán, por lo tanto no debemos confiar en la gente sino que debemos preocuparnos nosotros mismos de ese aspecto.

La seguridad jamás debe estar basada solamente en contraseñas, porque no es el punto más débil. El punto más débil siempre son los usuarios descuidados, negligentes, ignorantes, o indolentes. Ante gente así, ni el mejor algoritmo de encriptación del mundo servirá de algo.

Un método para mejorar la seguridad que proporcionan las contraseñas es convertir la contraseña introducida por el usuario en otra contraseña, que es la correcta para realizar la conexión.

Artículos relacionados:

Una técnica para dificultar el acceso no autorizado

Inferencia de datos

Impidiendo la conexión a una Base de Datos

Atacando a una Base de Datos: SQL injection

Evitando que los mirones averigüen nuestro password en ISQL

El índice del blog Firebird21

El foro del blog Firebird21

¿Cuáles usuarios tienen el rol RDB$ADMIN?

Deja un comentario

Como seguramente sabes, si un usuario tiene el rol RDB$ADMIN en una Base de Datos entonces en esa Base de Datos puede hacer de todo, exactamente igual a que si fuera el usuario SYSDBA o el creador de la Base de Datos.

Por lo tanto, a veces puede ser importante responder a la pregunta: ¿Quiénes tienen el rol RDB$ADMIN en esta Base de Datos?

El siguiente SELECT te lo dirá:

SELECT
   *
FROM
   RDB$USER_PRIVILEGES
WHERE 
   RDB$RELATION_NAME = 'RDB$ADMIN';

Como puedes ver, esa información la extraemos de la tabla RDB$USER_PRIVILEGES pues es en esa tabla donde se guardan todos los privilegios (derechos, permisos) que tiene cada usuario. Obtendremos algo similar a esto:

ADMIN1

Captura 1. Si haces clic en la imagen la verás más grande

Entonces, en esta Base de Datos, hay 3 usuarios que pueden conectarse con el rol RDB$ADMIN, ellos son: WOJEDAR, FATIMA y PRUEBA.

Artículos relacionados:

Derechos que poseen los usuarios de la Base de Datos

El índice del blog Firebird21

El foro del blog Firebird21

 

Algo más sobre GRANT y ROLE

2 comentarios

Los conceptos sobre GRANT y sobre ROLE pueden ser un poco difíciles de entender para quienes nunca los habían usado, así que con este artículo trataré de aclarar algunos conceptos y dudas que se puedan tener:

  1. Cuando un usuario consigue conectarse a la Base de Datos eso significa que tanto su nombre como su contraseña están reconocidos por el Firebird.
  2. Sin embargo, el hecho de haberse conseguido conectar no implica que pueda ejecutar exitosamente algún comando. Si no tiene derechos (permisos, privilegios) en esa Base de Datos entonces todos sus intentos fallarán. Ni siquiera podrá hacer un SELECT.
  3. Para que el usuario pueda ejecutar exitosamente algún comando, alguien previamente tuvo que haberle otorgado ese derecho (permiso, privilegio).
  4. Ese “alguien” que le otorgó el derecho puede ser el usuario SYSDBA, el creador de la Base de Datos, o un usuario que tiene el rol RDB$ADMIN con la opción de otorgar derechos, nadie más.
  5. Un rol es un grupo de usuarios. Los derechos (permisos, privilegios) que se otorgan a un rol automáticamente se otorgan a todos los usuarios que se conectan usando ese rol
  6. Para que un usuario pertenezca a un rol otro usuario debió haberlo hecho miembro de ese rol. Ese “otro usuario” puede ser SYSDBA, el creador de la Base de Datos o un usuario que tiene el rol RDB$ADMIN con la opción de otorgar derechos, nadie más.
  7. Cuando un usuario se conecta a la Base de Datos puede hacerlo especificando un rol o sin especificar un rol.
  8. Si se conecta sin especificar un rol, entonces tendrá solamente los derechos que a él específicamente se le hayan otorgado
  9. Si se conecta especificando un rol entonces tendrá todos los derechos que se le otorgaron específicamente a él más todos los derechos que tiene ese rol
  10. Un usuario puede pertenecer a muchísimos roles pero cuando se conecta solamente puede elegir uno de ellos y solamente tendrá los derechos que le corresponden a ese rol.

Ejemplo:

Al usuario JUAN se le otorgó el derecho de hacer SELECT a la tabla CLIENTES.

Al rol R_CONTABILIDAD se le otorgó el derecho de hacer SELECT a la tabla VENTAS.

Al usuario JUAN se lo hizo miembro del rol R_CONTABILIDAD.

Si el usuario JUAN se conecta sin especificar un rol, entonces podrá hacer SELECT a la tabla CLIENTES pero no a la tabla VENTAS.

Si el usuario JUAN se conecta especificando el rol R_CONTABILIDAD entonces podrá hacer SELECT a la tabla CLIENTES y también a la tabla VENTAS.

El usuario JUAN no podrá hacer SELECT a la tabla COMPRAS porque ni a él ni al rol R_CONTABILIDAD se le otorgó el derecho de hacerle un SELECT a esa tabla. Si más adelante a él o al rol R_CONTABILIDAD se le otorga el derecho de SELECT a la tabla COMPRAS entonces cuando vuelva a conectarse podrá hacer el SELECT, pero mientras tanto le será imposible.

Recuerda:

Un rol es un grupo de usuarios, si varios usuarios necesitan tener los mismos derechos entonces ahorrarás mucho tiempo creando un rol con esos derechos y luego otorgándole ese rol a cada usuario. Si no creas un rol entonces podrías olvidarte de asignarle un derecho a un usuario y además escribirás mucho más y en consecuencia perderás mucho tiempo.

Muy importante:

En general, por motivos de seguridad, lo recomendable es que no se otorguen derechos específicos a los usuarios sino a los roles. De esta manera si un usuario se conecta sin especificar un rol nada podrá hacer en la Base de Datos, ni siquiera un SELECT. Por lo tanto, siempre deberá conectarse usando un rol y en ese caso solamente tendrá los derechos (permisos, privilegios) que se le hayan otorgado al rol con el cual se conectó.

Artículos relacionados:

Entendiendo los derechos de acceso

Otorgando permisos con EMS SQL Manager

Delegando el otorgamiento de derechos

Un stored procedure para otorgarle TODOS los derechos a un usuario

El índice del blog Firebird21

 

Atacando a una Base de Datos: SQL injection

6 comentarios

Las bases de datos siempre se encuentran expuestas a ser atacadas por personas mal intencionadas. Eso le puede ocurrir tanto a una Base de Datos que se encuentra en una red local como a una Base de Datos que se encuentra en una red remota, como Internet, por ejemplo. En este último caso el peligro es mucho mayor porque el atacante puede estar en la otra mitad del mundo y aunque lo descubramos no se podrá tomar medidas punitivas contra él. En cambio, si el atacante es un empleado de nuestra propia empresa siempre de alguna forma se le podrá castigar.

Nuestra tarea, por supuesto, es evitar que los ataques tengan éxito. Para ello debemos proteger a la Base de Datos lo más que podamos. A veces nuestros esfuerzos serán insuficientes pero en general los atacantes desistirán de continuar con sus ataques si se dan cuenta que se enfrentan a una Base de Datos que está muy protegida.

Una forma común de atacarla es a través de un método llamado en inglés “SQL injection”.

¿Qué significa “SQL injection”?

Que al comando SQL se le está agregando algo, se le está inyectando algo. Un código que no debería estar. Ese código adicional que agregó el atacante es el que nos causará problemas.

Ejemplo 1. Un ataque trivial de SQL injection

Supongamos que tenemos un sitio web para vender productos en línea. Los visitantes de nuestro sitio web pueden escribir el código del producto que les interesa conocer características y precios.

Todo bien hasta ahí, ¿verdad?

Quizás no, si no tomamos las debidas precauciones puede ser muy vulnerable.

En nuestra página web tenemos un campo de texto donde el visitante escribirá el código del producto que le interesa y un botón “submit” que usará para enviar su solicitud. En nuestro programa escribimos algo así:

lcComando = '''SELECT * FROM PRODUCTOS WHERE PRD_CODIGO = ' || lcCodigo || ';'''

Un vistitante normal podría querer conocer las características y precios del producto que tiene código 127 y entonces nuestro comando quedaría como:

lcComando = 'SELECT * FROM PRODUCTOS WHERE PRD_CODIGO = 127';

Y estaría perfecto, en condiciones normales no tendríamos problemas. Pero un visitante malintencionado podría escribir algo como:

127 or 1=1

 con lo cual, nuestro comando quedaría como:

lcComando = 'SELECT * FROM PRODUCTOS WHERE PRD_CODIGO = 127 or 1=1';

¡¡¡CUIDADO!!! esa condición SIEMPRE será verdadera porque SIEMPRE tendremos que 1 es igual a 1.

En este caso el atacante podrá ver las características y precios no solamente del producto cuyo código es 127 sino de TODOS los productos que tenemos en nuestra Base de Datos.

¿No importa que los vea, están para ser vistos?

Quizás en el caso de los productos no importe, pero en otros casos sí podría importar.

Ejemplo 2. Un ataque peligroso de SQL injection

El Ejemplo 1. mostró el concepto pero no era peligroso porque el atacante solamente vio datos, no modificó ni borró algo, entonces en muchos casos sería algo trivial y no muy preocupante. Pero el atacante sí puede borrar algo, si escribe:

127;DELETE FROM PRODUCTOS

porque en ese caso nuestro comando quedaría así:

lcComando = 'SELECT * FROM PRODUCTOS WHERE PRD_CODIGO = 127;DELETE FROM PRODUCTOS';

 ¿Y qué hará el Firebird en ese caso?

Pues ignorará al primer comando (o sea, el SELECT) y ejecutará el segundo comando (o sea el DELETE).

Y ahora, lo que hizo el atacante es MUY PELIGROSO porque borró todas las filas de nuestra tabla llamada PRODUCTOS.

Detectando si el ataque tuvo éxito

¿Y cómo puede saber el atacante si su ataque tuvo éxito?

Pues simplemente escribiendo el código de un producto que debía existir, por ejemplo el 127, con lo cual nuestro comando quedaría así:

lcComando = 'SELECT * FROM PRODUCTOS WHERE PRD_CODIGO = 127';

Si el atacante escribió 127 antes de lanzar el ataque y recibió datos, y luego de lanzar el ataque vuelve a escribir 127 y no recibe datos entonces puede estar 100% seguro de que su ataque tuvo éxito.

Claro, para eso tendría que saber que la tabla se llama PRODUCTOS, si la tabla tiene otro nombre evidentemente su ataque no funcionó. ¿Y qué puede hacer en ese caso? Pues probar con otros nombres similares, tales como: PROD, PRODS, PRODUCTO, PRODUCTS, ARTICULOS, ARTICLES, ARTICS, ARTS, etc.

Si alguna vez al enviar el código 127 no recibe datos entonces sabrá (al menos) cuatro cosas:

  1. El nombre de la tabla
  2. Que su ataque tuvo éxito
  3. Que el diseñador del sitio web no se preocupó por la seguridad
  4. Que puede continuar atacando a esa Base de Datos porque no está protegida

Ahora que ya borró todas las filas de la tabla PRODUCTOS puede continuar escribiendo otros comandos similares, tales como:

DELETE FROM CLIENTES
DELETE FROM PROVEEDORES
DELETE FROM USERS
DELETE FROM USUARIOS
DELETE FROM VENTAS
DROP CLIENTES
DROP PROVEEDORES
DROP VENTAS
etc.

En estos casos, no podrá saber si su ataque tuvo éxito o no, pero si escribe muchísimos comandos DELETE es muy probable que algunos de ellos sí borren todas las filas de algunas tablas.

¿Cómo evitamos los ataques de SQL injection?

Ya sabemos como la Base de Datos puede ser atacada, ¿cómo la defendemos?

  1. Validando que el visitante no introduzca espacios en blanco
  2. Validando que el visitante no introduzca puntos y comas
  3. Validando que el visitante solamente introduzca dígitos (0 .. 9)
  4. Validando que el visitante no introduzca la palabra DELETE
  5. Validando que el visitante no introduzca la palabra MODIFY
  6. Validando que el visitante no introduzca la palabra DROP
  7. Validando que la longitud de nuestra variable (llamada lcComando en estos ejemplos) no sea mayor que la predeterminada. Si nuestros códigos tienen un máximo de 4 dígitos entonces la longitud de lcComando nunca debería ser mayor que 47 (en nuestros ejemplos, claro).

Entonces, en nuestro stored procedure (o en el código fuente de nuestro lenguaje de programación) deberíamos escribir algo como:

IF (POSITION('DROP' IN lcComando) > 0) THEN BEGIN
-- ERROR, no se debe ejecutar el comando, la Base de Datos fue atacada.
END

Conclusión:

Todas las bases de datos pueden ser atacadas y como puedes ver es demasiado fácil hacerlo, ni siquiera se necesita de un programa que ayude. Aquí hemos visto algunos de los muchos métodos que pueden usar los atacantes. Mi objetivo no es enseñarte a atacar bases de datos sino mostrarte que son muy vulnerables y que si no las proteges entonces pueden ser facilmente destruidas.

Nunca debes confiar en que tu Base de Datos no será atacada porque no tiene algo interesante o de valor, muchos las atacan por diversión, porque lo toman como un juego, para pasar un buen rato, desafiando a sus amigos quienes realizan más ataques, cosas así. A muchos ni les interesa el contenido, solamente les resulta divertido hacerlo. Pero para tí puede ser un perjuicio enorme. Así que, mucho cuidado.

Artículo relacionado:

El índice del blog Firebird21

 

Impidiendo la conexión a una Base de Datos

4 comentarios

En ocasiones queremos evitar que un usuario, un proceso o una computadora se conecten a nuestra Base de Datos. O varios usuarios, varios procesos o varias computadoras.

Ya habíamos visto algunos artículos sobre este tema:

Como evitar que se conecten a una Base de Datos

Evitando que un usuario se conecte más de una vez a la Base de Datos

Evitando que un usuario se conecte más de una vez (método mejorado)

En el presente artículo nos explayaremos más sobre como evitar las conexiones indeseadas.

A partir del Firebird 2.1 podemos usar los llamados triggers de las bases de datos (database triggers, en inglés) y nos servirán perfectamente para lo que pretendemos lograr.

El primer paso es crear una excepción, la cual mostrará un mensaje al usuario. En realidad esto no es obligatorio, podríamos dejar que el Firebird muestre su mensaje por defecto pero ese mensaje estará en inglés. Si queremos personalizar el mensaje entonces deberemos crear una excepción, como la siguiente:

CREATE EXCEPTION
   E_ACCESO_NO_PERMITIDO 'No tienes permiso para conectarte a esta Base de Datos' ;

A continuación crearemos los triggers de bases de datos que necesitaremos:

Un trigger para evitar que los usuarios se conecten a la Base de Datos:

Listado 1.

CREATE TRIGGER NEW_DBTRIGGER_C
   ACTIVE ON CONNECT
   POSITION 2
AS
BEGIN

   IF (CURRENT_USER IN ('JUAN', 'MARIA', 'ESTELA','MONICA')) THEN
      EXCEPTION E_ACCESO_NO_PERMITIDO;

END;

Ningún usuario cuyo nombre esté dentro del IN (en este caso: JUAN, MARIA, ESTELA y MONICA) podrá conectarse a la Base de Datos.

Un trigger para evitar que los programas se conecten a la Base de Datos:

Listado 2.

CREATE TRIGGER NEW_DBTRIGGER_C1
   ACTIVE ON CONNECT
   POSITION 3
AS
BEGIN

   IF (EXISTS(SELECT
                 *
              FROM
                 MON$ATTACHMENTS M
              WHERE
                 M.MON$ATTACHMENT_ID = CURRENT_CONNECTION AND
                (NOT M.MON$REMOTE_PROCESS IN ('MI_PROG1.EXE', 'MI_PROG2.EXE')))) THEN
      EXCEPTION E_ACCESO_NO_PERMITIDO;

END;

En este caso solamente permitiremos el acceso a los programas cuyos nombres se encuentren en el IN, o sea: MI_PROG1.EXE y MI_PROG2.EXE. Evidentemente que tú escribirías allí los nombres de tus propios programas.

¿Cuál es el defecto que tiene esta protección? Que si el intruso sabe que MI_PROG1.EXE puede conectarse entonces podría renombrar a su propio programa como MI_PROG1.EXE y así conseguirá la conexión. Por eso siempre es importante que los mensajes de las excepciones le den al intruso muy poca información. Sería muy mala idea que el mensaje sea algo como: “Solamente se pueden conectar MI_PROG1.EXE y MI_PROG2.EXE” porque en ese caso lo primero que se le ocurrirá al intruso será renombrar a su programa y conseguirá conectarse. Además, hay que tomar en cuenta otro aspecto: no se debe impedir el acceso a los programas legítimos que podamos necesitar, como: GBAK.EXE

Un trigger para evitar que desde una computadora se conecten a la Base de Datos:

Listado 3.

CREATE TRIGGER NEW_DBTRIGGER_C2
   ACTIVE ON CONNECT
   POSITION 4
AS
BEGIN

   IF (EXISTS(SELECT
                 1
              FROM
                 MON$ATTACHMENTS M
              WHERE
                 M.MON$ATTACHMENT_ID = CURRENT_CONNECTION AND
                 M.MON$REMOTE_ADDRESS IN ('192.168.0.100', '192.168.0.104'))) THEN
      EXCEPTION E_ACCESO_NO_PERMITIDO;

END;

En este caso, las computadoras cuyos IP son 192.168.0.100 ó 192.168.0.104 jamás podrán conectarse a nuestra Base de Datos, siempre se les rechazarán todos los intentos de conexión.

Un trigger para evitar que desde una subred se conecten a la Base de Datos:

Listado 4.

A veces queremos que se rechace la conexión desde toda una subred y escribir todos los IP después del IN como se mostró en el ejemplo anterior sería muy largo y muy tedioso. Para esos casos tenemos una mucha mejor alternativa:


CREATE TRIGGER NEW_DBTRIGGER_C3
   ACTIVE ON CONNECT
   POSITION 4
AS
BEGIN

   IF (EXISTS(SELECT
                 1
              FROM
                 MON$ATTACHMENTS M
              WHERE
                 M.MON$ATTACHMENT_ID = CURRENT_CONNECTION AND
                 M.MON$REMOTE_ADDRESS STARTING WITH '192.168.14')) THEN
      EXCEPTION E_ACCESO_NO_PERMITIDO;

END;

Aquí estamos rechazando las conexiones de todas las computadoras de la subred 192.168.14, o en otras palabras cualquier computadora cuyo IP empiece con esos números será rechazada. Esto puede ser muy útil cuando por ejemplo tenemos una Base de Datos para los sueldos y jornales de los empleados y no queremos que desde otras computadoras de la Empresa puedan curiosear en ella. Entonces, de un plumazo las rechazamos a todas las que no se encuentran en nuestra misma subred.

Un trigger para evitar que se conecten fuera del horario autorizado:

Si el horario laboral de la empresa va de 8:00 a 18:00 entonces sería muy sospechoso que alguien tratara de conectarse a las 23:45 ¿verdad? ¿Por qué alguien querría conectarse a esa hora? Para estos casos podríamos tener un trigger que restrigiera el acceso fuera del horario establecido.

Listado 5.

CREATE TRIGGER NEW_DBTRIGGER_C4
   ACTIVE ON CONNECT
   POSITION 5
AS
BEGIN

 IF (CURRENT_USER <> 'SYSDBA' AND
     CURRENT_TIME < '07:45:00' OR CURRENT_TIME > '18:15:00') THEN
    EXCEPTION E_ACCESO_NO_PERMITIDO;

END;

Aquí, solamente al usuario SYSDBA le permitimos conectarse a cualquier hora que desee, todos los demás usuarios deberán iniciar la conexión entre las 07:45:00 y las 18:15:00

Desde luego que también podríamos restringir la conexión por los días de la semana: de Lunes a Viernes tendrían un horario de conexión, los Sábados tendrían otro horario de conexión y los Domingos tendrían otro horario.

O podríamos realizar combinaciones: MARCELA tiene un horario, SILVIA tiene otro horario, SUSANA tiene otro horario, etc.

Conclusión:

Para mantener la confidencialidad y la seguridad de los datos y de la información muchas veces es muy importante impedir que personas no autorizadas puedan conectarse a la Base de Datos. Esas personas podrían tener derechos de conexión a otras bases de datos de la Empresa, pero no a esta Base de Datos.

Usando los triggers de las bases de datos podemos impedir (o al menos dificultar) que se conecten quienes no deberían conectarse. Pero recuerda que ningún método es infalible. El usuario SYSDBA y el creador de la Base de Datos siempre podrán conectarse. Y podrían irse a almorzar dejando la conexión abierta y el intruso aprovechar la ocasión.

Hay muchísimas combinaciones más que puedes realizar pero con los ejemplos anteriores ya tendrás una buena idea de lo que se puede lograr.

Artículos relacionados:

Como evitar que se conecten a una Base de Datos

Evitando que un usuario se conecte más de una vez a la Base de Datos

Evitando que un usuario se conecte más de una vez (método mejorado)

El índice del blog Firebird21

El foro del blog Firebird21

Inferencia de datos

Deja un comentario

Como sabes, las bases de datos son muy útiles para guardar y procesar datos pero también pueden conllevar un compromiso con la seguridad de los mismos. Muchas veces lo que se guarda en sus tablas es para que lo vean solamente algunos usuarios, no todos los usuarios.

Esto es más importante en las aplicaciones que se diseñan para los organismos de seguridad (militares, policías, servicios de inteligencia, etc.) pero también puede ocurrir con empresas comerciales.

¿Qué significa inferir?

Según el Diccionario es obtener una conclusión, deducir algo a partir de los datos con los que se cuenta.

Ejemplo

Tenemos una tabla llamada SALARIOS donde se guarda el salario de cada empleado de la Empresa. El personal de Recursos Humanos es el encargado de elaborar los cheques de pago a esos empleados, pero no deben conocer el salario de los empleados de nivel superior, solamente deben conocer el salario de los empleados de nivel medio y nivel bajo.

INFERIR1

Captura 1. Si haces clic en la imagen la verás más grande

En la Captura 1 estamos viendo el Identificador del Empleado, el Número del Mes, el Número del Año y el Monto de su salario. El Gerente de Recursos Humanos es “Juan” y él sí puede ver esa tabla. Pero su empleada “María” no debería ver el salario del empleado cuyo Identificador es 3, o sea que “María” debería ver esto:

INFERIR2

Captura 2. Si haces clic en la imagen la verás más grande

Al mirar esa tabla ella nota que está faltando un empleado con Identificador igual a 3, y entonces cuando la Empresa contrata a un nuevo empleado cuyo nombre es “Martín” ella trata de usar el Identificador 3 para asignárselo a “Martín” y así no tener números de Identificación faltantes. Pero como el Identificador 3 sí existe (aunque ella no puede verlo) al intentar grabar los datos de “Martín” obtendrá un mensaje de error. Y como “María” es inteligente entonces infiere (es decir: deduce) que sí existe un empleado con Identificador igual a 3 pero que a ella no le permiten verlo.

Y como además de inteligente es curiosa a partir de ese momento se dedica a intentar averiguar los datos del empleado con Identificador 3, mediante tablas cruzadas, o algunas otras técnicas.

Diseñando para evitar inferencias

Si algún usuario puede inferir (deducir) que algo se le está ocultando entonces puede también inferir (deducir) que se trata de algo valioso, algo de lo cual podrá obtener provecho económico o de otro tipo. Por algo se le ocultan los datos ¿verdad?.

Entonces, cuando diseñamos nuestras bases de datos debemos pensar en como evitar las inferencias. No es fácil ante usuarios inteligentes y con muchos conocimientos de Informática pero debemos intentarlo.

La primera y elemental medida es impedir que los usuarios puedan asignar identificadores o códigos. Estos deberían ser elegidos y puestos automáticamente por el Servidor del Firebird o por nuestra aplicación.

Lo segundo a recordar siempre es que los identificadores son para uso interno y los códigos son para uso externo. Eso implica que los usuarios jamás deberían ver los identificadores (ni siquiera necesitan saber que existen) y manejarse siempre exclusivamente con códigos. En general los códigos no deberían cambiarse pero si se cambian no afectarán a la operatividad de la Base de Datos porque ésta no los utiliza para nada, son solamente para mostrárselos a los usuarios.

Tercero, los códigos no deberían ser de la forma “A, B, C, D, E, …” o de la forma “1, 2, 3, 4, 5, …” porque si falta una letra o un número en la secuencia entonces es muy fácil inferir que algo se está ocultando.

Conclusión:

Cuando se diseña una Base de Datos un aspecto importante es el relacionado con la seguridad de los datos. Y dentro de la seguridad hay que tomar en cuenta que los usuarios no autorizados a ver una información no puedan realizar inferencias para saber que esa información existe.

En el caso de nuestro ejemplo “María” rápidamente descubrió que se le estaban ocultando los salarios del empleado cuyo Identificador es 3. ¿Por qué? porque la Base de Datos estaba mal diseñada y se le permitía a ella asignar un Identificador al nuevo empleado. En una Base de Datos bien diseñada ningún usuario, por ningún motivo, puede asignar o cambiar un Identificador o un Código. Si alguna vez se requiere hacer eso entonces debería hacerse exclusivamente usando nuestra aplicación.

Artículos relacionados

Usando IDENTIFICADORES y CÓDIGOS en nuestras tablas

El índice del blog Firebird21

Ejemplos del uso de Zebedee con Firebird

16 comentarios

Aquí hay algunos ejemplos del uso de Zebedee con Firebird.

En estos dos artículos, habíamos visto para que sirve Zebedee y como usarlo. Ahora, para aclarar mejor el tema, algunos ejemplos:

Usando Zebedee con Firebird

Usando Zebedee con Firebird. Parte 2

Servidor

Línea de comandos

START ZEBEDEE -s localhost:3050

Usando un archivo de configuración

START ZEBEDEE -f SERVIDOR1.ZBD

Cliente

Línea de comandos

START ZEBEDEE 3051:99.999.999.99:3050

Usando un archivo de configuración

START ZEBEDEE -f CLIENTE.ZBD

Conexión con una Base de Datos Firebird

CONNECT localhost/3051:E:\BASESDATOS\MiBase.FDB USER SYSDBA PASSWORD masterkey;

NOTAS:

  1. En la computadora donde se encuentra el Servidor de Zebedee debe estar abierto el puerto 11965
  2. Las demás computadoras no necesitan (y no deberían) tener puertos abiertos
  3. Cualquier usuario puede conectarse, no solamente SYSDBA, por supuesto que con sus nombres y passwords correctos
  4. No es obligatorio escribir el comando START, pero si no se lo escribe entonces la ventana “Símbolo del sistema” se queda congelada. Zebedee funciona igual, pero esas ventanas congeladas no les gustan a los usuarios
  5. Las computadoras Cliente deben poder acceder a la computadora Servidor. Eso significa que la IP del Servidor debe ser pública, de una VPN como Hamachi o encontrarse en una red local
  6. No suele justificarse usar Zebedee en una red local, porque el tiempo que se gana al enviar los datos comprimidos se pierde al comprimir y descomprimir esos datos. Se justificaría su uso si aún tratándose de una red local hay computadoras que no son confiables
  7. Si se usa un archivo de configuración, ese archivo no debe encontrarse en una carpeta compartida o cualquiera podría modificarlo a su antojo
  8. Si la conexión con el Servidor de Firebird se realiza a través de Internet entonces usar Zebedee (o algún programa similar) es un requisito ineludible

Artículos relacionados:

Proteger a las bases de datos visibles en Internet

Usando Zebedee con Firebird

Usando Zebedee con Firebird. Parte 2

El índice del blog Firebird21

Older Entries