Mostrando entradas con la etiqueta SSL/TLS. Mostrar todas las entradas
Mostrando entradas con la etiqueta SSL/TLS. Mostrar todas las entradas
Obtener SSL/TLS Ciphers Soportados
Ufff casi un año sin postear nada, desde que cambié de trabajo estoy extremadamente ocupado y no he tenido tiempo para postear, a pesar de que estuve viendo muchas cosas interesntes. Espero poder retomar un ritmo de post más seguido :)

Con el auge de las vulnerabilidades en TLS/SSL este último tiempo, tuvimos que ir ajustando el listado de ciphers varias veces, ya que los requerimientos son cada vez más exigentes. El problema es la compatibilidad con sistemas operativos/browsers más antiguos, que no soportan las versiones más nuevas de TLS (TLS 1.2) o ciphers más seguros.

Hoy les traigo algo que me sirvió mucho, que es listar los ciphers soportados por un servidor usando un simple script en bash que se basa en openssl. Si bien hay varias tools que hacen esta tarea, siendo la que más uso TestSSLServer, quería algo que pudiera ejecutar desde cualquier lugar, sin depender de tools externas o la instalación de java. OpensSSL está presente en toda las distribuciones, así que no necesitamos nada extra para correr este script.

El core del script lo encontré en este post de superuser, al cual le hice modificaciones para que OpenSSL use SNI, tenga un check básico de parámetros, permita pasar port por parámetro y reporte sólo los ciphers con resultado positivo. Sería un equivalente de TestSSLServer más básico, pero portable :D

#!/bin/bash -e

if [ "$1" == "" ]; then
    echo "usage: $0  [port]"
    exit
fi

if [ "$2" == "" ]; then
    PORT=443
else
    PORT=$2
fi

# OpenSSL requires the port number.
SERVER=$1:$PORT
DELAY=1
ciphers=$(openssl ciphers 'ALL:eNULL' | sed -e 's/:/ /g')

echo -n "Checking if server is up... "
result=$(echo -n | openssl s_client -connect $SERVER 2>&1)
if [[ "$result" =~ "Connection timed out" ]]; then
    echo "FAIL - connection time out"
    exit 1
fi
echo "OK"

echo "Obtaining cipher list from $(openssl version)."
for cipher in ${ciphers[@]}; do
    result=$(echo -n | openssl s_client -cipher "$cipher" -servername $SERVER -connect $SERVER 2>&1 || echo "")
    if [[ "$result" =~ "Cipher is ${cipher}" || "$result" =~ "Cipher    :" ]] ; then
        echo $cipher
    fi
    sleep $DELAY
done
Crear una CA con OpenSSL y firmar/revocar certificados con ella
Ya es el 4to  artículo (o fueron más?) que escribo sobre certificados digitales, y sin embargo siempre me encuentro con algún requerimiento nuevo. Esta vez necesitaba crear una CA propia para firmar mis certificados, y como siempre, decidí utilizar OpenSSL.

En los siguientes pasos describiré cómo crear la susodicha CA y cómo firmar certificados con la misma.

Si les interesa, pueden dar un repaso a los otro artículos del tema:
- Certificados Digitales
- Firmando una CA propia
- Shortcuts: comandos OpenSSL para generar claves, certificados y testear conexiones


1. Configurar OpenSSL

El primero paso es copiar o editar la información en /etc/ssl/openssl.cnf. Son pocos los campos que es importante/requerido editar. El resto pueden modificarlos también, pero  la idea acá es mostrar los requerimientos mínimos.

En el archivo openssl.cnf buscar y editar los siguientes valores:
[ CA_default ]
dir             = /ca
...
new_certs_dir   = $dir/newcerts
certificate     = $dir/ca.crt
...
private_key     = $dir/ca.key
...
default_days    = 365
donde:
  • dir: directorio que alojará la información de la CA, como certificados firmados, base de datos, número de serie, etc.
  • new_certs_dir: donde se alojarán los certificados firmados.
  • certificate: ubicación del certificado de la CA.
  • private_key: la clave de la CA.
  • default_days: cantidad de días de validez de un certificado por default.
También será de mucha utilidad pegarle una mirada y editar lo siguiente:
[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = AR
countryName_min                 = 2
countryName_max                 = 2
stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = Buenos Aires
localityName                    = Locality Name (eg, city)
0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = Super CA
Estos datos facilitan la vida al generar certificados, ya que se tomarán por default y no habrá que cargarlos cada vez que se genere un nuevo request.

Una vez finalizada la edición, realizar lo siguiente en el directorio default (ver variable dir de la configuración):
  • crear los archivos de texto index.txt y serial:
    # touch /ca/index.txt /ca/serial
    donde:
    index.txt es la base de datos de certificados firmados por la CA.
    serial cotiene el número de serie que debe colocarle al próximo certificado que firme.
  • al archivo serial, agregarle un valor. Este será el número de serie que imprima al primer certificado que genere, luego lo actualizará solo. El valor debe ser de dos dígitos:
    echo "01" > /ca/serial
  • crear el directorio para los certificados nuevos, si es que todavía no existe. Para el ejemplo dado:
    # mkdir /ca/newcerts

2. Generar clave y certificado de CA

Claramente la CA debe contar con su propia clave y certificado. Estos se utilizarán para firmar los certificados que se requieran luego. La forma más rápida es utilizando un sólo comando:
# openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /ca/ca.key -out /ca/ca.crt -config /ca/openssl.cnf
Generating a 2048 bit RSA private key
...+++
..........................................+++
writing new private key to 'ca.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AR]:
State or Province Name (full name) [Buenos Aires]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Super CA]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:super-ca.com
Email Address []:
Como verán, el archivo de configuración hace que los valores de "Country Name", "State or Province Name", etc se tomen de ahí.


3. Firmar certificados

En los anteriores artículos expliqué cómo generar un request de certificado, por lo que no me explayaré en eso. Les dejo el siguiente comando que crea una clave y CSR, y además utiliza como template el archivo de configuración:
# openssl req -new -newkey rsa:2048 -keyout prueba.key -out prueba.csr -config /ca/openssl.cnf
Generating a 2048 bit RSA private key
......................................+++
....+++
writing new private key to 'prueba.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AR]:
State or Province Name (full name) [Buenos Aires]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Super CA]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:superprueba.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Ok, ahora si a lo bueno, con este simple comando podremos firmar los request de certificados que deseemos:
# openssl ca -cert /ca/ca.crt -keyfile /ca/ca.key -in prueba.csr -out prueba.crt -config /ca/openssl.cnf
Using configuration from /ca/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 2 (0x2)
Validity
   Not Before: Jan  5 15:40:56 2015 GMT
   Not After : Jan  5 15:40:56 2016 GMT
Subject:
   countryName               = AR
   stateOrProvinceName       = Buenos Aires
   organizationName          = Super CA
   commonName                = superprueba.com
X509v3 extensions:
   X509v3 Basic Constraints:
CA:FALSE
   Netscape Comment:
OpenSSL Generated Certificate
   X509v3 Subject Key Identifier:
EE:9C:75:57:66:F6:3E:FA:D9:CF:6F:06:60:E0:97:D1:EE:EC:14:EA
   X509v3 Authority Key Identifier:
keyid:98:7A:32:95:93:72:24:37:B0:16:61:10:8D:E7:51:5F:54:95:C7:62
Certificate is to be certified until Jan  5 15:40:56 2016 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

4. Revocar certificados

Finalmente, y porque seguro les sucederá en algún momento, veamos cómo revocar un certificado. Es tan simple como ejecutar el siguiente comando:
# openssl ca -revoke prueba.crt -config /ca/openssl.cnf
Using configuration from /ca/openssl.cnf
Revoking Certificate 01.
Data Base Updated
Si miran el archivo index.txt, podrán observar una R al principio de la línea del certificado.

Un tip interesante, es qué pasa si no tenemos el certificado que queremos revocar. En este post de stackoverflow explican una forma de hacerlo.
OpenSSL guarda una copia de los certificados que firma en el directorio "newcerts" (o donde lo hayan configurado en openssl.cnf). Los certificados se guardan con el número de serie como nombre, por lo que primero hay que hayar el número de serie del certificado que queremos revocar. Un simple grep puede ayudarnos en este caso:
# grep "prueba" /ca/index.txt
V       160105143331Z           01      unknown /C=AR/ST=Buenos Aires/O=Super CA/CN=prueba
donde vemos que el ID es 01.
Con esta info, ejecutamos el comando anterior de la siguiente manera:
# openssl ca -revoke newcerts/01.pem -config /ca/openssl.cnf

Referencias

How To Setup a CA
POODLE Attack (die SSLv3!)
Leyendo noticias de seguridad, me topé con este interesante ataque que afecta la versión SSLv3 y permite a un atacante desencriptar porciones de tráfico HTTPS, como por ejemplo cookies.

Últimamente al pobre protocolo no le ha ido muy bien, basta recordar el mortal Heartbleed descubierto hace unos meses, y otros ataques como BEAST y CRIME descubiertos hace un par de años, o Lucky-13, por citar algunos.

Una de las personas que participó en el descubrimiento de esta vulnerabilidad es Thai Duong, quien también participó (junto a Juliano Rizzo) en el descubrimiento de BEAST y CRIME. En este caso, Thai trabajó con otros empleados de Google (Bodo Möller y Krzysztof Kotowicz) para el descubrimiento.

Como mencioné al principio, el ataque afecta sólo a SSLv3, el cual está obsoleto desde hace unos años, pero que todavía es soportado por muchos servidores y browsers por compatibilidad. La versión más actual del protocolo es TLSv1.2, pero los clientes pueden negociar con el servidor una versión inferior del protocolo, en caso de no soportar esta última.

El ataque no es tan directo como Heartbleed, ya que es necesario realizar previamente un ataque Man-in-the-Middle (MiTM). Pero un ataque MiTM no es tan complejo si tenemos acceso a la red de la víctima, o si accedemos a una red WiFi pública (hoteles, bares, etc).

Los detalles del ataque los pueden leer en el paper original, pero básicamente explota la encripción CBC utilizada en SSLv3, debido a la forma en que este algoritmo utiliza los paddings para completar bloques.

Según comentan en el paper, la única forma de evitar este ataque es eliminando el uso de SSLv3. En el mismo, proponen utilizar el mecanismo TLS_FALLBACK_SCSV para la negociación, en clientes y servidores. Utilizando TLS_FALLBACK_SCSV, el servidor siempre utilizará la versión más actual del protocolo habilitada en el mismo, rechazando cualquier intento de conexión con una versión inferior. Obviamente, si el servidor no soporta una versión superior a SSLv3, entonces será vulnerable igual.

Existen varios mecanismos para averiguar qué versiones de SSL/TLS soporta un servidor. Les dejo un par para que verifiquen sus servidores.

Una forma simple, es utilizar la capacidad de ejecución de scripts de NMAP, el cual todo administrador de seguridad tiene instalado:
$ nmap --script ssl-enum-ciphers -p 443 <IP Servidor>
Algo más avanzado es utilizar una herramienta dedicada a chequear conexiones SSL, denominada SSLyze, la cual pueden descargar aquí. Esta herramienta está escrita en python y se puede ejecutar sin instalarse:
$ python sslyze.py --regular <IP Servidor>:443
Finalmente y también muy interesante, es la herramienta web provista por Qualys, la cual chequea múltiples vulnerabilidades SSL, así como lista los protocolos soportados y genera un reporte. La misma se accede aquí.