Aikido

Mehrere Cross-Site-Scripting in Mailcow

Verfasst von
Jorian Woltjer

Mailcow ist ein weit verbreiteter, selbst gehosteter Open-Source-E-Mail-Server, der alles bereitstellt, was man benötigt, um E-Mail-Postfächer selbst zu verwalten. Um seine Sicherheit zu überprüfen, haben wir eine lokale Instanz eingerichtet und unsere KI-Penetrationstests daran. Wir fanden drei XSS-Schwachstellen, darunter eine kritische Schwachstelle, die es nicht authentifizierten Angreifern ermöglichte, Administrator-Konten zu übernehmen, während sie deren Protokolle in der Benutzeroberfläche einsehen konnten.

Der Zugriff auf ein E-Mail-Konto kann schwerwiegende Sicherheitsrisiken mit sich bringen. Sensible Daten in E-Mails können abgefangen werden, aber der Zugriff ermöglicht es Angreifern zudem, die Funktion zur Passwortzurücksetzung zu nutzen, um andere verbundene Konten des Opfers zu kompromittieren. Genau das wäre möglich gewesen, wenn jemand diese Schwachstellen ausgenutzt hätte.

Alle Sicherheitslücken wurden Mailcow verantwortungsbewusst gemeldet und sind seit Version 2026-03b (veröffentlicht am 31. März 2026) behoben. Wir möchten dem Betreuer, FreddleSpl0it, für den reibungslosen Ablauf und die schnelle Behebung danken.

Nicht maskierte Autodiscover-Protokolle

Diese Sicherheitslücke, die auf GitHub unter der Kennung GHSA-f9xf-vc72-rcgm gemeldet wurde, ermöglichte es nicht authentifizierten Angreifern, eine Autodiscover-Anfrage mit einer bösartigen E-Mail-Adresse zu senden, die in den Protokollen angezeigt wurde. Wenn ein Administrator diese Protokolle später einsieht, wird das Feld für die E-Mail-Adresse ohne Escape-Zeichen angezeigt, was HTML-Injection und XSS ermöglicht.

Fangen wir beim Waschbecken an. Mailcow ermöglicht die Anzeige von Autodiscover-Protokollen in einer Tabelle im Admin-Panel, die mithilfe von DataTables in dashboard.js dargestellt wird. Diese Bibliothek weist die übliche Schwachstelle auf, dass sie standardmäßig alle Datenwerte als HTML interpretiert. Alle Werte müssen daher zuvor ordnungsgemäß maskiert werden.

var table = $('#autodiscover_log').DataTable({
  ...
  ajax: {
    type: "GET",
    url: "/api/v1/get/logs/autodiscover/100",
    dataSrc: function(data){
      return process_table_data(data, 'autodiscover_log');
    }
  },

Der process_table_data() Die Funktion versucht, die Benutzereingaben in jeder Zeile zu escape . Bei Autodiscover-Protokollen  item.ua (User Agent) wird korrekt mit escapeHtml (dashboard.js):

} else if (table == 'autodiscover_log') { 
   $.each(data, function (i, item) { 
     if (item.ua == null) { 
       item.ua = 'unknown'; 
     } else { 
       item.ua = escapeHtml(item.ua); 
     } 
     item.ua = '<span style="font-size:small">' + item.ua + '</span>';

Eine Spalte, nämlich „item.name“, wird jedoch nicht maskiert. Dabei handelt es sich um die E-Mail-Adresse, die in der Autodiscover-Anfrage übermittelt wird.

Was ist das Gefährlichste daran? Eine Autodiscover-Anfrage ist von Natur aus nicht authentifiziert , und in diesem Fall wird die E-Mail-Adresse nicht überprüft. Sie landet in den Protokollen, und sobald ein Administrator diese einsieht, wird sie durch diese anfälligen Funktionen geleitet und als beliebiger HTML-Code dargestellt.

Nachfolgend finden Sie ein Beispiel für eine Anfrage, die Folgendes einfügt: <img src=x onerror=alert(origin)> in die Tabelle:

POST /Autodiscover/Autodiscover.xml HTTP/2
Host: 127.0.0.1
Content-Type: text/xml
Content-Length: 384

<?xml version='1.0' encoding='utf-8'?>
<Autodiscover xmlns='http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006'>
  <Request>
    <EMailAddress>&lt;img src=x onerror=alert(origin)&gt;</EMailAddress>
    <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
  </Request>
</Autodiscover>

Wenn ein Administrator nun die Autodiscover-Protokolle aufruft (zu finden unter Dashboard -> Protokolle -> Autodiscover), wird das JavaScript ausgeführt und ein Warnungs-Popup angezeigt, was eine XSS-Schwachstelle im Mailcow-Ursprungsserver belegt.

Auf der Localhost-Kopie von Mailcow erscheint ein Popup-Fenster mit der Meldung „localhost sagt: https://localhost“

Da davon ausschließlich Administratoren betroffen sind, können Angreifer auf die Postfächer aller Benutzer zugreifen und die Instanz neu konfigurieren. Aus diesem Grund wurde die Schwachstelle als kritisch eingestuft.

Diese Ausgabe wurde behoben indem man ein escapeHtml() Rufe während der Verarbeitung der Zeilen die Funktion `item.user` auf.

Dateinamen von Anhängen in Quarantäne einfügen

Diese als GHSA-2xjc-rg88-jvpp gemeldete Sicherheitslücke betrifft die Quarantänefunktion von Mailcow, in der Administratoren markierte Anhänge überprüfen können. Die Dateinamen dieser Anhänge wurden ohne HTML-Escaping angezeigt, was jedem Administrator, der sie aufrief, die Möglichkeit zu XSS-Angriffen eröffnete. Die Ausnutzung dieser Schwachstelle erforderte keine Authentifizierung seitens des Angreifers, allerdings musste die Quarantänefunktion auf der Zielinstanz aktiviert sein.

Diesmal ist der Sink frei. In „quarantine.js“ gibt es einen Codeabschnitt, der HTML mit dynamischen Daten verknüpft:

$.each(data.attachments, function(index, value) { 
   qAtts.append( 
     '<p><a href="/inc/ajax/qitem_details.php?id=' + qitem + '&att=' + index + '" target="_blank">' + value[0] + '</a> (' + value[1] + ')' + 
     ' - <small><a href="' + value[3] + '" target="_blank">' + lang.check_hash + '</a></small></p>' 
   ); 
 });

Sollten einige dieser Werte vom Benutzer gesteuert werden, könnte dies erneut zu einer HTML-Injektion führen. Bei diesen Werten handelt es sich um den Dateinamen, den MIME-Typ, die Dateigröße und den Virustotal-SHA256-Hash. Von diesen scheint der Dateiname am ehesten Benutzereingaben zu enthalten, da ein Angreifer eine E-Mail mit einem Anhang versenden kann, dessen Dateiname aus HTML-Tags besteht. 

When testing, it turns out that, as expected, no strict validation takes place on this filename. It can contain <> characters, which is all that's needed to inject an XSS payload. The remaining challenge is getting the email into the quarantine queue in the first place, so an admin will open and inspect it. The attacker solves this by attaching an EICAR antivirus test file, which is a standardized string that every antivirus engine is guaranteed to flag. This reliably routes the email to quarantine without requiring the attacker to send actual malware.

Der folgende Code erzeugt einen Anhang, dessen Inhalt die EICAR-Zeichenkette ist und dessen Dateiname eine XSS-Nutzlast enthält (das vollständige Skript finden Sie im Sicherheitshinweis ):

# Malicious filename attachment with EICAR to trigger quarantine
att = MIMEApplication(b'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*', _subtype='octet-stream')
att.add_header('Content-Disposition', 'attachment', filename='<img src=x onerror=alert(origin)>.exe')
msg.attach(att)

Nachdem die E-Mail an Mailcow gesendet und in Quarantäne verschoben wurde, kann der Administrator die Quarantäneseite öffnen, um sie einzusehen. Sobald er auf „Element anzeigen“ klickt, wird unser Dateiname angezeigt und der XSS-Angriff wird ausgelöst:

Beachten Sie, dass hierfür ebenfalls keine Authentifizierung bei Mailcow erforderlich ist. Es reicht aus, eine böswillig gestaltete E-Mail an die Mailcow-Domain zu senden und darauf zu warten, dass der Administrator diese untersucht. Von diesem Punkt an könnte die gesamte Instanz mithilfe von JavaScript übernommen werden, wodurch erneut Zugriff auf Postfächer erlangt und die Instanz konfiguriert werden könnte.

Dieses Problem wurde behoben, indem die Werte der Anhänge mit Aufrufen von `escapeHtml()` umschlossen wurden.

Ausnutzung eines Self-XSS in einer IP-Adresse, die im Anmeldungsverlauf aufgeführt ist

Die letzte XSS-Sicherheitslücke, die unter der Kennung GHSA-jprq-w83q-q62h gemeldet wurde, war aus technischer Sicht interessanter zu nutzen. Die XSS-Payload wird unter dem eigenen Konto des Angreifers gespeichert, was bedeutet, dass normalerweise nur der Angreifer selbst sie auslösen würde (ein „Self-XSS“ ohne echte Auswirkungen). Der Angriff wird gefährlich, wenn er mit einem Login-CSRF kombiniert wird, der den Browser des Opfers zwingt, sich in das Konto des Angreifers einzuloggen, wodurch die gespeicherte Payload der falschen Person präsentiert wird.

Die Sicherheitslücke beginnt mit einer weiteren einfachen HTML-Verkettungsstelle in der Datei „user.js“:

var real_rip = item.real_rip.startsWith("Web") ? item.real_rip : '<a href="https://bgp.tools/prefix/' + item.real_rip + '" target="_blank">' + item.real_rip + "</a>";

Der real_rip (Real Remote IP) wird in der Tabelle der letzten Anmeldungen unverändert angezeigt. Normalerweise sollte dies kein Problem darstellen; IP-Adressen folgen einem sehr strengen Format, das keinen Spielraum für XSS-Payloads lässt.

IP-Adressen werden jedoch nicht von Mailcow überprüft und stammen direkt von der X-Real-IP: Standardmäßig wird dieser Header gesetzt. Einige Proxys setzen diesen Header auf die Remote-IP des Benutzers; wenn jedoch kein solcher Proxy vorhanden ist, wird jeder angegebene Wert als vertrauenswürdig angesehen. Daher kannst du dich anmelden, während du X-Real-IP: "><img src onerror=alert(origin)> wodurch der Wert in den letzten Anmeldeeinträgen gespeichert wird. Bei der Anzeige (über /Benutzer), wird die XSS-Nutzlast dargestellt und die Warnmeldung ausgeführt.

POST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
X-Real-Ip: "><img src onerror=alert(origin)>

login_user=attacker&pass_user=attacker

Das ist jedoch noch nicht das Ende der Geschichte. Denn ein Opfer wird sich nicht mit diesem gefälschten IP-Header anmelden oder sich aus heiterem Himmel in das Konto des Angreifers einloggen. Vorerst handelt es sich um Self-XSS.

Zwei Aspekte dieser Sicherheitslücke ermöglichen eine Rechteausweitung. Erstens wird die Payload dauerhaft unter dem Konto des Angreifers gespeichert. Zweitens verfügt die Anmeldeanfrage über keinen CSRF-Schutz, was bedeutet, dass sie über verschiedene Websites hinweg ausgelöst werden kann. Ein Angreifer kann auf seiner eigenen Domain ein Formular hosten, das automatisch die Anmeldedaten des Angreifers übermittelt und das Opfer anmeldet, ohne dass dieses über den Besuch der Seite hinaus weitere Interaktionen vornehmen muss.

Ein Angreifer kann das folgende Formular auf seiner bösartigen Domain hosten:

<form action="http://mailcow.local/" method="POST">
    <input type="text" name="login_user" value="attacker">
    <input type="text" name="pass_user" value="attacker">
</form>
<script>
    document.forms[0].submit();
</script>

Sobald ein Opfer dieses auf der bösartigen Website gehostete Formular öffnet, wird es automatisch in das Konto des Angreifers eingeloggt. Wir können es dann weiterleiten zu /Benutzer um den zuvor gespeicherten XSS-Angriff auszulösen. Aber Moment mal, das Opfer ist jetzt im Konto des Angreifers angemeldet – wie kann der Angreifer also des Opfers Daten?

Hier kann der Angreifer einen raffinierten Trick anwenden: Er lässt das Postfach des Opfers bis nach dem Login-CSRF- und XSS-Angriff geöffnet und liest dann mithilfe des Same-Origin-Zugriffs die Daten aus.

Der neue Ablauf sieht wie folgt aus:

  1. Das Opfer ruft unsere bösartige Seite auf (Registerkarte 1)
  2. Tab 1 öffnet eine zweite bösartige Seite (Tab 2), die das CSRF-Anmeldeformular enthält, wobei es zu einer kurzen Verzögerung kommt, bevor es ausgeführt wird
  3. Registerkarte 1 leitet zur Mailbox des Opfers weiter und lädt die Daten, die der Angreifer stehlen möchte
  4. Tab 2 sendet das CSRF-Anmeldeformular ab und öffnet einen neuen Tab 3, der das Opfer beim Konto des Angreifers anmeldet
  5. Registerkarte 2 leitet weiter zu /Benutzer, wo das Stored-XSS ausgelöst wird
  6. Der XSS-Angriff in Registerkarte 2 nutzt einen Verweis auf Auftakt zu lesen und zu entwenden document.body.innerHTML auf Registerkarte 1, wo das Postfach des Opfers noch geöffnet ist

Das Diagramm zeigt drei Felder, die Browser-Registerkarten darstellen. 1. Mailbox 2. XSS 3. CSRF. Die beiden letzteren gehören dem Angreifer.

Dadurch ist es möglich, E-Mails vom Konto des Opfers abzurufen, da diese abgerufen wurden, während das Opfer noch in seinem Konto angemeldet war!

Ausführliche Informationen dazu, wie der Exploit-Ablauf in der Praxis funktioniert, finden Sie in der Sicherheitsempfehlung. Durch mehrere HTML-Dateien, die eine präzise Steuerung des Ablaufs ermöglichen, kann ein Angreifer E-Mails mit nur zwei Klicks stehlen (die zum Öffnen der beiden zusätzlichen Registerkarten erforderlich sind).

Dieses Problem wurde behoben, indem die Darstellung der IP-Adresse durch Aufrufe von `escapeHtml()` umschlossen wurde.

Behebung

Aktualisieren Sie Mailcow auf Version 2026-03b oder höher, veröffentlicht am 31. März 2026. Alle drei XSS-Sicherheitslücken wurden in dieser Version behoben. Wenn Sie Aikido verwenden, werden anfällige Mailcow-Instanzen in Ihrem Surface-Monitoring-Feed automatisch als kritischer Befund gekennzeichnet.

Aikido mit einem Wert von 95: Kritisch für Mailcow. Es enthält außerdem eine Zusammenfassung und Schritte zur Behebung des Problems.

Aikido nicht bei Aikido registriert? Erstelle ein kostenloses Konto, um loszulegen – keine Kreditkarte erforderlich.

Fazit

Ein Muster, das wir im Zuge dieser Sicherheitslücken beobachtet haben, ist, dass das Verketten von HTML-Zeichenfolgen nach wie vor keine gute Idee ist. Moderne HTML-Template-Engines haben in den meisten Anwendungen große Fortschritte erzielt, doch ältere Anwendungen ohne sichere Frameworks verfügen nicht über diesen Luxus. Manchmal greifen sie wieder auf das Verketten von Zeichenfolgen in JavaScript zurück, was, wie hier zu sehen ist, schnell dazu führt, dass vergessen wird, escape .

E-Mail-Anwendungen enthalten hochsensible Informationen und sollten daher mit großer Sorgfalt behandelt werden. Solche Anwendungen sollten einer gründlichen Prüfung unterzogen werden, da die Kompromittierung einer einzigen Anwendung zur Ausnutzung von Mechanismen zur Passwortzurücksetzung führen kann, was wiederum die Kompromittierung vieler anderer verbundener Konten zur Folge hat.

Aikido (KI-Penetrationstests) spürt solche Schwachstellen in Anwendungen auf – und das vollständig automatisiert. Wenn Sie sich angesichts dieser Ergebnisse fragen, ob Ihre eigenen Anwendungen ebenfalls XSS-Schwachstellen aufweisen, melden Sie sich an oder kontaktieren Sie uns!

Teilen:

https://www.aikido.dev/blog/xss-vulnerabilities-in-mailcow

Heute kostenlos starten.

Kostenlos starten
Ohne Kreditkarte

Abonnieren Sie Bedrohungs-News.

4.7/5
Falschpositive Ergebnisse leid?

Probieren Sie Aikido, wie 100.000 andere.
Jetzt starten
Erhalten Sie eine personalisierte Führung

Von über 100.000 Teams vertraut

Jetzt buchen
Scannen Sie Ihre App nach IDORs und realen Angriffspfaden

Von über 100.000 Teams vertraut

Scan starten
Erfahren Sie, wie KI-Penetrationstests Ihre App testen

Von über 100.000 Teams vertraut

Testen starten

Sicherheit jetzt implementieren

Sichern Sie Ihren Code, Ihre Cloud und Ihre Laufzeit in einem zentralen System.
Finden und beheben Sie Schwachstellen schnell und automatisch.

Keine Kreditkarte erforderlich | Scan-Ergebnisse in 32 Sek.