Gunicorn: Die Standardeinstellung für SSL-Verschlüsselungen deaktiviert die sichersten Verschlüsselungen

Erstellt am 23. Jan. 2019  ·  3Kommentare  ·  Quelle: benoitc/gunicorn

Der Standardwert für die Option --ciphers ist TLSv1 .

Dieser Wert ist ein schlechter Standardwert, da er neue, starke Verschlüsselungen, die nur mit TLSv1.2 verfügbar sind, aktiv deaktiviert. Insbesondere gibt es keine Schnittmenge zwischen dem durch diesen Standardwert konfigurierten Chiffrensatz und den von OWASP mit A+ bewerteten Chiffren :

>>> 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()

Dies kann bei Clients mit hohen Sicherheitseinstellungen zu OpenSSL NO_SHARED_CIPHER Fehlern führen.

Eine Lösung wäre, einfach TLSv1.2-Chiffren zum Satz hinzuzufügen, indem Sie den Standard in die Zeichenfolge 'TLSv1:TLSv1.2' ändern. Dies würde die Kompatibilität für Clients erhöhen, die mit strengen Sicherheitseinstellungen konfiguriert sind, ohne vorhandene Benutzer von gunicorn zu beeinträchtigen. Dies würde jedoch schwache Chiffren in der Menge hinterlassen.

Eine sicherere Option wäre die Auswahl einer der OWASP-Zeichenfolgen als Standard, basierend auf dem beschriebenen Kompatibilitätsgrad. Zum Beispiel würde OWASP Cipher String C oder C- eine breite Kompatibilität bewahren, während bekannte schwache Chiffren ausgeschlossen werden.

In beiden Fällen könnte die Dokumentation aktualisiert werden, um zu empfehlen, den Standardwert basierend auf der erwarteten Nutzung durch einen stärkeren Standardwert zu ersetzen, einschließlich eines Links zur OWASP-Seite als Referenz.

Feedback Requested FeaturSSL

Hilfreichster Kommentar

Außerdem hat Python seine eigene Standard-Verschlüsselungsliste: Sie greift nie auf die Standardeinstellung von OpenSSL zurück (die anscheinend DEFAULT:!aNULL:!eNULL ). Es ist als ssl._DEFAULT_CIPHERS zugänglich, obwohl dies intern/undokumentiert ist. Daher können Sie auf die Standardeinstellungen zugreifen, indem Sie nie set_ciphers() in einem SSLContext aufrufen.

Für Python 3.6 ist _DEFAULT_CIPHERS

'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'

In Python 3.7 ist es

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

mit dem Kommentar "DEFAULT: OpenSSL's default cipher list. Seit 1.0.2 ist die Liste in sinnvoller Reihenfolge."

Diese Einstellungen scheinen ziemlich eng zu sein und im gleichen Sinne wie die OWASP.

Es gibt auch ein _RESTRICTED_SERVER_CIPHERS das für die Verwendung in Servern gedacht ist (also perfekt für Gunicorn) und in einigen Python-Versionen enger als _DEFAULT_CIPHERS , aber das ist sowohl intern als auch nirgendwo verwendet - wurde aber gepflegt seit mindestens 3.4.

Option 3 ist also standardmäßig die Standard-Verschlüsselungssammlung von Python.

Der einzige Grund, dies nicht zu tun, ist, wenn wir denken, wir könnten heute eine Liste liefern, die sicherer ist als die in älteren Python-Versionen, oder wenn wir uns für eine der noch engeren OWASP-Stufen entscheiden möchten. Das ist ehrlich gesagt ziemlich marginal.

Alle 3 Kommentare

Vielen Dank, dass Sie dieses Problem gemeldet haben. Wir sind uns dessen absolut bewusst. Gunicorn hat seit einiger Zeit keine wesentlichen Änderungen an seiner SSL-Unterstützung vorgenommen. Siehe #1933 und die in dieser Diskussion verlinkten Themen.

Wenn es in der Zwischenzeit eine sinnvollere Standardeinstellung gibt, da Gunicorn nur Python 3.4+ unterstützt, senden Sie bitte einen Pull-Request und ich würde ihn gerne zusammenführen. Wir erwägen auch, diese Mindestversion zu erhöhen. Wenn es also eine höhere Python-Mindestversion gibt, die einen noch sichereren Standard ermöglichen würde, posten Sie diese Informationen bitte hier, um diese Entscheidung vor der nächsten Version zu treffen.

Die verfügbaren Verschlüsselungen (und die Interpretation des Arguments zu SSLContext.set_ciphers() ) werden nicht von der Python-Version beeinflusst, sondern von der Version von OpenSSL/LibreSSL, auf der Python baut. Unter Linux wäre dies normalerweise die von der Distribution bereitgestellte Version.

Wenn Ihre Frage lautet: "Können wir einen sichereren Standard festlegen, der in Python 3.4+ immer funktioniert", lautet die strikte Antwort "Nein", da es davon abhängt, wie Sie Python kompiliert haben. Es ist möglicherweise möglich, ein aktuelles Python gegen ein sehr altes OpenSSL zu kompilieren, dem starke Verschlüsselungen fehlen. Wenn also starke Verschlüsselungen in gunicorn erforderlich sind, kann SSL überhaupt nicht funktionieren.

Ich denke jedoch, dass wir ziemlich sicher sind. Python 3.4 wurde 2014 veröffentlicht, während OpenSSL 1.0.1a, das TLSv1.2 hinzugefügt hat, im April 2012 veröffentlicht wurde. Daher werden Distributionsversionen von Python wahrscheinlich starke Verschlüsselungen haben. Die andere Sache ist, dass jede Python-Version eine bestimmte OpenSSL-Version erfordert (zB Python 3.7 erfordert OpenSSL 1.0.2, ich verstehe), aber ich weiß nicht genau, welche Python-Versionen was erfordern.

Insgesamt müsste ich mich von OWASP leiten lassen. Sie sagen, C- sei "Legacy, größte Kompatibilität zu echten alten Browsern und Legacy-Bibliotheken" - mit dem zusätzlichen Bonus, dass sie als Quelle angegeben werden können.

Außerdem hat Python seine eigene Standard-Verschlüsselungsliste: Sie greift nie auf die Standardeinstellung von OpenSSL zurück (die anscheinend DEFAULT:!aNULL:!eNULL ). Es ist als ssl._DEFAULT_CIPHERS zugänglich, obwohl dies intern/undokumentiert ist. Daher können Sie auf die Standardeinstellungen zugreifen, indem Sie nie set_ciphers() in einem SSLContext aufrufen.

Für Python 3.6 ist _DEFAULT_CIPHERS

'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'

In Python 3.7 ist es

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

mit dem Kommentar "DEFAULT: OpenSSL's default cipher list. Seit 1.0.2 ist die Liste in sinnvoller Reihenfolge."

Diese Einstellungen scheinen ziemlich eng zu sein und im gleichen Sinne wie die OWASP.

Es gibt auch ein _RESTRICTED_SERVER_CIPHERS das für die Verwendung in Servern gedacht ist (also perfekt für Gunicorn) und in einigen Python-Versionen enger als _DEFAULT_CIPHERS , aber das ist sowohl intern als auch nirgendwo verwendet - wurde aber gepflegt seit mindestens 3.4.

Option 3 ist also standardmäßig die Standard-Verschlüsselungssammlung von Python.

Der einzige Grund, dies nicht zu tun, ist, wenn wir denken, wir könnten heute eine Liste liefern, die sicherer ist als die in älteren Python-Versionen, oder wenn wir uns für eine der noch engeren OWASP-Stufen entscheiden möchten. Das ist ehrlich gesagt ziemlich marginal.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen