[LinuxFocus-icon]
Hogar  |  Mapa  |  Indice  |  Busqueda

Noticias | Arca | Enlaces | Sobre LF
Este documento está disponible en los siguientes idiomas: English  Castellano  Deutsch  Francais  Nederlands  Turkce  

convert to palmConvert to GutenPalm
or to PalmDoc

Bernard Perrot
por Bernard Perrot
<bernard.perrot(at)univ-rennes1.fr>

Sobre el autor:
Bernard ha sido el Ingeniero de red y sistemas del CNRS (Centro Nacional de Investigaciones Científicas de Francia) desde 1982. Ha estado a cargo de los proyectos relativos a la seguridad del sistema informático en el "Instituto nacional de física nuclear y física de las partículas" (In2p3). Ahora, trabaja para el Instituto de investigación matemática (IRMAR) en el Departamento de ciencias físicas y matemáticas (SPM).



Taducido al español por:
Javier Gómez Sierras <jgomsi(at)obelix.umh.es>

Contenidos:

 

Asegurando tus conexiones con SSH

ssh

Resumen:

Este artículo se publicó por primera vez en un número especial de Linux Magazine France enfocado a la seguridad. El editor, los autores y los traductores permitieron amablemente a LinuxFocus publicar todos los artículos de este número especial. En consecuencia, LinuxFocus los publicará tan pronto como estén traducidos al inglés. Gracias a todas las personas implicadas en este trabajo. Este resumen se mostrará en todos los artículos que procedan de la misma fuente.

El propósito de este artículo es realizar un buen repaso de SSH, y por qué se usa. Esto no es un manual o guía de instalación, sino una introducción al vocabulario y las características de SSH. Los enlaces y la documentación que aparecen durante todo el artículo, te darán todos los detalles de la implementación.


_________________ _________________ _________________

 

¿Para qué se usa SSH?

Primero de todo (e históricamente), SSH (el comando ssh) es una versión segura de los comandos rsh (y rlogin). SSH significa "Secure SHell -- shell segura" y rsh significa "Remote SHell -- shell remota". Por lo tanto, mientras que rsh te da un acceso a una shell remota fácilmente, pero sin un mecanismo de autentificación de usuario, ssh proporciona el mismo servicio pero con una seguridad multinivel muy alta.

Si quisiéramos dar una explicación muy breve a un usuario que no quiere saber nada más (o hacer nada más), uno se podría para aquí y decir el administrador ha hecho su trabajo y ha instalado el software (esto es bastante fácil hoy en día), todo lo que tienes que hacer es reemplazar los comandos telnet, rsh o rlogin por el comando ssh, y todo funcionará igual pero con más seguridad.

Por lo tanto, donde hacías:

% rlogin servidor.org (o telnet servidor.org)

ahora tienes que hacer:

% ssh servidor.org

¡y es mucho mejor!

Para terminar este breve resumen, sugeriré que hoy en día, todos los incidentes de seguridad que podrían haber sido evitados simplemente usando SSH en vez de rsh (rlogin,telnet) son principalmente consecuencia de la negligencia de las víctimas.

 

¿Qué se necesita?

Para ver los detalles, aquí tienes algunos de los aspectos más importantes y frágiles de las conexiones interactivas que uno quiere ver resueltos:

Para responder a estas necesidades, existen algunas soluciones que no son del todo satisfactorias:

Y tenemos SSH, una buena solución para:

SSH versión 1 y SSH versión 2

Como nada en este mundo es perfecto, existen dos versiones incompatibles del protocolo SSH: la versión 1.x (1.3 y 1.5) y la versión 2.0. Pasar de una versión a la otra no es doloroso para el usuario, teniendo a mano el cliente correcto y el servidor correcto compatible con la versión.

La versión 1 del protocolo SSH está integrada, mientras que la versión 2 ha definido el protocolo anterior en tres "capas":

  1. Capa de transporte del protocolo SSH (SSH-TRANS)
  2. Autentificación del protocolo SSH (SSH-AUTH)
  3. Conexión del protocolo SSH (SSH-CONN)

Cada capa del protocolo está definida específicamente en un documento (borrador) normalizado por la IETF, seguido de un cuarto borrador que describe la arquitectura (Arquitectura del protocolo SSH, SSH-ARCH). Se pueden encontrar todos los detalles en: http://www.ietf.org/html.charters/secsh-charter.html

Sin meternos en muchos detalles, aquí tienes lo que encontrarás en SSHv2:

Las principales diferencias técnicas entre la versión 1 de SSH y la versión 2 son:

SSH versión 1

SSH versión 2

diseño monolítico (integrado)

separación de las funciones de autentificación, conexión y transporte en capas

integridad via CRC32 (no seguro)

integridad via HMAC (cifrado hash)

un único canal por sesión

un número ilimitado de canales por sesión

negociación usando únicamente cifrado simétrico en el canal, identificación de sesión con una única clave en ambos lados

negociación más detallada (cifrado simétrico, llave pública, compresión, ...), y una clave de sesión independiente, compresión e integridad en ambos lados

sólo RSA para el algoritmo de clave pública

RSA y DSA para el algoritmo de clave pública

clave de sesión transmitida por el cliente

clave de sesión negociada por el protocolo Diffie-Hellman

clave de sesión válida para toda la sesión

clave de sesión renovable

 

Manejando un montón de claves

Tipos de claves SSH, las definiré rápidamente:

El usuario añade una frase de paso (pass phrase) que protege la parte privada de las anteriores claves. Esta protección se asegura cifrando el fichero que contiene la clave privada con un algoritmo simétrico. La clave secreta usada para cifrar el fichero se deriva de esta frase de paso.

Métodos de autentificación

Hay varios métodos de autentificación de usuario, la elección depende de la necesidades definidas en las políticas de seguridad. Los métodos autorizados se activan o no en el fichero de configuración del servidor. Aquí están las principales categorías:

También, es útil saber al menos dos elementos más referentes a la autentificación:

 

Los algoritmos de cifrado

Se debe distinguir entre los que cifran los canales de comunicación (cifrando con claves secretas) y los que se usan para la autentificación (cifrando con claves públicas).

Para la autenticación, podemos elegir entre RSA y DSA con la versión 2 del protocolo, y únicamente RSA con la versión 1 (no hay elección posible...). Históricamente se eligió DSA porque RSA estaba patentado en algunos países. Desde finales del verano del año 2000, RSA está libre de derechos, y por lo tanto esta restricción ha desaparecido. No tengo preferencia sobre si la elección buena y la mala (y más cuando DSA es un producto "puro" de la NSA, aunque halla sido esta quien lo ha puesto directa o indirectamente a disposición de la criptografía pública y comercial...¿?)

Para el cifrado simétrico existen casi demasiados donde elegir... El protocolo impone un algoritmo común que tiene que estar presente en todas las implementaciones : el triple-DES con tres claves. En consecuencia, siempre se usará si la negociación entre el cliente y el servidor falla con los otros algoritmos. Si puedes, prueba a negociar con otro algoritmo, que será mejor, ya que que 3DES es hoy en día uno de los algoritmos de menor rendimiento. No obstante dejaremos de lado, a menos que sea necesario, los exóticos o antiguos (arc4, DES, RC4, ...) y nos limitaremos a:

Personalmente, me pregunto a mi mismo sobre el interés que tiene proponer tanto algoritmos: incluso aunque el protocolo permite la posibilidad de negociar "uno privado" ( para un grupo particular de usuarios, por ejemplo), algo que me parece esencial, pero para el uso normal, creo que con el tiempo, AES está llamado a convertirse en el estándar. Si AES fuera comprometido, entonces los problemas de seguridad serían mucho mayores que los que pudiese inducir SSH...

 

Redirección de puertos, túneles

SSH permite la redirección (forwarding) de cualquier flujo de datos TCP a través de un "túnel" en una sesión SSH. Esto significa que el flujo de datos de la aplicación, en vez de ser gestionada directamente por los puertos del servidor y el cliente, es "encapsulada" en un "túnel" creado al conectar (inicio de sesión) (ver el siguiente diagrama).

Esto mismo se hace con el protocolo X11 sin ningún esfuerzo especial (por parte del usuario), con un manejo transparente de los displays y la capacidad de propagarse continuamente cuando se realizan varias conexiones.

Para otros flujos, existe una opción de línea de comandos, para cada lado:

Esta potente característica ha llevado algunas veces a calificar a SSH como "un túnel para pobres". Se debe comprender que la pobreza aquí significa: aquellos que no tienen privilegios de administrador en el lado cliente. Sólo en casos particulares se puede redirigir un puerto local con menos privilegios ( puertos > 1024) y sin privilegios de superusuario ("root"). Por otro lado, cuando se necesita redirigir un puerto local con privilegios, se tiene que hacer con la cuenta de root, o el cliente debe tener privilegios de superusuarios ("suid") (De hecho, un puerto local privilegiado permite la redefinición de un servicio estándar).

Como con IP, es bastante fácil meter cualquier cosa en cualquier cosa (y lo contrario), no solo es posible redirigir un flujo TCP, sino también las conexiones PPP, lo que nos permite hacer un túnel IP "real" en IP (que está cifrado, por lo tanto seguro). El método excede el objetivo de este artículo, pero puedes leer el "Linux VPN-HOWTO" para conocer los detalles y obtener scripts de instalación (también podrás encontrar soluciones nativas VPN para Linux, como "stunnel" que deberías considerar antes de realizar la elección final).

Ten presente que la primera posibilidad es redirigir los flujos de telnet: Esto podría parecer totalmente inútil, ya que SSH implementa una conexión interactiva por defecto. Sin embargo, al redirigir las conexiones telnet, podrías usar tu cliente favorito en vez del modo SSH interactivo. Esto es realmente valioso en entornos Windowstm o MacOStm donde los clientes SSH puede que no se adecuen a la ergonomía preferida por el usuario. Por ejemplo, la "emulación de terminal" parte del cliente "Mindterm" (cliente SSH en Java, presente en todos los sistemas modernos) sufre la escasez de rendimiento del lenguaje Java: puede ser ventajoso usar este cliente únicamente para abrir un túnel SSH.

De la misma manera, también puedes iniciar un cliente remoto como "xterm" (por ejemplo, usando redirección X11 automática -- automatic X11 forwarding -- en SSH), lo que nos permite usar SSH en terminales X.

Ten en cuenta que el túnel permanece abierto mientras halla un flujo de datos, incluso aunque no venga del que lo inició. Por lo tanto, el comando "sleep" es muy útil para abrir un túnel SSH para redirigir una nueva conexión TCP.

% ssh -n -f -L 2323:serveur.org:23 serveur.org sleep 60

% telnet localhost 2323

... bienvenido a serveur.org ...

La primera línea abre el túnel, lanza el comando "sleep 60" en el servidor, y redirige el puerto local número 2323 al puerto remoto (telnet) número 23. El segundo inicia un cliente telnet en el puerto local número 2323, y entonces usará el túnel (cifrado) para conectarse al demonio telnetd del servidor. El comando "sleep" terminará después de un minuto (tienes sólo un minuto para iniciar telnet) , pero SSH sólo cerrará el túnel cuando el último cliente halla terminado.

 

Principales distribuciones: disponibles gratuitamente

Tenemos que distinguir entre los clientes y/o servidores en las diferentes plataformas y deberías saber que la SSH versión 1 y SSH versión 2 son incompatibles. Las referencias al final del artículo te ayudarán a encontrar otras implementaciones, que no se incluyen en la siguiente tabla que se limita a los productos gratuitos con características suficientemente estables.

producto

plataforma

protocolo

enlace

notas

OpenSSH

Unix

versiones 1 y 2

www.openssh.com

detalles debajo

TTSSH

Windowstm

versión 1

www.zip.com.au/~roca/ttssh.html

 

Putty

Windowstm

versiones 1 y 2

www.chiark.greenend.org.uk/~sgtatham/putty

sólo beta

Tealnet

Windowstm

versiones 1 y 2

telneat.lipetsk.ru

 

SSH secure shell

Windowstm

versiones 1 y 2

www.ssh.com

gratuito para uso no comercial

NiftytelnetSSH

MacOStm

versión 1

www.lysator.liu.se/~jonasw/freeware/niftyssh/

 

MacSSH

MacOStm

versión 2

www.macssh.com

 

MindTerm

Java

versión 1

www.mindbright.se

v2 ahora comercial

Ten en cuenta que MindTerm es tanto una implementación independiente en Java (sólo necesitas el runtime de Java ) como un servlet que se puede ejecutar dentro de un un navegador web compatible y bien diseñado. Desafortunadamente, las últimas versiones de esta excelente distribución han pasado a ser productos comerciales.

 

OpenSSH

Hoy en día esta distribución es probablemente la que se debe usar en entornos Unix/Linux (soporte continuo, buen tiempo de respuesta, código abierto y gratuito).

El desarrollo de OpenSSH comenzó con la versión original (SHH 1.2.12) de Tatu Ylonen (la última realmente libre) en el proyecto OpenBSD 2.6 (via OSSH). Ahora, OpenSSH es desarrollado por dos grupos, uno desarrollando únicamente para el proyecto OpenBSD, y otro adaptando continuamente el código para hacer una versión portable.

Todo esto tiene algunas consecuencias, particularmente, el código es cada vez más y más una monstruosa adaptación constante (noto el síndrome "sendmail" apareciendo en el horizonte) y esto no es saludable para una aplicación dedicada al cifrado que debería ser extremadamente rigurosa y clara.

Además de una programación limpia y legible, otros dos puntos me molestan:

En mi opinión (y no soy el único), un producto de cifrado multiplataforma debería tener un comportamiento demostrado, determinado y constante independientemente de la plataforma, así como tomar en cuenta (eliminando) las características particulares de la plataforma y su evolución.

Dicho esto, tenemos que admitir que, las implementaciones de la competencia no son ni numerosas ni atractivas. Creo que es más pragmático considerar que hoy en día OpenSSH es la peor implementación ¡si excluimos al resto...! Un proyecto muy útil para la comunidad sería el rediseño y reescritura del código.

 

Malas noticias...

¡SSH no es milagroso! Cumple bien la tarea para la que fue diseñado, pero no le puedes pedir más. Particularmente no evitará conexiones "autorizadas": si una cuenta es comprometida, el intruso podrá conectarse via SSH a tu máquina, aunque este sea el único método, ya que controla la autentificación. Sólo se puede confiar totalmente en SSH si va acompañado de una política de seguridad práctica y coherente: si alguien usa la misma contraseña para todo, y no usa SHH en todos lados, el riesgo potencial sólo disminuye ligeramente. Podemos admitir que en esta situación SSH se puede "volver contra tí" ya que el intruso puede usar una conexión segura cifrada con un túnel, y podrá hacer casi todo lo que quiera sin que puedas rastrearlo de forma eficiente.

De la misma manera, uno debe tener en cuenta también los "rootkits" bien hechos que normalmente contienen un demonio SSH para hacer volver discretamente a tu sistema, pero con unas pocas modificaciones: por supuesto no escucha en el puerto 22, tiene la delicadeza de no loguear, se llama como un demonio ordinario ( por ejemplo httpd), e invisible para el comando "ps" (que también ha sido modificado de alguna manera por el rootkit).

Al contrario, uno no debe estar demasiado preocupado por el peligro que puede representar un demonio SSH que puede permitir a los intrusos estar más cubiertos todavía: deberías saber (espero) que es posible meter casi cualquier cosa en casi cualquier cosa en IP, incluyendo la "apropiación indebida" de protocolos esenciales a través de un cortafuegos: tunelización de HTML, tunelización de ICMP, tunelización de DNS, .... Así que no enciendas el ordenador si quieres un sistema 100% seguro ;-).

SSH no está exento de "agujeros" de seguridad derivados de la implementación (muchos han sido corregidos en el pasado, no hay programa perfecto), pero también a nivel de protocolo. Estos "agujeros", aunque se anuncien como muy alarmantes, normalmente afectan a debilidades que son difíciles de utilizar lo que hace que su manipulación sea técnicamente compleja: uno debe tener en mente que los incidentes de seguridad que podrían haber sido evitados por el uso de SSH son diarios, mientras que aquellos que estarían causados por puntos débiles de SSH son de alguna manera teóricos. Sería interesante leer el estudio relativo a ataques "man in the middle": http://www.hsc.fr/ressources/presentations/mitm/index.html. No obstante será necesario tener en cuenta este tipo de vulnerabilidades potenciales para las aplicaciones de "alta seguridad" (banca, militares, ....), donde los medios usados por el cracker, altamente motivado por el premio y el beneficio, pueden ser considerables.

Me gusta señalar a menudo una debilidad incomprensible del protocolo respecto al "relleno -- padding" (conocido como canal cubierto): tanto en la versión 1 y 2 los paquetes, tienen una longitud que el múltiplo de 64 bits, si son rellenados con un número aleatorio. Esto es bastante inusual y por lo tanto da lugar a un fallo clásico que es bien conocido en las implementaciones de los productos de cifrado: un canal "oculto" (o "subliminal"). Normalmente, "rellenamos" con una secuencia verificada como por ejemplo, dar el valor n para el rango de bytes n (relleno autodescriptivo). En SSH, la secuencia siendo (por definición) aleatoria, no se puede verificar. Consecuentemente es posible que una de las partes en comunicación comprometiese la comunicación, por ejemplo como en el caso de una tercera parte que está a la escucha. Una también puede imaginar una implementación corrupta desconocida por las dos partes (fácil de realizar en un producto donde se proporcionen únicamente los binarios como en general es el caso de los productos comerciales). Esto se puede hacer fácilmente y en este caso uno sólo necesita "infectar" el cliente o el servidor. Dejar dicho increíble fallo en el protocolo, siendo universalmente conocido que la instalación de un canal cubierto en un producto de cifrado es EL método clásico y básico para corromper la comunicación, me parece increible. Puede ser interesante leer los comentarios de Bruce Schneier sobre la implementación de dichos elementos en productos influenciados por agencias gubernamentales. (http://www.counterpane.com/crypto-gram-9902.html#backdoors).

Para terminar quiero resaltar el error que encontré en el código de las versiones Unix anteriores a la 1.2.25, al realizar SSF, la adaptación francesa de SSH, y cuya consecuencia era que el generador de números aleatoreos producía... resultado... predecibles (esta situación es lamentable en un producto criptográfico, no entraré en detalles pero se podía comprometer una comunicación con simplemente capturar los datos). Por aquel entonces el equipo de desarrollo de SSH ya había corregido el problema (sólo había que modificar una línea), pero curiosamente sin enviar ninguna alerta, ni siquiera una mención en el "changelog" del producto... si no hubiesen querido que no se supiera, no habrían actuado de esa manera. Por supuesto esto no tiene ninguna relación con el enlace al artículo anterior.

Conclusión

Voy a repetir lo que escribí en la introducción: SSH, ni hace milagros, ni resuelve él solo todos los problemas de seguridad, pero hace posible el manejo eficiente de los aspectos más frágiles de los programas históricamente utilizados para las conexiones interactivas (telnet, rsh...).

Bibliografía, enlaces esenciales

Los dos siguientes libros cubren la versión 1 y 2 de SSH:

Y si te quieres gastar un poco de dinero, aquí tienes un sitio donde comenzar...:

 

Explotando el canal cubierto (inducido por el relleno aleatorio en SSHv1)

Aquí tienes un método para explotar el canal cubierto (subliminal) consecuencia del uso el relleno aleatorio en SSHv1 (y v2). Rechazo cualquier responsabilidad sobre los ataques de corazón que les puedan dar a los más paranoicos.

Los paquetes de SSHv1 tienen la siguiente estructura:

offset

(bytes)

nombre

longitud

(bytes)

descripción

0

tamaño

4

tamaño del paquete, tamaño del campo sin relleno, entonces:

tamaño = longitud(tipo)+longitud(data)+longitud(CRC)

4

relleno

p =1 a 8

relleno aleatorio : tamaño ajustado para que la parte cifrada sea múltiplo de ocho

4+p

tipo

1

tipo de paquete

5+p

datos

n (variable >= 0)

 

5+p+n

suma de control (checksum)

4

CRC32

Únicamente un campo no está cifrado: el "tamaño". La longitud de la parte cifrada es siempre un múltiplo de ocho, ajustada por el "relleno". El relleno siempre se realiza, si la longitud de los últimos tres campos es ya múltiplo de 8 entonces el relleno tendrá una longitud de ocho bytes (5+p+n resto 0 modulo 8). Sea la función de cifrado C, simétrica, usada en modo CBC, y la función de descifrado C-1. Para simplificar la demostración, cogeremos solo los paquetes con un relleno de ocho bytes. Cuando llega un paquete, en vez de rellenarlo con un número aleatorio, pondremos un valor C-1(M), de ocho bytes en este caso. Esto significa descifrar el mensaje M con la función C usada para cifrar el canal (el hecho de que M sea "descifrada" sin haber sido cifrada de antemano no tiene ninguna importancia desde un punto de vista estrictamente matemático, no voy a entrar en detalles aquí sobre la implementación). Lo siguiente es llevar a cabo el procesado normal del paquete, esto es, el cifrado en bloques de ocho bytes.

El resultado será el siguiente :

offset

contenidos

notas

0

tamaño

4 bytes no cifrado

4

relleno de 8 bytes (cifrado)

entonces C(C-1(M))

12... fin

tipo, datos, CRC

 

¿Qué es lo asombroso? El primer bloque cifrado contiene C(C-1(M)). Como C es una función de cifrado simétrica, entonces C(C-1(M)) = M. ¡Este primer bloque se envia sin cifrar en un flujo de datos cifrado! Eso simplemente significa que cualquier persona espiando la comunicación que conozca la estratagema sabrá como explotar la información. Por supuesto, uno puede asumir que el propio mensaje M está cifrado (mediante una clave pública, por ejemplo, lo que evita poner la clave dentro del código pervertido), lo que permite que alguien que no esté informado no la pueda descifrar.

Por ejemplo, son suficientes tres paquetes de este tipo para pasar la clave de sesión triple-DES (168 bit), tras los cuales el sniffer escuchando este flujo podrá descifrar toda la comunicación. A partir del momento en que la clave es transmitida, ya no es necesario "pre-descifrar" el relleno pervertido antes de inyectarlo al paquete, es posible usar rellenos de cualquier tamaño si uno quiere añadir incluso más información.

El uso de este canal cubierto es ¡absolutamente indetectable! (se debe tener cuidado al cifrar cada elemento del mensaje como se explicó previamente, para que la entropía del bloque no revele la estratagema). Indetectable porque el relleno es aleatorio, lo que elimina cualquier posibilidad de pruebas de validación. El Relleno Aleatorio nunca debería utilizarse en los productos de criptografía, nunca.

Lo que hace a este canal incluso más peligroso que otros en el protocolo es lo inducido por mensajes como SSH_MSG_IGNORE que es utilizable sin tener conocimiento de la clave cifrada.

Para evitar los perversos efectos del relleno aleatorio, uno simplemente debe definir en el protocolo el uso del relleno determinístico: normalmente llamado "self describing padding -- relleno autodescriptivo", lo que significa que el bit de offset n contiene n. El relleno aleatorio existe en SSH v2, es una elección, así que tenlo presente...

Para terminar, simplemente diré que si critico el canal cubierto, es porque me gustaría que un producto como SSH, que dice ser altamente seguro, realmente ofreciera un máximo de seguridad. Ahora eres capaz de imaginar que existen múltiples oportunidades potenciales de manipulación en los productos comerciales: solo los productos de código abierto pueden ofrecer una solución a un requisito indispensable, la posibilidad de revisar el código (incluso aunque dichas revisiones sean necesarias).

 

Formulario de "talkback" para este artículo

Cada artículo tiene su propia página de "talkback". A través de esa página puedes enviar un comentario o consultar los comentarios de otros lectores
 Ir a la página de "talkback" 

Contactar con el equipo de LinuFocus
© Bernard Perrot, FDL
LinuxFocus.org
Información sobre la traducción:
fr --> -- : Bernard Perrot <bernard.perrot(at)univ-rennes1.fr>
fr --> en: Guy Passemard <g.passemard(at)free.fr>
en --> es: Javier Gómez Sierras <jgomsi(at)obelix.umh.es>

2003-04-07, generated by lfparser version 2.34