2009-05-08 14 views
55

Antecedentes:Generación de autenticación segura mediante cifrado tokens

Esto es realmente una cuestión general de mejores prácticas, pero algunos antecedentes sobre la situación específica podría ser útil:

Estamos desarrollando una aplicación de "conectado" para el iphone. Se comunicará con la aplicación de back-end a través de servicios REST. Para no tener que solicitar al usuario un nombre de usuario y contraseña cada vez que inician la aplicación, expondremos un servicio de "Inicio de sesión" que valida su nombre de usuario y contraseña en el inicio inicial y devuelve un token de autenticación que se puede usar para futuras aplicaciones web solicitudes de servicio para datos reales. El token puede tener un tiempo de vencimiento después del cual les pediremos que vuelvan a autenticarse con su nombre de usuario/contraseña.

La Pregunta:

¿Cuáles son las mejores prácticas para la generación de este tipo de contadores a usarse para la autenticación?

Por ejemplo, podríamos ...

  • hash (SHA-256, etc) una cadena aleatoria y almacenarla en la base de datos para el usuario dado junto con una fecha de caducidad. Realice una búsqueda simple del token en solicitudes posteriores para asegurarse de que coincida.
  • Cifre la identificación del usuario y cierta información adicional (marca de tiempo, etc.) con una clave secreta. Descifra el token en solicitudes posteriores para asegurarte de que fue emitido por nosotros.

Parece que debe ser un problema resuelto.

Respuesta

29

Basándose en la información de las otras respuestas a esta pregunta, la investigación adicional, y las discusiones fuera de línea, esto es lo que terminamos haciendo ...

Se señaló rápidamente que el modelo de interacción aquí es esencialmente exactamente igual que el modelo utilizado por Forms Authentication en ASP.NET cuando se marca una casilla de verificación "recordarme". Simplemente no es un navegador web que realiza las solicitudes HTTP. Nuestro "boleto" es equivalente a la cookie que establece la Autenticación de formularios. La autenticación de formularios utiliza esencialmente un enfoque de "cifrar algunos datos con una clave secreta" de manera predeterminada.

En nuestro servicio web de inicio de sesión, podemos usar este código para crear un ticket:

string[] userData = new string[4]; 

// fill the userData array with the information we need for subsequent requests 
userData[0] = ...; // data we need 
userData[1] = ...; // other data, etc 

// create a Forms Auth ticket with the username and the user data. 
FormsAuthenticationTicket formsTicket = new FormsAuthenticationTicket(
    1, 
    username, 
    DateTime.Now, 
    DateTime.Now.AddMinutes(DefaultTimeout), 
    true, 
    string.Join(UserDataDelimiter, userData) 
    ); 

// encrypt the ticket 
string encryptedTicket = FormsAuthentication.Encrypt(formsTicket); 

Entonces tenemos un atributo de comportamiento de operación para los servicios WCF que añade un IParameterInspector que comprueba si un billete válido en el HTTP encabezados para la solicitud. Los desarrolladores colocan este atributo de comportamiento de operación en las operaciones que requieren autenticación.Aquí es cómo ese código analiza el billete:

// get the Forms Auth ticket object back from the encrypted Ticket 
FormsAuthenticationTicket formsTicket = FormsAuthentication.Decrypt(encryptedTicket); 

// split the user data back apart 
string[] userData = formsTicket.UserData.Split(new string[] { UserDataDelimiter }, StringSplitOptions.None); 

// verify that the username in the ticket matches the username that was sent with the request 
if (formsTicket.Name == expectedUsername) 
{ 
    // ticket is valid 
    ... 
} 
+0

¿Cómo está encontrando este enfoque? Puedo estar equivocado, sin embargo, creo que hay un pequeño error con eso. Lo único que se requiere para que la solicitud del cliente sea autorizada es que el ticket se puede descifrar en el servidor. Si el ticket se intercepta durante el tránsito (por ejemplo, inhalación de paquetes) o incluso se extrae del dispositivo móvil, un atacante podría volver a utilizarlo para enviar solicitudes maliciosas. Si está utilizando SSL, el primer ataque se mitigará; sin embargo, el segundo es aún viable. – James

+2

Todavía estamos muy contentos con este enfoque. Usamos SSL, por lo que el problema del rastreo no es una preocupación. El ticket que se extrae de un dispositivo móvil requiere que el dispositivo móvil se vea comprometido y/o físicamente en manos de un atacante. En ese punto, el atacante ya ha "ganado" y se acabó el juego. Sin importar los detalles técnicos, este siempre será el caso si hay una funcionalidad de "recordar mi contraseña". En nuestro caso, esto se ve un tanto mitigado por el hecho de que un ticket solo es válido durante 8 horas, por lo que el atacante tiene un margen de tiempo limitado para hacer uso del ticket robado. –

+0

La razón por la que pregunto es porque realmente pensé que era una forma inteligente de generar un token sin tener que escribir ningún código de seguridad. Sin embargo, pedí una [pregunta] (http://security.stackexchange.com/questions/19676/token-based-authentication-securing-the-token) en el sitio de seguridad de TI para obtener algunos consejos con respecto a * cómo * seguro en realidad fue y la opinión difiere. Tenía que ver más con el hecho de que usa el cifrado para proteger el token en lugar de un [MAC] (http://en.wikipedia.org/wiki/Message_authentication_code). – James

0

Esto simplemente suena como un identificador de sesión con un largo tiempo de caducidad. Los mismos principios utilizados para esto en aplicaciones web podrían aplicarse aquí.

En lugar de codificar información, los identificadores de sesión se eligen al azar de un espacio muy grande (128 bits). El servidor mantiene un registro que asocia el identificador de sesión con el usuario y otra información deseada, como el tiempo de caducidad. El cliente presenta el identificador de sesión sobre un canal seguro con cada solicitud.

La seguridad se basa en la imprevisibilidad de los identificadores de sesión. Genere con un RNG criptográfico, desde un espacio muy grande.

12

Crear su propio sistema de autenticación siempre es una "peor práctica". Ese es el tipo de cosa mejor para los profesionales que se especializan en sistemas de autenticación.

Si está empeñado en construir su propia arquitectura de "expirar ticket desde un servicio de inicio de sesión" en lugar de volver a utilizar una existente, probablemente sea una buena idea familiarizarse con los problemas que impulsaron el diseño de sistemas, como Kerberos. Una suave introducción está aquí:

http://web.mit.edu/kerberos/dialogue.html

También sería una buena idea echar un vistazo a lo que los agujeros de seguridad han sido encontradas en Kerberos (y sistemas similares) en los últimos 20 años y asegurarse de que don no los repliques.Kerberos fue construido por los expertos en seguridad y cuidadosamente revisado por décadas, y aún graves deficiencias algorítmicas se están encontrando en ella, como éste:

http://web.mit.edu/kerberos/www/advisories/MITKRB5-SA-2003-004-krb4.txt

Es mucho mejor aprender de sus errores a la suya.

+12

Si hay un sistema de autenticación preexistente que funciona entre las aplicaciones de iPhone y los servicios web WCF de REST, publique un enlace y estaré encantado de usarlo en lugar de inventar el nuestro ... Demostrando eso, ciertamente eche un vistazo a los enlaces de Kerberos que proporcionó. –

+0

Dirígete a una buena práctica como RESTful API. Iniciar sesión es exactamente lo que estoy buscando en este momento =) El OP claramente está pidiendo las mejores prácticas y no intenta construir las suyas también. – JPK

10

Amazon.com utiliza un HMAC SHA-1 message token para autenticar y autorizar solicitudes. Lo usan para un servicio comercial bastante grande, por lo que es probable que confíe en sus decisiones de ingeniería. Google publica el OpenSocial API que es algo similar. Basado en Google y Amazon.com, que utilizan enfoques similares y publicados abiertamente para asegurar las solicitudes web, sospecho que estas son probablemente buenas maneras de hacerlo.

1

Dado que está utilizando WCF, usted tiene una variedad de opciones si se utiliza CFNetwork - por ejemplo NTLM o autenticación implícita:

http://developer.apple.com/documentation/Networking/Conceptual/CFNetwork/Concepts/Concepts.html#//apple_ref/doc/uid/TP30001132-CH4-SW7

Sé que esto no responde a tu pregunta específica, pero También me he enfrentado a este problema (iPhone - Tomcat) y he decidido usar los servicios de autenticación en el servidor web tanto como sea posible. No hay una penalización significativa por incluir la información de autenticación con cada solicitud en la mayoría de los casos. Un Google rápido aparece un montón de publicaciones en el blog sobre WCF y servicios RESTful (y algunas preguntas relacionadas en StackOverflow).

Espero que esto ayude!

3

Cualquiera de las dos respuestas que ha proporcionado será suficiente. Puede encontrar marcos que hagan esto por usted, pero la verdad es que no es tan difícil de construir. (Todas las empresas para las que he trabajado han hecho suyas). La elección de tokens almacenados en la base de datos frente a "cookies" de datos encriptados es una decisión arquitectónica. ¿Desea realizar una búsqueda en la base de datos en cada vista de página o preferiría? masticar CPU con descifrado de cookies? En la mayoría de las aplicaciones, el uso de cookies cifradas proporciona una ganancia de rendimiento a escala (si es una preocupación). De lo contrario, es solo una cuestión de gusto.

Cuestiones relacionadas