Verwendung eines extern kontrollierten Format-Strings
Beschreibung
Die Verwendung eines extern kontrollierten Format-Strings (Format-String-Schwachstelle) tritt auf, wenn benutzerbereitgestellte Eingaben direkt als Format-String-Argument in Funktionen wie printf(), sprintf(), fprintf() und ähnlichen Formatierungsfunktionen verwendet werden. Format-Specifier wie %s, %x und %n in printf-Familie-Funktionen können ausgenutzt werden, um aus beliebigen Speicherstellen zu lesen (%s, %x), Programme zum Absturz zu bringen oder in beliebige Speicherstellen zu schreiben (%n). Der %n-Specifier ist besonders gefährlich, da er die Anzahl der bisher gedruckten Bytes an eine auf dem Stack bereitgestellte Adresse schreibt und somit beliebige Schreib-Primitive ermöglicht.
Risiko
Format-String-Schwachstellen sind extrem gefährlich und bieten Angreifern mächtige Exploitation-Primitive, vergleichbar mit Buffer Overflows. Die wiederholte Verwendung von %x ermöglicht das Lesen von Stack-Inhalten und legt potenziell Rücksprungadressen (Umgehung von ASLR), Canary-Werte und sensible Daten offen. Der %n-Specifier ermöglicht beliebige Schreibzugriffe auf den Speicher, was Angreifern erlaubt, GOT-Einträge, Rücksprungadressen oder Funktionspointer für Code-Ausführung zu überschreiben. Ganze Bücher wurden über Format-String-Exploitation-Techniken geschrieben. Die Schwachstelle wurde in die Top 10 der am häufigsten gemeldeten Schwachstellentypen eingestuft und betrifft Hunderte von Anwendungen in CVE-Datenbanken.
Lösung
Übergeben Sie niemals benutzerkontrollierte Eingaben direkt als Format-String. Verwenden Sie immer einen statischen Format-String mit der Benutzereingabe als Argument: printf("%s", user_input) anstelle von printf(user_input). Aktivieren Sie Compiler-Warnungen für Format-String-Probleme (-Wformat-security, -Wformat, -Wformat-nonliteral in GCC/Clang). Verwenden Sie Format-String-Prüfungsattribute für benutzerdefinierte Formatierungsfunktionen. Erwägen Sie die Verwendung sicherer Alternativen, die %n nicht unterstützen. Wenden Sie statische Analysetools an, die Format-String-Schwachstellen erkennen. In C++ bevorzugen Sie typsichere Formatierung wie std::format oder die fmt-Bibliothek.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Bereich: Informationsoffenlegung Format-Specifier %s und %x ermöglichen das Lesen beliebiger Speicherstellen auf dem Stack und potenziell darüber hinaus, was sensible Daten offenlegt. |
| Zugriffskontrolle | Bereich: Code-Ausführung Der %n-Specifier bietet ein beliebiges Schreib-Primitiv, das das Überschreiben von Rücksprungadressen, GOT-Einträgen oder Funktionspointern ermöglicht. |
| Verfügbarkeit | Bereich: Denial-of-Service Ungültige Format-Specifier oder das Dereferenzieren ungültiger Adressen verursacht Abstürze. |
Beispielcode + Lösungscode
Anfälliger Code
#include <stdio.h>
// ANFÄLLIG: Benutzereingabe als Format-String
void log_message(char *user_input) {
printf(user_input); // Benutzer kann %x, %s, %n einschleusen
}
// ANFÄLLIG: Format-String in syslog
void log_error(char *error_msg) {
syslog(LOG_ERR, error_msg); // Gleiche Schwachstelle
}
// ANFÄLLIG: Indirekter Format-String
void display_username(char *username) {
char buffer[256];
// Benutzergesteuerter Format-String
sprintf(buffer, username); // Anfällig!
display(buffer);
}
/*
* Angriffsbeispiele:
* Eingabe: "%x %x %x %x" -> Leakt Stack-Werte
* Eingabe: "%s" -> Liest String an Stack-Adresse (kann abstürzen)
* Eingabe: "%n" -> Schreibt an Adresse auf Stack
* Eingabe: "AAAA%08x.%08x.%08x.%08x.%n" -> Write-what-where-Angriff
*/
Korrigierter Code
#include <stdio.h>
#include <syslog.h>
// SICHER: Benutzereingabe als Argument, nicht Format-String
void log_message_safe(const char *user_input) {
printf("%s", user_input); // Benutzereingabe kann keine Specifier einschleusen
}
// SICHER: Format-String für syslog
void log_error_safe(const char *error_msg) {
syslog(LOG_ERR, "%s", error_msg); // Fester Format-String
}
// SICHER: Ordnungsgemäße sprintf-Verwendung
void display_username_safe(const char *username) {
char buffer[256];
// Format-Specifier für Benutzerdaten verwenden
snprintf(buffer, sizeof(buffer), "Benutzer: %s", username);
display(buffer);
}
// SICHER: C++ typsichere Formatierung (C++20)
#ifdef __cplusplus
#include <format>
#include <string>
void log_cpp(const std::string& user_input) {
// Typsichere Formatierung - keine Format-String-Injection möglich
auto msg = std::format("Nachricht: {}", user_input);
std::cout << msg << std::endl;
}
#endif
// Kompilieren mit Format-Warnungen: gcc -Wformat -Wformat-security -Werror
Ausgenutzt in der Praxis
ProFTPD Format-String (ProFTPD, 1999-2000)
Die Entdeckung von Format-String-Schwachstellen als Angriffsvektor kam aus einem Sicherheits-Audit von ProFTPD im September 1999. Die ersten großen öffentlichen Exploits, die Remote-Root-Zugriff ermöglichten, wurden im Juni 2000 auf Bugtraq veröffentlicht und markierten den Beginn der weitverbreiteten Format-String-Exploitation.
PHP Format-String-Schwachstellen (PHP, mehrfach)
CVE-2011-1153 und verwandte Schwachstellen behob 27 Format-String-Probleme in PHP auf einmal und demonstrierte, wie verbreitet diese Schwachstellenklasse in der Softwareentwicklung wurde.
Wu-FTPd Format-String (Wu-FTPd, 2000)
Eine der am weitesten verbreiteten frühen Format-String-Schwachstellen, die einen populären FTP-Server-Daemon betraf, der auf vielen Unix-Systemen verwendet wurde, und Remote-Root-Kompromittierung ermöglichte.
Tools zum Testen/Ausnutzen
-
GDB + PEDA/GEF — Debugger-Erweiterungen für Format-String-Exploit-Entwicklung.
-
pwntools — CTF-Framework mit Format-String-Exploitation-Utilities.
-
Format String Exploitation Tools — Spezialisierte Tools für Format-String-Angriffe.
CVE-Beispiele
-
CVE-2011-1153 — PHP mehrfache Format-String-Schwachstellen.
-
CVE-2012-0809 — sudo Format-String-Schwachstelle ermöglicht Privilegieneskalation.
-
CVE-2022-42043 — PDF-XChange Format-String-Schwachstelle.
Referenzen
-
MITRE. "CWE-134: Use of Externally-Controlled Format String." https://cwe.mitre.org/data/definitions/134.html
-
CERT. "FIO30-C. Exclude user input from format strings." https://wiki.sei.cmu.edu/confluence/display/c/FIO30-C
-
Wikipedia. "Uncontrolled format string." https://en.wikipedia.org/wiki/Uncontrolled_format_string