certificado digital

Como Mejorar la Seguridad de las Conexiones de las Bases de Datos

 

 

Texto Original: https://www.microsoft.com/en-us/microsoft-365/blog/2011/04/08/power-tip-improve-the-security-of-database-connections/

 

Traducción automática con Google Translator

8 de abril de 2011
Como mejorar  la seguridad de las conexiones de las bases de datos
Autor: Chris Downs


Esta publicación sobre cómo hacer que las conexiones ODBC sean más seguras es proporcionada por Access MVP Ben Clothier.


De vez en cuando, llegamos a un punto en el que decidimos aumentar el tamaño de una base de datos de Access a un RDBMS basado en servidor. Las razones para aumentar el tamaño pueden variar, pero un tema común es la seguridad. Con un RDBMS basado en servidor, tenemos más opciones de seguridad que cuando estamos trabajando con una fuente de datos basada en archivos. Incluso si la seguridad no fue la razón del aumento de personal, tenemos la obligación de asegurarnos de desarrollar una aplicación de "buen ciudadano" y proteger los activos de la compañía contenidos en el RDBMS. Cuando nuestro RDBMS admite la autenticación de Windows (por ejemplo, SQL Server, Oracle, FireBird), lo tenemos fácil: no es necesario almacenar nombre de usuario ni contraseña. Pero desafortunadamente, no siempre tenemos disponible la autenticación de Windows, e incluso cuando es compatible, puede que no sea práctico. Este artículo se centra en el caso en el que tenemos que pasar un nombre de usuario y una contraseña como parte de la cadena de conexión y queremos hacerlo de manera segura. El artículo también asume que estamos usando ODBC y DAO.
Agujeros en los nombres de origen de datos

De forma predeterminada, Access ofrece configurar un Nombre de origen de datos (DSN) cuando queremos crear una nueva tabla vinculada. Como cuestión de desarrollo, el DSN es bastante conveniente, ya que nos proporciona un método gráfico para construir y especificar rápidamente una cadena de conexión ODBC sin tener que recordar toda la sintaxis y los parámetros. Desafortunadamente, cuando llega el momento de la implementación, el uso de DSN tiene una serie de problemas, especialmente de seguridad. Repasemos rápidamente algunos de los agujeros de seguridad asociados con el uso de DSN.

Figura 1
Figura 1

Cuando vinculamos una nueva tabla ODBC, el acceso predeterminado es no guardar la contraseña cuando seleccionamos un DSN. Tenemos que seleccionar Guardar contraseña para hacerlo, como se ve en la Figura 1. Las versiones recientes de Access advierten que la contraseña se guardará como texto sin formato. Si ignoramos la advertencia y guardamos la contraseña de todos modos, la contraseña se guarda en la tabla del sistema de Access, MSysObjects, como texto sin formato. Puede ver un ejemplo de esto en la Figura 2.

Figura 2
Figura 2
No guardar contraseñas no es lo suficientemente bueno

Entonces, elija no guardar la contraseña. ¿Eso resuelve el problema? Lamentablemente, no necesariamente. Cuando creamos un DSN, los datos utilizados para construir cadenas de conexión se almacenan en una entrada de registro. Veamos cómo se estructura el DSN para una base de datos MySQL. Puede encontrarlo en el nodo de registro que se muestra en la Figura 3.

Figura 3
figura 3

Aquí, la contraseña se almacena en el registro como texto sin formato, por lo que a pesar de que no verificamos la opción Guardar contraseña , y nuestro Connect no enumeraría la contraseña en ninguna parte de la base de datos, todavía está allí para tomarla. Yikes Peor aún, almacenar contraseñas es una implementación específica del proveedor. El controlador ODBC PostgreSQL también almacena las contraseñas como texto sin formato, pero el controlador ODBC Firebird siempre cifra la contraseña. Los controladores ODBC de SQL Server nunca intentarán almacenar una contraseña de autenticación de SQL Server, pase lo que pase. Teniendo en cuenta la gran cantidad de controladores ODBC diferentes, incluidos los controladores de terceros para el mismo RDBMS, preferiría no tener que rastrear las rarezas específicas de cada controlador ODBC y acomodar cada uno de ellos a medida que me muevo de RDBMS a RDBMS.

Podemos decir: "No definamos la contraseña en el DSN, lo que requiere que el usuario complete la conexión en tiempo de ejecución". De hecho, podemos hacerlo, pero ahora nos encontramos con un nuevo problema que también afecta al controlador ODBC de SQL Server. Cada vez que un usuario abre un objeto de Access que es, o depende de, un objeto ODBC, se le solicitará al usuario que ingrese su contraseña para esa conexión ODBC. Esto no brinda una excelente experiencia de usuario, sin mencionar varios problemas adicionales que se presentan al mostrar a los usuarios el cuadro de diálogo para configurar el controlador ODBC, que expone opciones con las que no querrá que los usuarios jueguen.
Usando una conexión sin DSN

En resumen, el uso de DSN puede ser conveniente, pero puede ser problemático implementarlo de manera segura. Además, debido a que los detalles de la implementación varían según el controlador ODBC, no existe una buena solución general para diseñar un DSN seguro. Por lo tanto, debemos considerar cadenas de conexión sin DSN. Aunque las conexiones sin DSN per se no son necesariamente más seguras, la seguridad adicional proviene del hecho de que pueden ser desechables, lo que se vuelve muy importante, como veremos en breve.

El MVP de acceso Douglas J. Steele ha publicado una muestra de cómo construir una conexión sin DSN en VBA para un servidor SQL Server . Doug actualizó recientemente el material, incorporando modificaciones sugeridas por George Hepworth, otro MVP de Access, para soportar conexiones confiables y autenticación de SQL Server. Este documento nos proporciona un excelente punto de partida para aprender cómo podemos construir conexiones sin DSN. También aprenderemos cómo podemos asegurarnos de que todas las tablas vinculadas se puedan actualizar agregando un índice único local a Access.
Conexión en caché

Hay un comportamiento interesante en Access que queremos aprovechar. Cuando Access abre una conexión ODBC, almacena en caché esa conexión. Cualquier objeto ODBC posterior que coincida con tres parámetros (controlador ODBC, servidor y base de datos) reutilizará esa conexión en caché. Esto significa que no tenemos que especificar la cadena de conexión completa para todos los objetos ODBC cada vez. Solo necesitamos suministrar la cadena de conexión completa una vez al inicio y almacenar solo la cadena de conexión incompleta. Luego podemos dejarlo en Access para que coincida con los objetos ODBC posteriores a esa cadena de conexión en caché. Esto ayuda enormemente a simplificar la configuración de seguridad.

Durante el inicio de la aplicación, queremos llamar a una rutina que creará una consulta temporal que contiene la conexión completa. Entonces podemos descartar esa consulta al final de la rutina. Procedimiento InitConnect demuestra este paso crucial.

Public Function InitConnect() As Boolean
' Codigo Original: https://www.microsoft.com/en-us/microsoft-365/blog/2011/04/08/power-tip-improve-the-security-of-database-connections/
' AVISO: el codigo Original No funcionaba asi que he tenido que modificarlo ligeramente
' Modificaciones Javier.Mil

On Error GoTo Err_Handler

Rem ***** Inicio CONFIGURACION ***********
Const cDriver As String = "MySQL ODBC 5.3 Unicode Driver"  
' << Poner exactamente el mismo texto que tu conector ODBC
Const cNombreBase As String = "xxxxxxxxx"  
' << Poner Nombre Base Datos
Const cUsuario As String = "xxxxxxxx"
' << Poner Usuario
Const cPassword As String = "xxxxxxxx"
' << Poner Password
Const cIPservidor As String = "xxx.xx.xxx.xx"
' << Poner dirección IP
Const cPuerto As Integer = 3306  
'<< Normalmente puerto 3306
Const cOpcion As String = ""
' << Dejar vacio
Const cSTMT As String = ""  
' << Dejar vacio
Rem ******* Fin CONFIGURACION *************


Dim dbCurrent As DAO.Database
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset
Dim strConnection As String


Rem configuration specific to MySQL ODBC driver
strConnection = "ODBC;DRIVER={" & cDriver & "};" & _
"Server= " & cIPservidor & ";" & _
"Port= " & cPuerto & ";" & _
"Option= " & cOpcion & ";" & _
"Stmt= " & cSTMT & ";" & _
"Database= " & cNombreBase & ";"


Set dbCurrent = CurrentDb   '
DBEngine(0)(0)
Set qdf = dbCurrent.CreateQueryDef("")

With qdf
.Connect = strConnection & _
"Uid=" & cUsuario & ";" & _
"Pwd=" & cPassword
.SQL = "SELECT CURRENT_USER();"

Set rst = .OpenRecordset(dbOpenSnapshot, dbSQLPassThrough)
End With

InitConnect = True


Exit_Procedure:
On Error Resume Next

Set rst = Nothing
Set qdf = Nothing
Set dbCurrent = Nothing
Exit Function


Err_Handler:
InitConnect = False
MsgBox Err.Description, vbCritical, "Error N°: " & Err.Number

Resume Exit_Procedure
Resume
End Function


Aunque descartamos la consulta al final del procedimiento, Access mantiene la conexión que creó detrás de escena. Hasta donde yo sé, no hay acceso programático a esta conexión en caché. Sin embargo, una vez que existe, puede abrir cualquier otro objeto ODBC que coincida con los parámetros del controlador, el servidor y la base de datos e interactuar con él como si tuviera la cadena de conexión completa. La Figura 4 muestra una tabla abierta sin ningún aviso adicional después de ejecutar el procedimiento al inicio. Aunque no tiene la cadena de conexión completa, Access usó la conexión en caché creada por InitConnect, por lo que no hay necesidad de solicitar al usuario la información faltante.

Figura 4
Figura 4

Con esta técnica, ahora puede implementar un formulario de inicio de sesión personalizado para que los usuarios ingresen su nombre de usuario y credenciales en tiempo de ejecución y llamen al procedimiento InitConnect. Esa información se pasa al fragmento de código ilustrado anteriormente para crear la conexión. Ahora tiene una aplicación que no almacena la contraseña en ningún lugar, dentro o fuera del archivo. Aunque eso no evitará que sus usuarios escriban su contraseña en una nota pegada a su monitor, puede estar seguro de que, si el archivo se copia y se lleva fuera del edificio, sería inútil; más aún si la conexión requiere estar dentro de una determinada red. (Ciertas direcciones IP como 192.168. *. * No son accesibles en todo el mundo y requieren una conexión física a un servidor DHCP en particular o al menos VPN o un software de túnel similar).
Las consultas de paso también tienen una cadena de conexión

Figura 5

Figura 5

Como muestra la Figura 5, debemos recordar que las tablas vinculadas no son los únicos objetos que tienen una propiedad Connect; las consultas pasantes pueden tener una propiedad Connect que también debe mantenerse. Afortunadamente, esas consultas también pueden compartir la conexión en caché, por lo que no debería haber ninguna razón para que almacenemos una cadena de conexión completa para ellos. Solo necesitamos asegurarnos de que todas las consultas pasantes tengan el mínimo de tres parámetros requeridos y listo.
Cerrando un hoyo más

Hay un agujero que debemos cerrar: la conexión en caché no se cierra cuando cerramos la base de datos pero no salimos de Access. En otras palabras, si un usuario cierra su aplicación y abre sus propias bases de datos, no se les impedirá acceder a los mismos objetos ODBC utilizando la conexión en caché. Afortunadamente, eso es bastante fácil de remediar: cuando se cierra el último formulario, forzar el acceso para salir generalmente asegurará que la conexión en caché se elimine correctamente al final de la sesión de su aplicación. Esto garantiza que los usuarios siempre tendrán que iniciar sesión explícitamente cuando abran Access e intenten acceder a las fuentes ODBC.

Cuando ha implementado una cadena de conexión incompleta, el archivo ya no puede simplemente copiarse. Si alguien intenta omitir la rutina de inicio de sesión, las tablas y consultas no podrán conectarse. Hacer doble clic en esos objetos simplemente les daría el cuadro de diálogo del controlador ODBC pidiéndoles que completen la conexión. Debido a que la contraseña no se almacena en ningún lado, no pueden simplemente mirar debajo del felpudo. Aunque cifrar la contraseña es una opción, es mucho más preferible no almacenar ninguna contraseña y requerir que el usuario la proporcione justo a tiempo. Cifrar la contraseña y almacenarla en el archivo es análogo a poner su información confidencial en una pequeña caja fuerte y dejarla en su patio delantero. Cualquiera puede llevar su pequeña caja fuerte a otro lugar y tomar todo el tiempo que quiera para descifrar la contraseña. La verdadera seguridad consiste en no tener nada disponible para tomar y bloquear el acceso en lugar de dificultar el acceso.
Lectura extra

Para obtener opciones de seguridad adicionales, puede considerar crear una tabla MSysConf en su servidor RDBMS para asegurarse de que Access no ofrezca guardar contraseñas localmente.
Para aquellos que no desean que los usuarios inicien sesión e ingresen una contraseña, el ejemplo de Access MVP Tom van Stiphout de usar Active Directory para proporcionar control de acceso a nivel de usuario para los formularios de Access se puede usar como modelo para implementar la autenticación a través de un servidor de terceros (p. ej., Active Directory).
Si recién está comenzando con las cadenas de conexión, puede ir al sitio de Carl Prothman y ConnectionStrings para encontrar excelentes repositorios de cadenas de conexión completas, aunque es posible que desee ir al proveedor de su controlador ODBC para obtener la información más actualizada y completa documentación.
Finalmente, visite el sitio de George Hepworth para obtener muchos consejos, demostraciones y descargas.

Nota: Si creamos un DSN de archivo en lugar de un DSN de sistema o usuario, los datos se almacenarán en un archivo en lugar de en una entrada del registro. Sin embargo, los DSN de archivo aún almacenan los datos en texto sin formato, similar a lo que vimos en el registro. Por lo tanto, las preocupaciones por la seguridad se aplican igualmente a los DSN de archivo y a los DSN de sistema / usuario.

–Ben Clothier

Ben Clothier ha sido MVP de Access desde 2009. Es un contratista independiente que trabaja con J Street Technology y Advisicon y fue editor técnico de Access 2010 Programmer's Reference .