FlawOpen

flawopen.com/Incidents/citrix-bleed-session-token-leak-october-2023

● Citrix · CVE-2023-4966 · October 2023 · CVSS 9.4 · Kritisch
Sicherheitsforschung · FlawOpen

Citrix Bleed: Sitzungstoken-Leak und MFA-Umgehung

CVE-2023-4966 legte NetScaler-Speicher samt Sitzungstoken offen und ermöglichte Sitzungsübernahmen ohne MFA. Die Ausnutzung begann Ende August 2023.[1], [2]

💡 Einfache Erklärung (ELI5)

Sie bitten einen Assistenten, eine Nachricht auf eine kleine Karte zu schreiben und Ihnen ihre Länge zu nennen. Auf die Karte passen nur 50 Zeichen, also schreibt er 50 – aber auf die Frage nach der Länge antwortet er ehrlich „800 Zeichen“, denn so lang war das Original. Dann geben Sie die Karte jemandem und sagen, er solle 800 Zeichen davon vorlesen. Er liest Ihre 50 und liest einfach weiter, was sonst noch auf dem Blatt steht.[2]

Kernkonzepte & Begriffe

snprintf
Eine C-Funktion, die Text in einen Puffer fester Größe formatiert. Passt der Text nicht, kürzt sie ihn, gibt aber die Länge zurück, die der vollständige Text gehabt hätte.[3]
NetScaler ADC / Gateway
Citrix-Appliances für Fernzugriff und Lastverteilung am Netzwerkrand. Betroffen waren nur Geräte, die als Gateway oder AAA-Virtual-Server konfiguriert waren.[1]
Lesen über Puffergrenzen (CWE-125)
Lesen über das Ende eines Puffers hinaus. Nichts wird überschrieben, aber was im angrenzenden Speicher liegt, wird preisgegeben. Dies beschreibt den konkreten Out-of-Bounds-Read-Mechanismus (CWE-125); Citrix ordnet CVE-2023-4966 allgemein CWE-119 zu.[1], [3]
Sitzungstoken
Der Wert, der belegt, dass sich ein Benutzer bereits angemeldet hat. Wer ihn vorlegt, gilt als dieser Benutzer – ohne Passwort- oder MFA-Abfrage.[2]

Framework-Zuordnungen

Vorfall-Zeitstrahl

2023-08

Laut späteren Berichten aus der Vorfallsbearbeitung beginnt die Ausnutzung der Lücke als Zero-Day.[2]

2023-10-10

Citrix veröffentlicht das Bulletin CTX579459 mit den korrigierten Builds 14.1-8.50, 13.1-49.15 und 13.0-92.19.[1]

2023-10-18

Die CISA nimmt CVE-2023-4966 in ihren Katalog Known Exploited Vulnerabilities auf.[4]

Schritt-für-Schritt Angriffsablauf

Schritt 1

Ein übergroßer Header

Eine nicht authentifizierte Anfrage mit sehr langem Host-Header erreicht Code, der auf der Appliance eine OpenID-Connect-Discovery-Antwort erzeugt.[2], [3]

Schritt 2

Die Länge wird falsch gelesen

snprintf kürzt den Text auf die Puffergröße, gibt aber die volle hypothetische Länge zurück, und der Code hält diese für die Zahl geschriebener Bytes.[3], [2]

Schritt 3

Speicher jenseits des Puffers wird gesendet

Die Antwort wird mit dieser größeren Länge verschickt, also liefert die Appliance neben dem gekürzten JSON angrenzenden Speicher aus.[2]

Schritt 4

Sitzungen werden übernommen

Der offengelegte Speicher kann gültige Sitzungstokens enthalten. Wer einen davon wiederverwendet, erhält die angemeldete Sitzung des Benutzers ohne Passwort und MFA.[2], [1]

Quellcode: Verwundbar vs. Sicher

Illustrativer C-Code, kein NetScaler-Quellcode. Die Korrektur prüft den Rückgabewert von snprintf, der angibt, wie lang die vollständige Ausgabe gewesen wäre. Ist er negativ oder mindestens so groß wie der Puffer, ist die Formatierung fehlgeschlagen oder wurde gekürzt; die Funktion sendet dann nichts. send_response erhält die Länge daher nur, wenn die vollständige Antwort in buf passt.[3], [2]

VERWUNDBARE IMPLEMENTIERUNG
#include <stdio.h>

int send_response(const char *data, int len);

int send_oidc_config(const char *host)
{
    char buf[256];
    /* n ist die Anzahl der Bytes, die geschrieben worden wären, und kann sizeof(buf) überschreiten */
    int n = snprintf(buf, sizeof(buf), "{\"issuer\":\"https://%s\"}", host);
    return send_response(buf, n);   /* sendet n Bytes und liest dabei über buf hinaus */
}
GEHÄRTETER SICHERHEITS-PATCH
#include <stdio.h>

int send_response(const char *data, int len);

int send_oidc_config(const char *host)
{
    char buf[256];
    int n = snprintf(buf, sizeof(buf), "{\"issuer\":\"https://%s\"}", host);
    if (n < 0 || (size_t)n >= sizeof(buf))
        return -1;                  /* gekürzte Ausgabe ablehnen; nie über den Puffer hinaus senden */
    return send_response(buf, n);
}

Checkliste für Engineering & Systemsicherheit

Quellen