2009-02-18 22 views
17

Almacenamos todas nuestras contraseñas de aplicaciones y bases de datos en texto sin formato en el control de código fuente. Hacemos esto ya que nuestro proceso de compilación/implementación genera los archivos de configuración necesarios y también los despliegues reales que requieren estas contraseñas (es decir: ejecutar SQL contra una base de datos requiere que inicie sesión en el DB utilizando credenciales válidas). ¿Alguien ha tenido una necesidad similar en la que pudo implementar este tipo de funcionalidad sin almacenar las contraseñas en texto plano?Almacenamiento de contraseñas en el control de código fuente

+1

Ponga las contraseñas en las variables de entorno de usuario de o/s. –

Respuesta

21

Si su plan es almacenar todo el código y la información de configuración para ejecutar un sistema de producción directamente desde el control de versiones, y sin intervención humana, está jodido. ¿Por qué? Esto es solo una violación del antiguo axioma de seguridad "nunca escribir su contraseña". Hagamos una prueba por negación.

En primer corte, tiene contraseñas de texto sin formato en los archivos de configuración. Eso no es bueno, pueden ser leídos por cualquiera que pueda ver los archivos.

Segundo corte, encriptaremos las contraseñas! Pero ahora el código necesita saber cómo descifrar las contraseñas, por lo que debe colocar la clave de descifrado en algún lugar del código. El problema acaba de bajar un nivel.

¿Qué tal el uso de claves públicas/privadas? Mismo problema que las contraseñas, la clave debe estar en el código.

El uso de un archivo de configuración local no almacenado en el control de la versión todavía coloca la contraseña y los medios para leerlos si están encriptados, en el disco y disponibles para un atacante. Puedes endurecer un poco las cosas asegurándote de que los permisos del archivo de configuración sean muy limitados, pero si la caja se enruta, estás jodido.

Lo que nos lleva a por qué poner contraseñas en el disco es una mala idea. Viola el concepto de un firewall de seguridad. Una máquina comprometida que contiene información de inicio de sesión significa que otras máquinas estarán en peligro. Una máquina mal mantenida puede derribar toda su organización.

En algún momento un humano tendrá que inyectar el secreto crítico para comenzar la cadena de confianza. Lo que podría hacer es encriptar todos los secretos en el código y luego, cuando el sistema se inicie, un humano ingrese manualmente la clave para descifrar todas las contraseñas. Es como el sistema de contraseña maestra que usa Firefox. Está abierto al abuso ya que una vez que una contraseña se ve comprometida, muchos sistemas pueden verse comprometidos, pero es conveniente y probablemente más seguro ya que los usuarios solo tienen que recordar una contraseña y es menos probable que la escriban.

El toque final es asegurarse de que la información de inicio de sesión se vea comprometida (y siempre debe asumir que será) que A) el atacante no puede hacer mucho con ella y B) puede cerrar rápidamente el comprometido cuentas El primero significa dar a las cuentas solo el acceso que necesiten. Por ejemplo, si su programa solo necesita leer desde una base de datos, inicie sesión en una cuenta restringida a SELECCIONAR. En general, elimine todos los accesos y luego agréguelos solo cuando sea necesario. Sé tacaño sobre los derechos a eliminar para evitar que te visiten little Bobby Tables.

Esto último significa que cada usuario/organización/proyecto tiene su propio inicio de sesión, incluso si pueden tener los mismos derechos y privilegios y acceder a los mismos datos. Es un poco más complicado, pero significa que si un sistema se ve comprometido, puede cerrar rápidamente esa cuenta sin cerrar todo su negocio.

+0

"pero si la caja se enraiza, estás jodido" Estoy confundido: ¿hay protocolos de seguridad en los que el rooteo forma parte del modelo de amenaza? No puedo imaginar cómo podrías defenderte contra un ataque de raíz. – christianbundy

+0

@christianbundy Cuando se penetra un sistema, debes asegurarte de que no puedan usarlo para penetrar en otro sistema. En este caso, si almacena la contraseña de su base de datos en el disco y se penetra una sola máquina, el atacante puede ahora acceder a su base de datos. Supongo que el código de la aplicación y la base de datos se ejecutan en diferentes servidores. Además, no necesita ser root para leer el archivo de configuración de la aplicación, solo necesita ser el usuario de la aplicación, que es mucho más fácil. Ni siquiera necesita eso, solo necesita engañar a la aplicación para que le permita ver su archivo de configuración. – Schwern

+0

si se penetra su sistema, ¿cómo es posible evitar que el atacante lea la contraseña? Guardarlo en el sistema de archivos es fácil de leer a través de FS I/O, guardarlo en un entorno es fácil de leer a través de/proc /, y guardarlo en la RAM es fácil de leer a través de '/ dev/mem'. ¿Qué alternativa estás sugiriendo? – christianbundy

-8

Si lo hace en C podría almacenarlo como una matriz de caracteres y poner los caracteres como referencias decimales. No estoy seguro si esto romperá las cuerdas o no, pero podría ayudar a aliviar parte de ese problema.

char pass[]={72, 101, 108, 108, 111}; 
+1

Boshfpngvba qbrf abg cebivqr frphevgl! – Schwern

+0

eewwwwwwwwwwwww –

-5

Tienda de contraseñas en forma cifrada. Escriba una rutina personalizada que descifre las contraseñas y actualice los archivos de configuración en tiempo de compilación. Esto se puede integrar fácilmente con la herramienta de compilación como Ant.

+3

Entonces, ¿dónde pones la clave de descifrado? – Schwern

-1

Usted no ha mencionado la lengua, por lo que aquí es una solución vb.net usamos:

Imports System.Web.Security 
Imports System.Security.Cryptography 
Imports System.Text 
Imports Microsoft.Win32 

Public Class myCrypt 

Private myKey As String = "somekeyhere" 
Private cryptDES3 As New TripleDESCryptoServiceProvider() 
Private cryptMD5Hash As New MD5CryptoServiceProvider() 


Private Function Decrypt(ByVal myString As String) As String 
    cryptDES3.Key = cryptMD5Hash.ComputeHash(ASCIIEncoding.ASCII.GetBytes(myKey)) 
    cryptDES3.Mode = CipherMode.ECB 
    Dim desdencrypt As ICryptoTransform = cryptDES3.CreateDecryptor() 
    Dim buff() As Byte = Convert.FromBase64String(myString) 
    Decrypt = ASCIIEncoding.ASCII.GetString(desdencrypt.TransformFinalBlock(buff, 0, buff.Length)) 
End Function 

Private Function Encrypt(ByVal myString As String) As String 
    cryptDES3.Key = cryptMD5Hash.ComputeHash(ASCIIEncoding.ASCII.GetBytes(myKey)) 
    cryptDES3.Mode = CipherMode.ECB 
    Dim desdencrypt As ICryptoTransform = cryptDES3.CreateEncryptor() 
    Dim MyASCIIEncoding = New ASCIIEncoding() 
    Dim buff() As Byte = ASCIIEncoding.ASCII.GetBytes(myString) 
    Encrypt = Convert.ToBase64String(desdencrypt.TransformFinalBlock(buff, 0, buff.Length)) 
End Function 

End Class 
+0

Nuestro proceso de compilación/implementación es ANT. Nuestro código de aplicación pasa a ser Java. –

+3

MD5? TripleDES? Maldición, MD5 ya está comprometido y 3DES está en camino de salir. Use AES y SHA256. Más importante aún, una vez que haya cifrado las credenciales de inicio de sesión, ¿dónde coloca la clave de descifrado? Huevo de gallina. – Schwern

6

supongo que el objetivo es que no desea que las contraseñas privadas de su empresa estén disponibles, cifrada , descifrado, o de otra manera, a cualquier persona que de otra manera debería tener acceso al resto de la fuente.

Así es como lo hago. Dupliqué este patrón de TikiWiki, que también lo hace.

en un archivo que normalmente contiene contraseñas, establézcalas en valores ficticios, no importa qué. Establézcalo como lo que su cliente debería ver. Ponga un comentario cerca para que los desarrolladores dejen este archivo solo y modifiquen un segundo archivo.

En el segundo archivo, que se crea si no está allí, ponga las contraseñas reales. haga arreglos para que este archivo sea incluido, importado, lo que sea, por el primer archivo.

Disponga su control de fuente para ignorar ese archivo. Podría verse algo como esto:

# in .gitignore 
localsettings.py 

# in settings.py 
## Alter this value to log into the snack machine: 
## developers: DON'T alter this, instead alter 'localsettings.py' 
SECRET_VALUE = "" 
try: 
    from localsettings import * 
except: 
    pass 

# in localsettings.py 
SECRET_VALUE = "vi>emacs" 
1

He creado sistemas en los que los pares de ID de usuario/contraseña no forman parte del código. La clave es configurar un mecanismo de configuración específico del sitio. Luego puede poner esa información en la casilla en cuestión, sin que sea parte de la base de código.

Hay una ventaja: no solo se pueden tener contraseñas diferentes para distintas reducciones de código, sino también para diferentes desarrolladores. :-)

+0

Buen punto. Un escenario que tenemos es donde nuestro script de implementación ejecuta sql contra un db (podría ser dev, qa, prod, etc.). Todo esto se hace en un único servidor de implementación. No estoy seguro de cómo implementar esta solución en ese caso. –

+0

La forma de hacerlo es que el script sql-update se ejecute en el servidor de destino final. Luego puede usar la configuración local para encontrar la base de datos. :-) – staticsan

Cuestiones relacionadas