it-swarm-es.com

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

Digamos que tengo un servidor que escucha en el puerto 1234. Tengo algún software cliente que necesita para poder conectarse a este puerto. Pero quiero evitar que los usuarios malintencionados pasen por alto el software del cliente y se conectan al puerto por algún otro medio (como en una consola u otra pieza de software).

El software de confianza de confianza y el servidor pueden compartir una clave secreta, si es necesario (puedo vivir con la posibilidad de que la clave pueda extraerse del binario). Preferiría no enviar dicha clave en texto plante, pero los datos después de la autenticación pueden estar en texto plante. Específicamente, estoy tratando de averiguar cómo derrotar a un ataque de hombre en el medio donde el usuario malicioso está utilizando el software de cliente confiable para calcular las respuestas correctas a los desafíos del servidor.

¿Puedo llegar desde aquí?

Podría hacer que el puerto de audición del servidor se une solo a localhost y requiera que los clientes primero obtengan acceso a la máquina a través de SSH. Luego, el software del 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 malicioso no podrá 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 superior adicional. Tal vez haya un programa similar a SSH que solo hace la autenticación, pero luego deja el canal en texto plano después de eso?

Actualizar:

Corrí una prueba para determinar la sobrecarga asociada con el cifrado todo el tráfico.

spew.RB Sale 10 millones de líneas de 100 caracteres.

CONTROL:

[email protected]> time /home/fantius/spew.rb > /dev/null

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

los principales muestran un consumo de CPU del 25% (un núcleo completo, de cuatro núcleos)

PRUEBA:

[email protected]> time ssh localhost /home/fantius/spew.rb > /dev/null

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

top Muestra el uso del 45% de la CPU (casi dos núcleos completos)

Esa tasa de mensaje probablemente excede la mayoría de las conexiones entre máquinas.

6
Fantius

Primero, sugiero evitar las suposiciones sobre la sobrecarga del cifrado. Debe Mida . Mi PC desde 2001 ya fue lo suficientemente poderosa como para transferir datos con SSH a toda velocidad de un enlace de 100 Mbit/s, con cifrado. Mi PC real, un núcleo común2 a 2.4 GHz, puede hacer el cifrado AES a 167 Mbytes por segundo (sí, Megabytes , no megabits), más que suficiente Para Gigabit Ethernet, y eso está utilizando un solo núcleo, tengo otros tres núcleos.

Si desea autenticar a un cliente, el cliente debe tener algo especial que el usuario malintencionado previsto no lo haya imaginado. Cryptográficamente hablando, algunos datos secretos, que llamaremos una clave porque eso es lo que las claves son: una pieza de datos secretos, utilizados en un algoritmo que Se asume no secreto. Tenga en cuenta que esto implica una falla estructural que no se puede evitar realmente: cualquier persona con acceso de lectura al código del cliente puede realizar alguna ingeniería inversa y recuperar la tecla. Esto se puede hacer un poco más difíciles a través de las 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 usar una verificación de integridad criptográfica, que se llama A [~ # ~] MAC [~ # ~ ~] . En ese momento, agregar cifrado es fácil. SSH usa tanto el cifrado simétrico como una Mac.

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

  1. Usa SSH. El cliente se conecta a través de SSH y utiliza una contraseña de codificación dura para autenticarse (la contraseña es la clave de la que estaba hablando más arriba). El hombre en el Medio está evitado por el mecanismo habitual de SSH, es decir, el cliente SSH debe mantener 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 verifique que este sea el mismo certificado que el enviado por el servidor. Una vez que se establece el túnel, con cheques de cifrado e integridad, el cliente puede simplemente enviar su clave "tal como está" para demostrar su identidad.

  3. Use SSL/TLS con un certificado de cliente. En esta configuración, el cliente tiene un par de claves públicas/privadas. 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 apretón de manos SSL. Todo esto son cosas SSL estándar, por lo tanto, respaldadas por las bibliotecas SSL existentes. En comparación con la solución 2, esto evita la necesidad de incluir un mensaje de envío de teclas en el protocolo de su aplicación, y también permite el uso de suites de cifrado solo de MAC, en caso de que resulte que el cifrado es demasiado computacional (que dudo) .

  4. Use la tecla del cliente en A intercambio de claves autenticados de la contraseña para obtener una clave de sesión común, luego se usa para una MAC (y posiblemente el cifrado). El punto de los protocolos de paquee es que pueden tolerar los secretos de baja entropía, es decir, contraseñas que encajan en el cerebro de los usuarios humanos. Ejecutar un túnel macizado tiene algunas sutilezas por lo que la forma correcta es usar un protocolo existente. Esto luego requiere TLS con SRP . La "Contraseña" está codificada en el cliente (y aunque SRP tolera las contraseñas cortas, nada le impide que use una contraseña larga y muy aleatoria). La belleza de la cosa es que esto suprime cualquier pastilla con certificados o claves públicas conocidas. El cliente se autentica en virtud de su conocimiento de la contraseña. Simultáneamente, el servidor es también Autenticado por la contraseña por parte del cliente. Como una bonificación adicional, con SRP, el servidor solo almacena una pieza de datos derivada de contraseña, que no es directamente utilizable por el cliente, 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 de SRP. Es elegante . Desafortunadamente, SRP es bastante nuevo, por lo que no toda la implementación de SSL/TLS lo respalda. Pero gnutls lo hace.

8
Thomas Pornin

Cuando todo está dicho y hecho, no hay una forma 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 en que podría prevenir este problema es si tiene un sistema no hackeable (o más precisamente, más difícil de hackear) que proporciona la pieza de identificación, es decir, un usuario, y esas credenciales se transfieren de forma encriptada/hash. Si alguna forma de información "secreta" que usted planea utilizar como credencial se almacena dentro de la aplicación, algunos de los que, un usuario malicioso podrá acceder a esa información.

1
Steve