Gunicorn: La configuración predeterminada de cifrados SSL desactiva los cifrados más seguros

Creado en 23 ene. 2019  ·  3Comentarios  ·  Fuente: benoitc/gunicorn

El valor predeterminado para la opción --ciphers es TLSv1 .

Este valor es un valor predeterminado incorrecto, porque desactiva activamente cifrados nuevos y sólidos que solo están disponibles con TLSv1.2. En particular, no hay intersección entre el conjunto de cifrados configurados por este valor predeterminado y los cifrados clasificados A + por OWASP :

>>> import ssl
>>> ctx = ssl.SSLContext()
>>> ctx.set_ciphers('TLSv1')
>>> tlsv1 = {c['name'] for c in ctx.get_ciphers()}
>>> ctx.set_ciphers('DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256')  # From OWASP
>>> aplus = {c['name'] for c in ctx.get_ciphers()}
>>> aplus & tlsv1
set()

Esto puede provocar errores de OpenSSL NO_SHARED_CIPHER para clientes configurados con configuraciones de alta seguridad.

Una solución sería simplemente agregar cifrados TLSv1.2 al conjunto, cambiando el valor predeterminado a la cadena 'TLSv1:TLSv1.2' . Esto agregaría compatibilidad para clientes configurados con configuraciones de seguridad estrictas, sin romper a los usuarios existentes de gunicorn. Sin embargo, esto dejaría cifras débiles en el conjunto.

Una opción más segura sería elegir una de las cadenas de OWASP como predeterminada, según el nivel de compatibilidad descrito. Por ejemplo, OWASP Cipher String C o C- preservaría una amplia compatibilidad mientras descartaba los cifrados débiles conocidos.

En cualquier caso, la documentación podría actualizarse para recomendar reemplazar el valor predeterminado con un valor predeterminado más fuerte en función del uso esperado, incluido un enlace a la página OWASP como referencia.

Feedback Requested FeaturSSL

Comentario más útil

Además, Python tiene su propia lista de cifrado predeterminada: nunca vuelve al valor predeterminado de OpenSSL (que aparentemente es DEFAULT:!aNULL:!eNULL ). Es accesible como ssl._DEFAULT_CIPHERS aunque es interno / no documentado, por lo que la forma de acceder a los valores predeterminados es nunca llamar a set_ciphers () en un SSLContext.

Para Python 3.6 _DEFAULT_CIPHERS es

'TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:RSA+AESGCM:RSA+AES:RSA+HIGH:!aNULL:!eNULL:!MD5:!3DES'

En Python 3.7 es

'DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK'

con un comentario que dice "PREDETERMINADO: lista de cifrado predeterminada de OpenSSL. Desde 1.0.2 la lista está en orden sensato".

Estos ajustes parecen ser bastante ajustados y con el mismo espíritu que el OWASP.

También hay un _RESTRICTED_SERVER_CIPHERS que está diseñado para usarse en servidores (tan perfecto para gunicorn) y es más ajustado que _DEFAULT_CIPHERS en algunas versiones de Python, pero es interno y no se usa en ninguna parte, pero ha sido mantenido desde al menos 3.4.

Entonces, la opción 3 es predeterminada para el conjunto de cifrado predeterminado de Python.

La única razón para no hacerlo es si pensamos que hoy podríamos enviar una lista que sea más segura que la de las versiones anteriores de Python, o que queremos optar por uno de los niveles de OWASP aún más estrictos. Honestamente, eso es bastante marginal.

Todos 3 comentarios

Gracias por informar de este problema. Somos absolutamente conscientes de esto. Gunicorn no ha tenido cambios significativos en su soporte SSL durante un tiempo. Vea el n. ° 1933 y los temas vinculados en esa discusión.

Mientras tanto, si hay un valor predeterminado más sensato ahora que Gunicorn solo admite Python 3.4+, envíe una solicitud de extracción y con gusto lo fusionaré. También estamos considerando impulsar esa versión mínima más alta, por lo que si hay una versión mínima de Python más alta que permitiría un valor predeterminado aún más seguro, publique esa información aquí para ayudar a tomar esa decisión antes de la próxima versión.

Los cifrados disponibles (y la interpretación del argumento de SSLContext.set_ciphers() ) no se ven afectados por la versión de Python, sino por la versión de OpenSSL / LibreSSL con la que Python construye. En Linux, esa suele ser la versión proporcionada por la distribución.

Si su pregunta es "¿podemos establecer un valor predeterminado más seguro que siempre funcione en Python 3.4+", entonces la respuesta estricta es "no" porque depende de cómo haya compilado Python? Puede ser posible compilar un Python reciente contra un OpenSSL muy antiguo que carece de cifrados fuertes, por lo que requerir cifrados fuertes en gunicorn podría significar que SSL no funciona en absoluto.

Sin embargo, creo que estamos bastante a salvo. Python 3.4 se lanzó en 2014, mientras que OpenSSL 1.0.1a, que agregó TLSv1.2, se lanzó en abril de 2012. Por lo tanto, las versiones de distribución de Python probablemente tendrán cifrados sólidos. La otra cosa es que cada lanzamiento de Python requiere una determinada versión de OpenSSL (por ejemplo, Python 3.7 requiere OpenSSL 1.0.2, lo entiendo), pero no sé exactamente qué versiones de Python requieren qué.

En general, tendría que ser guiado por OWASP. Dicen que C- es "Heredado, la compatibilidad más amplia con navegadores antiguos reales y bibliotecas heredadas", con la ventaja adicional de que se pueden citar como fuente.

Además, Python tiene su propia lista de cifrado predeterminada: nunca vuelve al valor predeterminado de OpenSSL (que aparentemente es DEFAULT:!aNULL:!eNULL ). Es accesible como ssl._DEFAULT_CIPHERS aunque es interno / no documentado, por lo que la forma de acceder a los valores predeterminados es nunca llamar a set_ciphers () en un SSLContext.

Para Python 3.6 _DEFAULT_CIPHERS es

'TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:RSA+AESGCM:RSA+AES:RSA+HIGH:!aNULL:!eNULL:!MD5:!3DES'

En Python 3.7 es

'DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK'

con un comentario que dice "PREDETERMINADO: lista de cifrado predeterminada de OpenSSL. Desde 1.0.2 la lista está en orden sensato".

Estos ajustes parecen ser bastante ajustados y con el mismo espíritu que el OWASP.

También hay un _RESTRICTED_SERVER_CIPHERS que está diseñado para usarse en servidores (tan perfecto para gunicorn) y es más ajustado que _DEFAULT_CIPHERS en algunas versiones de Python, pero es interno y no se usa en ninguna parte, pero ha sido mantenido desde al menos 3.4.

Entonces, la opción 3 es predeterminada para el conjunto de cifrado predeterminado de Python.

La única razón para no hacerlo es si pensamos que hoy podríamos enviar una lista que sea más segura que la de las versiones anteriores de Python, o que queremos optar por uno de los niveles de OWASP aún más estrictos. Honestamente, eso es bastante marginal.

¿Fue útil esta página
0 / 5 - 0 calificaciones