¿Cómo puedo autenticar una conexión de cliente de manera segura?

6

Digamos que tengo un servidor escuchando en el puerto 1234. Tengo algún software cliente que necesita poder conectarse a este puerto. Pero quiero evitar que los usuarios malintencionados omitan el software cliente y se conecten al puerto por otros medios (como en una consola u otro software).

El software cliente de confianza y el servidor pueden compartir una clave secreta, si es necesario (puedo vivir con la posibilidad de que la clave se pueda extraer del binario). Prefiero no enviar esa clave en texto sin formato, pero los datos después de la autenticación pueden estar en texto sin formato. Específicamente, estoy tratando de descubrir cómo derrotar a un ataque de intermediarios en el que el usuario malintencionado está utilizando el software de cliente de confianza para calcular las respuestas correctas a los desafíos del servidor.

¿Puedo llegar desde aquí?

Podría hacer que el puerto de escucha del servidor se vincule solo a localhost y requerir que los clientes primero obtengan acceso a la máquina a través de ssh. Luego, el software cliente podría usar una biblioteca ssh para ejecutar un comando en el servidor que se conecta al puerto local (en este escenario, el usuario malintencionado no podría usar ssh para acceder a la máquina porque no tendría la contraseña). Pero entonces todo mi tráfico está encriptado, lo que es una sobrecarga adicional. Quizás hay un programa similar a ssh que solo hace la autenticación pero luego deja el canal en texto sin formato después de eso.

Actualización:

Realicé una prueba para determinar la sobrecarga asociada con el cifrado de todo el tráfico.

spew.rb genera 10 millones de líneas de 100 caracteres.

CONTROL:

fantius@machine> time /home/fantius/spew.rb > /dev/null

real    0m35.015s
user    0m34.934s
sys     0m0.084s

top muestra un 25% de uso de CPU (un núcleo completo, de cuatro núcleos)

PRUEBA:

fantius@machine> time ssh localhost /home/fantius/spew.rb > /dev/null

real    0m40.704s
user    0m19.981s
sys     0m1.400s

top muestra un 45% de uso de CPU (casi dos núcleos completos)

Esa tasa de mensajes probablemente supera la mayoría de las conexiones entre máquinas.

    
pregunta Thomas Pornin 13.01.2011 - 20:32
fuente

2 respuestas

8

Primero, sugiero evitar los supuestos sobre la sobrecarga de cifrado. Debes medir . Mi PC desde 2001 ya era lo suficientemente potente como para transferir datos con SSH a la velocidad máxima de un enlace de 100 Mbit / s, con cifrado. Mi PC real, un Core2 común a 2.4 GHz, puede hacer un cifrado AES a 167 Mbytes por segundo (sí, megabytes , no megabits), más que suficiente para Gigabit Ethernet, y eso está usando un solo núcleo. - Tengo otros tres núcleos.

Si desea autenticar un cliente, el cliente debe debe tener algo especial que el usuario malintencionado previsto no tiene. Hablando criptográficamente, algunos datos secretos, que llamaremos una clave , porque esas son las claves: un fragmento de datos secretos, utilizados en un algoritmo que se supone no secreto. Tenga en cuenta que esto conlleva una falla estructural que no se puede evitar realmente: cualquier persona con acceso de lectura al código del cliente puede realizar ingeniería inversa y recuperar la clave. Esto se puede hacer un poco más difícil a través de técnicas de ofuscación de código, pero no hasta el punto de hacerlo imposible.

Además, desea autenticar la conexión , es decir, no solo el acto de iniciar el túnel de datos, sino también los datos que realmente se transfieren. De lo contrario, el atacante podría secuestrar la conexión una vez que se haya realizado el paso de autenticación. Esto implica el uso de una verificación de integridad criptográfica, que se denomina MAC . En ese punto, agregar cifrado es fácil. SSH utiliza tanto el cifrado simétrico como un MAC.

Fuera de los bloques de construcción existentes, sugiero las siguientes soluciones:

  1. Use SSH. El cliente se conecta a través de SSH y utiliza una contraseña codificada para autenticarse (la contraseña es la clave que mencioné anteriormente). El mecanismo habitual de SSH evita los usuarios intermedios, es decir, el cliente SSH debe guardar una copia de la clave pública del servidor.

  2. Use SSL / TLS. Esto es muy similar a lo que sucede con SSH. El cliente sabe que habla con el servidor correcto porque la clave pública del servidor se presenta como parte de un certificado X.509, que está firmado y puede ser validado por el cliente. El cliente debe tener conocimiento de la clave pública de la autoridad de certificación. Alternativamente, el cliente ya puede conocer el certificado del servidor y simplemente verificar que este sea el mismo certificado que el enviado por el servidor. Una vez que se establece el túnel, con el cifrado y las comprobaciones de integridad, el cliente puede simplemente enviar su clave "tal cual" para probar su identidad.

  3. Use SSL / TLS con un certificado de cliente. En esta configuración, el cliente tiene un par de claves pública / privada. La clave privada es la clave de la que estaba hablando. La clave pública se codifica en un certificado que el cliente muestra durante el protocolo de enlace SSL. Todo esto es material SSL estándar, por lo tanto, es compatible con las bibliotecas SSL existentes. En comparación con la solución 2, esto evita la necesidad de incluir un mensaje de envío de clave en su protocolo de aplicación, y también permite el uso de conjuntos de cifrado solo para MAC, en caso de que resulte que el cifrado sea demasiado costoso computacionalmente (lo cual dudo) .

  4. Use la clave del cliente en un Cambio de clave autenticado por contraseña para obtener una clave de sesión común , luego se utiliza para un MAC (y posiblemente encriptación). El punto de los protocolos PAKE es que pueden tolerar secretos de baja entropía, es decir, contraseñas que encajan en el cerebro de los usuarios humanos. La ejecución de un túnel con MAC tiene algunas sutilezas, por lo que la forma correcta es utilizar un protocolo existente. A continuación, esto requiere TLS con SRP . La "contraseña" está codificada en el cliente (y aunque SRP tolera contraseñas cortas, nada le impide usar una contraseña larga y muy aleatoria). La belleza de la cosa es que esto suprime cualquier eliminación con certificados o claves públicas conocidas. El cliente se autentica en virtud de su conocimiento de la contraseña. Al mismo tiempo, el servidor es también autenticado por contraseña por el cliente. Como beneficio adicional, con SRP, el servidor solo almacena una parte de los datos derivados de la contraseña, que el cliente no puede utilizar directamente, por lo que un atacante que lee la base de datos del servidor no obtiene acceso automático como "cliente".

Mi solución favorita es, por supuesto, la que tiene SRP. Es elegante . Desafortunadamente, SRP es bastante nuevo, por lo que no todas las implementaciones de SSL / TLS lo soportan. Pero GnuTLS sí.

    
respondido por el Thomas Pornin 13.01.2011 - 21:30
fuente
1

Cuando todo está dicho y hecho, no hay una manera real de evitar que un cliente de terceros se conecte al puerto si todo está diseñado para ejecutarse sin interacción humana.

La única forma de evitar este problema es si tiene un sistema no hackeable (o más precisamente, más difícil de piratear) que proporciona la pieza de identificación, es decir, un usuario, y esas credenciales se transfieren en un cifrado / hash camino. Si alguna información "secreta" que planea usar como credencial se almacena dentro de la aplicación de alguna manera, un usuario malintencionado podrá acceder a esa información.

    
respondido por el Steve 13.01.2011 - 20:47
fuente

Lea otras preguntas en las etiquetas