FlawOpen

flawopen.com/Teardowns/cve-2023-6246-glibc-syslog-heap-buffer-overflow

● CVE-2023-6246 · CVSS 7.8 · Hoch
Sicherheitsforschung · FlawOpen

CVE-2023-6246: Heap-Überlauf in glibc-syslog

CVE-2023-6246 ist ein glibc-syslog-Heap-Überlauf durch einen langen Header. Installieren Sie das korrigierte glibc-Paket Ihrer Distribution.

💡 Einfache Erklärung (ELI5)

Stellen Sie sich einen Mitarbeiter vor, der ein Paket und sein Etikett mit einem kurzen Lineal misst. Das Etikett passt nicht, deshalb erfasst die Berechnung den benötigten Platz nicht. Er bestellt eine winzige Schachtel und versucht, das vollständige Etikett samt Inhalt hineinzudrucken. In glibc konnte ein langer syslog-Header die erforderliche Größe unbestimmt lassen, sodass der Logger zu wenig Heap-Speicher reservierte.

Kernkonzepte & Begriffe

glibc
Die GNU C Library stellt zentrale C-Runtime-Funktionen für die meisten Linux-Programme bereit.
__vsyslog_internal()
Interne glibc-Implementierung, die syslog() und vsyslog() zum Formatieren der Nachricht und des SYSLOG_HEADER vor der Übergabe an den Systemlogger verwenden.
SYSLOG_HEADER
Prioritäts- und Identifikationspräfix vor der syslog-Nachricht. Es kann den Programmnamen oder eine über openlog() gesetzte Kennung enthalten.
Heap-based buffer overflow (CWE-122)
Ein Schreibvorgang überschreitet die Grenzen eines Heap-Puffers. Hier scheiterte die Größenberechnung, wenn der Header mit langem Namen nicht in den festen Anfangspuffer passte.

Framework-Zuordnungen

  • CWE-Referenz für die in diesem Leitfaden beschriebene Schwachstelle: CWE-122

Ursachenanalyse

Laut glibc-Hinweis aktualisierte __vsyslog_internal() die erforderliche Puffergröße nicht, wenn ein SYSLOG_HEADER mit langem Programmnamen formatiert wurde. Im verwundbaren Code konnte die Headerlänge l mindestens so groß wie der 1.024-Byte-Stackpuffer sein; dadurch wurde der Zweig übersprungen, der den Nachrichtenkörper formatierte und bufsize setzte. Der spätere Heap-Pfad verwendete dann eine undefinierte oder nullgroße Größe und schrieb Header und Nachricht in einen zu kleinen Bereich. Qualys zufolge kann der lange Name aus dem vom Aufrufer kontrollierten Basename von argv[0] oder einer mehr als 1.024 Byte langen openlog()-Kennung stammen. Ein verwundbares setuid-Programm, das diesen Protokollpfad nutzt, kann den Fehler sicherheitsrelevant machen. Qualys demonstrierte eine lokale Rechteausweitung über su auf Fedora 38. Das Risiko hängt von lokalem Zugriff, Konfiguration und Aufrufpfad ab; es ist kein allgemeiner entfernter syslog-Exploit.

Schritt-für-Schritt Angriffsablauf

Schritt 1

Lokale Voraussetzung

Ein lokaler Prozess muss über ein Programm mit betroffener glibc syslog() oder vsyslog() erreichen. Für Sicherheitsauswirkungen braucht es einen privilegierten Aufrufer und einen Pfad, der den Programmnamen-Präfix nicht durch eine sichere, begrenzte Kennung ersetzt.

Schritt 2

Langer Header

Der Header überschreitet den Anfangspuffer|Der SYSLOG_HEADER enthält einen langen Programmnamen (__progname, abgeleitet vom Basename von argv[0]) oder eine lange openlog()-Kennung. Qualys zufolge muss der auslösende Wert länger als 1.024 Byte sein.

Schritt 3

Fehlende Berechnung

Zweig für Größenberechnung wird übersprungen|Passt der Header nicht in den 1.024-Byte-Stackpuffer, überspringt der verwundbare Code den Zweig, der bufsize berechnet. Dem Heap-Pfad fehlt dann Platz für Header und formatierte Nachricht.

Schritt 4

Speicherauswirkung

Schreibvorgang überschreitet die Zuweisung|Der Logger schreibt Header und Nachricht in einen zu kleinen Puffer und beschädigt den Heap. Qualys zeigte lokale Rechteausweitung über su auf Fedora 38; leiten Sie daraus keine gleiche Erreichbarkeit für alle Anwendungen oder Distributionen ab.

Quellcode: Verwundbar vs. Sicher

Der alte Zweig ließ bufsize auf null, wenn der Header nicht in den Stackpuffer passte; dadurch konnte der Heap-Fallback zu wenig Speicher reservieren. Der Fix markiert den Stackpuffer in diesem Fall als unbrauchbar, misst den Nachrichtenkörper darin, setzt l + vl und verwendet anschließend den bestehenden Allokationspfad mit der erforderlichen Größe. Dies sind gezielte Upstream-Auszüge, keine vollständigen eigenständigen Funktionen.

Quelltextauszug: misc/syslog.c

VERWUNDBARE IMPLEMENTIERUNG
/* Gezielter Auszug aus misc/syslog.c vor Commit 6bd0e4efcc78. */
char bufs[1024];
char *buf = NULL;
size_t bufsize = 0;
...
if (0 <= l && l < sizeof bufs)
  {
    va_list apc;
    va_copy (apc, ap);
    int vl = __vsnprintf_internal (bufs + l, sizeof bufs - l, fmt, apc,
                                   mode_flags);
    if (0 <= vl && vl < sizeof bufs - l)
      buf = bufs;
    bufsize = l + vl;
    va_end (apc);
  }
/* Ein langer Header überspringt den obigen Zweig zur Größenfestlegung. */
GEHÄRTETER SICHERHEITS-PATCH
/* Gezielter Auszug aus misc/syslog.c nach Commit 6bd0e4efcc78. */
char bufs[1024];
char *buf = bufs;
size_t bufsize;
...
if (0 <= l && l < sizeof bufs)
  {
    pos = bufs + l;
    len = sizeof (bufs) - l;
  }
else
  {
    buf = NULL;
    pos = bufs;
    len = sizeof (bufs);
  }
vl = __vsnprintf_internal (pos, len, fmt, apc, mode_flags);
if (!(0 <= vl && vl < len))
  buf = NULL;
bufsize = l + vl;

Checkliste für Engineering & Systemsicherheit

Quellen