¿Cómo implementaría un sistema seguro de credenciales de inicio de sesión estático en Java?

StackOverflow https://stackoverflow.com/questions/103203

Pregunta

Recientemente tuvimos una auditoría de seguridad y expuso varias debilidades en los sistemas que existen aquí.Una de las tareas que resultaron de esto es que necesitamos actualizar nuestro sistema de credenciales de socios para hacerlo más seguro.

La forma "antigua" de hacer las cosas era generar una contraseña (incorrecta), dársela al socio con una identificación y luego enviaría esa identificación y una copia codificada en Base 64 de esa contraseña con todas sus solicitudes XML a través de https. .Luego los decodificamos y los validamos.

Estas contraseñas no cambiarán (porque entonces nuestros socios tendrían que realizar cambios de codificación/configuración para cambiarlas y coordinar la caducidad de contraseñas con cientos de socios para múltiples entornos sería una pesadilla) y no es necesario que las ingrese un ser humano. o legible por humanos.Estoy abierto a cambiar esto si hay una implementación mejor pero aún relativamente simple para nuestros socios.

Básicamente todo se reduce a dos cosas:Necesito un sistema de generación de contraseñas Java más seguro y garantizar que se transmitan de forma segura.

Encontré algunos generadores de contraseñas hechos a mano, pero ninguno que realmente se destacara como una forma estándar de hacer esto (tal vez por una buena razón).También puede haber una forma más segura de transmitirlos que la simple codificación Base 64 a través de https.

¿Qué haría usted con el generador de contraseñas? ¿Cree que el método de transmisión utilizado es lo suficientemente seguro para ello?

Editar:El XML viene en un mensaje SOAP y las credenciales están en el encabezado, no en el XML mismo.Además, dado que las contraseñas son una operación única para cada socio cuando las configuramos, no nos preocupamos demasiado por la eficiencia del generador.

¿Fue útil?

Solución

Generación de contraseña

En cuanto a codificar una contraseña para su transmisión, la única codificación que realmente agregará seguridad es la encriptación.Usar Base-64 o hexadecimal no es por seguridad, sino simplemente para poder incluirlo en un formato de texto como XML.

La entropía se utiliza para medir la calidad de la contraseña.Por lo tanto, elegir cada bit con un "lanzamiento de moneda" aleatorio le dará la contraseña de mejor calidad.Usted querrá que las contraseñas sean tan seguras como otras claves criptográficas, por lo que recomendaría un mínimo de 128 bits de entropía.

Hay dos métodos sencillos, dependiendo de cómo desee codificar la contraseña como texto (lo cual realmente no importa desde el punto de vista de la seguridad).

Para Base-64, usa algo como esto:

  SecureRandom rnd = new SecureRandom();
  /* Byte array length is multiple of LCM(log2(64), 8) / 8 = 3. */
  byte[] password = new byte[18];
  rnd.nextBytes(password);
  String encoded = Base64.encode(password);

Lo siguiente no requiere que usted cree un codificador Base-64.La codificación resultante no es tan compacta (26 caracteres en lugar de 24) y la contraseña no tiene tanta entropía.(Pero 130 bits ya es mucho, comparable a una contraseña de al menos 30 caracteres elegida por un humano).

SecureRandom rnd = new SecureRandom();
/* Bit length is multiple of log2(32) = 5. */
String encoded = new BigInteger(130, rnd).toString(32); 

La creación de nuevos objetos SecureRandom es costosa desde el punto de vista computacional, por lo que si va a generar contraseñas con frecuencia, es posible que desee crear una instancia y conservarla.

Un mejor enfoque

Incrustar la contraseña en el propio XML parece un error.

En primer lugar, parece que le gustaría autenticar a un remitente antes de procesar cualquier documento que le envíe.Supongamos que lo odio y empiezo a enviarle archivos XML gigantes para ejecutar un ataque de denegación de servicio.¿Quiere tener que analizar el XML sólo para descubrir que no soy un socio legítimo?¿No sería mejor si el servlet simplemente rechazara las solicitudes de usuarios no autenticados desde el principio?

En segundo lugar, las contraseñas de sus socios legítimos estaban protegidas durante la transmisión mediante HTTPS, pero ahora probablemente estén almacenadas "de forma clara" en algún lugar de su sistema.Eso es mala seguridad.

Un mejor enfoque sería autenticar a los socios cuando le envíen un documento con credenciales en los encabezados de solicitud HTTP.Si solo permite HTTPS, puede eliminar la contraseña del documento por completo y colocarla en un Autenticación HTTP "básica" encabezado en su lugar.Está protegido por SSL durante la transmisión y no se almacena en su sistema de forma clara (solo almacena un hash unidireccional con fines de autenticación).

La autenticación HTTP básica es simple, ampliamente compatible y será mucho más fácil de implementar para usted y sus socios que los certificados de cliente SSL.

Proteger el contenido del documento

Si el contenido de los documentos en sí es confidencial, el remitente debería cifrarlos y usted debería almacenarlos en su forma cifrada.La mejor manera de hacerlo es con criptografía de clave pública, pero eso sería tema para otra pregunta.

Otros consejos

¿No podrías usar claves SSL para la autenticación?

No tengo claro por qué su equipo de auditoría considera "insegura" la transmisión de contraseñas a través de SSL, a través de HTTPS.Entonces, cuando pides dos cosas, parece que la segunda (garantizar que las contraseñas se transmitan de forma segura) ya se está manejando bien.

En cuanto a lo primero, tendríamos que saber qué pasa con la auditoría que expuso sus contraseñas como inseguras...

Abandonaría todo el enfoque de contraseña y comenzaría a usar certificados de cliente que permitan una conexión SSL autenticada por ambos lados.

Tienes que generar y firmar certificados individuales para cada cliente.En el protocolo de enlace SSL, solicita el certificado del cliente y lo verifica.Si falla, la conexión finaliza con un código de estado 401.

Los certificados pueden ser revocados en cualquier momento por su parte, lo que permite desconectar fácilmente a antiguos clientes.

Dado que todo esto sucede en el protocolo de enlace previo a la comunicación, no es posible inundar su servidor con datos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top