2009-10-28 10 views
8

Pregunta: ¿Es esta técnica de autenticación API fácilmente pirateable?Diseño de autentificación API y hackability

apiKey = "123456789" 
apiCallId = "1256341451" 
apiSecret = "67d48e91ab2b7471d4be2a8c2e007d13" 
sig = md5(apiKey + apiCallId + apiSecret) = 09c297a354219f173bfc49c2e203ce03 

donde

  • apiKey: algún identificador único para el usuario
  • apiCallId: un número entero único que debe ser aumentado en valor (por ejemplo UNIX sello de tiempo)
  • apiSecret: cadena conocidos solamente para el usuario, y para nosotros, no pasó en la URL
  • sig: firma "no apta" de esta llamada API - MD5 hash

Ejemplo llamada a la API:

http://api.domain.com/?apiKey=123456789&apiCallId=1256341451&sig=09c297a354219f173bfc49c2e203ce03&param1=x&param2=y 

Esta API no requiere una sesión, y no está diseñado para una tercera parte use en nombre de un usuario. En cambio, debe ser utilizado por el usuario.

Me gusta mucho la simplicidad de esto. El requisito de que apiCallId sea único y siempre aumenta significa que no es posible reutilizar un sig, por lo que me siento seguro (protegido contra ataques de repetición), pero no soy un experto.

Otras API utilizan todos los parámetros GET ordenados alfabéticamente al calcular el sig, pero no veo por qué es necesario cuando se incluye apiCallId.

Intente hackear esto ahora antes de implementarlo y liberarlo.

Agradezco cualquier comentario, sugerencia y educación de seguridad.

Respuesta

13

Lo que está haciendo parece razonablemente sensato, excepto que no verifica los parámetros (que será un problema bastante grande).

Algo que es muy similar a su diseño que podría ser conveniente para copiar es el Amazon Web Services Request Authentication Scheme

En particular Asegúrese de que el esquema de codificación de los parámetros no es ambigua e invertible; Amazon screwed this up en un punto. Aprende de sus errores :)

Criptográficamente hablando, lo que está haciendo no se llama una firma sino un código de autenticación de mensaje (MAC). Un MAC puede ser creado y verificado por cualquiera que comparta la clave secreta (el término 'firma' normalmente se reserva para esquemas de claves públicas como DSA o RSA). MD5 (msg || K) es un MAC conocido y razonablemente sano; No estoy seguro si te lo perdiste por accidente o intencionalmente, pero un método que parece en la superficie ser equivalente, MD5 (K || msg), es bastante inseguro, porque es una rareza en cómo MD5 (y la mayoría de los demás hash funciones) están diseñados significa que si conoce H (m) puede calcular fácilmente H (m || m2) para cualquier m2, por lo que si estaba usando MD5 (K || param1 = 5), alguien podría sacar esto del cable y luego crea MD5 (K || param1 = 5, param2 = 666). (Tal vez sea un poco más técnico de lo que le interesa, pero esto se llama length extension property).

Sin embargo, mientras que MD5 (K || msg) es probablemente "bueno", es mejor usar algo como HMAC, porque en realidad fue diseñado como un MAC. MD5 tiene muchos problemas pero nada afecta directamente su uso como MAC (aún - MD4 se ha roto de esta manera). Por lo tanto, en el futuro (a prueba de auditoría) utilice HMAC con SHA-1 o SHA-256. Incluso si no desea extraer una biblioteca criptográfica, HMAC es bastante simple y hay valores conocidos disponibles para SHA-1 y SHA-2 para que pueda verificar su código.

+0

Respuesta impresionante, y me encantan los detalles técnicos. 'erickson' señaló que la interceptación (man-in-the-middle) es posible con lo anterior. ¿Tiene alguna recomendación de cómo prevenir este tipo de ataque? Supongo que esto va más allá de la pregunta original. ¿El uso de HTTPS (y no de HTTP) lo cubre? –

+1

Si el MAC cubre todos los datos, _y _ no hay un segundo conjunto de entrada que canonicalice a la misma entrada al MAC (esto es importante, como aprendió Amazon), y se asegura de que no haya forma de hacer ataques de repetición (su contador esquema, implementado correctamente, parece estar bien), y su MAC es segura, entonces debe estar a salvo de MITM. Esto se debe a que un atacante no tiene opciones: pueden modificar un parámetro o valor API e intentar enviarlo, pero no habrá forma de que generen el valor MAC correcto, por lo que la llamada (debería ser) rechazada. –

+1

Supongo que usted exige que la identificación de la llamada siempre se incremente en una tabla de base de datos. Solo tenga cuidado de actualizarlo solo al aceptar un mac válido. De lo contrario, cualquier atacante aleatorio podría enviar apiKey = your_id y apiCallId = 9999999999999999 ... y un valor MAC basura y causar una denegación de servicio fácil. En HTTPS: puede usarlo, hágalo; en primer lugar, protegerá la confidencialidad de las entradas API (y las respuestas RPC) y, en general, hará que los ataques a su esquema de autenticación sean mucho más difíciles. –

0

Bueno, supongamos que conozco el secreto, entonces podría generar el sig y pasarlo. Lo que estaba haciendo para una de mis startups es llevar aún más el sig param al hacer que sig dependa de los otros parámetros y también un requestID (UUID) y la marca de tiempo y almacenar ese UUID (razones de seguridad por un par de horas para negar al hacker llamando a la misma función una y otra vez). De esta manera no puedes volver a llamar a la misma llamada, deberías generar un nuevo UUID y si el hacker reemplaza el UUID en el param el sig lo invalida, y él no sabe cómo generar el sig porque, aparte de secreto, somos también genera una firma basada en una clave interna que tiene 30 caracteres de longitud. Así essenity

MD5 (Lista alfabética de los Parámetros + apikey + CallID + Secert + someLonginternalKey)

No estoy seguro si respondido a su pregunta, pero esa es otra forma de hacer la seguridad de API

+0

P.S Auto promoción desvergonzada, voy a tomar sobre esto en Riadventure (Riadventure.com) –

+0

"Bueno, supongo que sabía el secreto" se ha acabado el juego en la mayoría de las API. Su solución definitivamente parece más segura, pero ¿es "seguridad a través de la complejidad"? No quiero complicar el proceso innecesariamente. ¿Por qué la ventaja de incluir todos los parámetros? ¿Por qué la clave extra lo hace menos propenso a ser pirateado? –

+1

No se requiere la clave adicional solo un relleno extra, puede ignorar eso. Sin embargo, al mezclar los parámetros en la firma, esto asegura los datos que está pasando (i.e param1 param2) se mantiene la integridad y está seguro de que nadie lo cambió (hombre en el medio) como decía la otra publicación. –

2

No. La integridad de los otros parámetros (param1 y param2 en su ejemplo) no está protegida. Un atacante puede interceptar la llamada y modificarla como quiera antes de reenviarla. El apiCallId solo evita las repeticiones, no la alteración de la primera llamada.

No soy un experto. Si lo vi de inmediato, probablemente haya otros problemas al acecho.

+0

Ah-haaa ... la interceptación es la razón. –

+0

Pero, ¿qué es detener la interceptación de cualquier llamada API incluso si todos los parámetros se usan en la firma? –

+0

Lo que @erickson dice es que los parámetros no están encriptados y pueden ser fácilmente alterados y transmitidos. Si también estuvieran encriptados, esto no sería posible. –

0

Sugiero usar firmas digitales en este caso, ya que son más apropiadas. Una firma digital sobre, por ejemplo, el apikey es más que suficiente. Ni siquiera necesitas el apisecret y el hash de eso. Solo debe asegurarse de que la firma digital se mantenga privada (al igual que el hash md5).

Si desea evitar el ataque de repetición, necesita algún tipo de aleatoriedad en cada solicitud. Así que le sugiero lo siguiente:

servidor -> API: Nonce (= un número aleatorio)

API -> Servidor: Enc (nonce + firma digital)

esta es encriptada con la clave pública del servidor y la firma digital se coloca con la clave privada del servidor.

Ahora no puede tener un ataque de repetición. Sin embargo, todavía existe el problema de un hombre en el ataque al medio, pero arreglarlo no es tan trivial (pero sí factible). Entonces, dependiendo del nivel de seguridad que desee/necesite, puede adaptar sus medidas técnicas.

Cuestiones relacionadas