Für ein Projekt möchte ich ein Web-Formular als E-Mail versenden. Um die sensitiven Daten besonders gut zu schützen, möchte ich das E-Mail direkt vom Hosting Web-Server auf den Ziel-Mailserver senden und den lokalen SMTP des Hostinganbieters nicht mit den Daten in Berührung kommen lassen. Und die Übermittlung des E-Mails an den SMTP-Server müsste auch noch verschlüsselt erfolgen.
Leider verfügt der Ziel-SMTP-Server über ein (mittlerweile) schwaches Zertifikat, denn PHPMailer respektive OpenSSL weigert sich, verschlüsselt mit dem SMTP-Server zu kommunizieren:
... 2020-09-30 19:48:46 Connection failed. Error #2: stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages:error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small [../PHPMailer-5.2.28/class.smtp.php line 374] ...
PHPMailer gibt diese Debug-Meldungen direkt an den Browser aus, wenn man bei der Initialisierung der Klasse folgende Option aktiviert:
... $mail = new PHPMailer(); ... $mail->SMTPDebug = SMTP::DEBUG_LOWLEVEL; ...
Andere, weniger geschwätzige Optionen sind: SMTP::DEBUG_CLIENT, SMTP::DEBUG_SERVER, SMTP::DEBUG_CONNECTION. SMTP::DEBUG_OFF unterdrückt jegliche Debug-Meldungen.
Das Problem ist, dass der vom Server verwendete Diffie Hellman-Key zu kurz ist; im vorliegenden Fall ist er nur 1024 bit lang. Dies erlaubt Logjam-Attacken.
Überprüfen kann man die Key-Länge mit folgendem Befehl:
$ openssl s_client -connect mailserver.tld:25 -starttls smtp ... Server Temp Key: DH, 1024 bits ...
Beim Debugging habe ich auch noch den Web-Service www.checktls.com entdeckt, der mir bestätigt hat, dass der Server grundsätzlich verschlüsselt spricht.
Nun, entweder überzeugt man den Betreiber des SMTP-Servers, die Verschlüsselungskonfiguration anzupassen respektive einen neuen Schlüssel zu generieren.
Falls dies keine Option ist, und man das Risiko in Kauf nehmen möchte, gibt es aber noch folgende Möglichkeit:
... $mail = new PHPMailer(); ... $mail->SMTPSecure = 'tls'; $mail->SMTPOptions = array( 'ssl' => array( 'security_level' => 0 ) ); ...
Die Option security_level gibt es seit PHP 7.2 und OpenSSL 1.1.0. Mögliche Werte sind in der offiziellen Dokumentation nachzuschlagen. 0 bedeutet sinnbildlich NULL Sicherheit.
DIESER WORKAROUND ERFOLGT AUF EIGENE GEFAHR! Ich würde das nur machen, wenn man sich wirklich bewusst ist, was man tut.