Verwendung von umask() mit chmod-style Argument
Beschreibung
Verwendung von umask() mit chmod-style Argument ist eine Schwachstelle, bei der ein Programm die umask()-Funktion fälschlicherweise mit einem Argument aufruft, das so angegeben ist, als wäre es ein Argument für chmod(). Dies resultiert aus einem grundlegenden Missverständnis darüber, wie umask() funktioniert. Während chmod() Berechtigungen setzt, die gewährt werden, setzt umask() Berechtigungen, die verweigert (maskiert) werden. Wenn Entwickler diese Semantik verwechseln und chmod-style Argumente mit umask() verwenden, werden Dateien mit falschen Berechtigungen erstellt - typischerweise freizügiger als beabsichtigt.
Risiko
Falsche umask()-Verwendung erzeugt erhebliche Dateiberechtigungsschwachstellen. Wenn Entwickler beabsichtigen, Berechtigungen einzuschränken, aber chmod-style Argumente verwenden, haben die resultierenden Dateien die entgegengesetzten Berechtigungen von dem, was beabsichtigt war. Zum Beispiel erzeugt der Aufruf umask(0644) im Glauben, Dateien mit rw-r--r-- Berechtigungen zu erstellen, tatsächlich Dateien mit -------w- (0022) Berechtigungen. Dies kann zu world-writable Dateien, Ausführungsberechtigungen wo keine sein sollten, oder für alle lesbare Dateien führen, wenn sie privat sein sollten.
Lösung
Verstehen Sie, dass umask() invers zu chmod() arbeitet: Berechtigungen in der umask werden vom mode-Argument für open() und andere Dateierstellungsfunktionen ausgeschaltet. Verwenden Sie umask() mit dem korrekten Argument, das die zu verweigernden, nicht die zu gewährenden Berechtigungen darstellt. Für restriktive Dateierstellung verwenden Sie umask(0077), um alle Gruppen- und Ändere-Berechtigungen zu verweigern. Erwägen Sie die Verwendung von explizitem chmod() oder fchmod() nach der Dateierstellung für präzise Berechtigungskontrolle.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Bereich: Vertraulichkeit Dateien oder Verzeichnisse lesen - Falsche umask-Einstellungen können Dateien erstellen, die von unbefugten Benutzern lesbar sind. |
| Integrität | Bereich: Integrität Dateien oder Verzeichnisse ändern - Dateien können mit Schreibberechtigungen für unbeabsichtigte Benutzer erstellt werden. |
| Zugriffskontrolle | Bereich: Zugriffskontrolle Schutzmechanismus umgehen - Beabsichtigte Dateizugriffsbeschränkungen sind aufgrund invertierter Berechtigungslogik unwirksam. |
Beispielcode
Verwundbarer Code
// Verwundbar: chmod-style Argument mit umask()
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
void vulnerable_create_config_file(const char* filename, const char* content) {
// Verwundbar: Entwickler denkt, dies setzt rw-r--r-- (0644) Berechtigungen
// Aber umask arbeitet invers - dies maskiert tatsächlich 0644 AUS
// Resultierende Berechtigungen: ~0644 & 0777 = 0133 (--x-wx-wx)
umask(0644);
// Datei mit sehr falschen Berechtigungen erstellt!
int fd = open(filename, O_CREAT | O_WRONLY, 0777);
// Tatsächliche Berechtigungen: 0777 & ~0644 = 0133
write(fd, content, strlen(content));
close(fd);
}
void vulnerable_create_private_file(const char* filename) {
// Verwundbar: Entwickler denkt, dies beschränkt auf Eigentümer-only (0600)
// Erstellt tatsächlich Dateien mit Berechtigungen 0066 (----rw-rw-)
umask(0600);
int fd = open(filename, O_CREAT | O_WRONLY, 0666);
// Beabsichtigt: rw------- (0600)
// Tatsächlich: 0666 & ~0600 = 0066
// Datei ist schreibbar für Gruppe und Ändere!
close(fd);
}
void vulnerable_create_secret_file(const char* filename, const char* secret) {
// Verwundbar: Denkt "Ich will 0700 Berechtigungen"
umask(0700);
int fd = open(filename, O_CREAT | O_WRONLY, 0777);
// Beabsichtigt: rwx------ (0700)
// Tatsächlich: 0777 & ~0700 = 0077 (----rwxrwx)
// Datei ist vollständig zugänglich für Gruppe und Ändere!
write(fd, secret, strlen(secret));
close(fd);
}
// Verwundbar: Häufiges Missverständnismuster
int main() {
// Verwundbar: Entwickler will restriktive Berechtigungen
// Verwendet fälschlicherweise gewünschte Berechtigungen als umask-Wert
mode_t old_umask = umask(0644); // FALSCH!
// Erstellt Datei - Berechtigungen sind invertiert
FILE* fp = fopen("/tmp/config.txt", "w");
if (fp) {
fprintf(fp, "DB_PASSWORD=secret123\n");
fclose(fp);
// Datei hat falsche Berechtigungen, potenziell world-writable
}
// Verwundbar: Ein weiterer häufiger Fehler
umask(0755); // Denkt, dies gibt rwxr-xr-x
// Tatsächlich maskiert: Eigentümer write+read, Gruppe execute, Andere execute
// Resultat für 0777 open: ----w--w- (0022)
return 0;
}
Lösungscode
// Behoben: Korrekte umask-Verwendung
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
void secure_create_config_file(const char* filename, const char* content) {
// Behoben: umask spezifiziert Berechtigungen zum VERWEIGERN
// Um rw-r--r-- (0644) zu erhalten, verweigere: ----w--w- (0022)
mode_t old_umask = umask(0022);
int fd = open(filename, O_CREAT | O_WRONLY, 0644);
// Tatsächliche Berechtigungen: 0644 & ~0022 = 0644 (rw-r--r--)
// Korrekt!
if (fd >= 0) {
write(fd, content, strlen(content));
close(fd);
}
umask(old_umask); // Vorherige umask wiederherstellen
}
void secure_create_private_file(const char* filename) {
// Behoben: Um rw------- (0600) zu erhalten, verweigere alles für Gruppe/Ändere
// Verweigere: ----rwxrwx (0077)
mode_t old_umask = umask(0077);
int fd = open(filename, O_CREAT | O_WRONLY, 0600);
// Tatsächliche Berechtigungen: 0600 & ~0077 = 0600 (rw-------)
// Korrekt!
if (fd >= 0) {
close(fd);
}
umask(old_umask);
}
void secure_create_secret_file(const char* filename, const char* secret) {
// Behoben: Für Eigentümer-only Zugriff (0700), verweigere alle Gruppe/Ändere
mode_t old_umask = umask(0077);
int fd = open(filename, O_CREAT | O_WRONLY, 0700);
// Tatsächlich: 0700 & ~0077 = 0700 (rwx------)
// Korrekt!
if (fd >= 0) {
write(fd, secret, strlen(secret));
close(fd);
}
umask(old_umask);
}
// Behoben: Verwendung von explizitem chmod() für präzise Kontrolle
void secure_create_with_chmod(const char* filename, const char* content,
mode_t desired_mode) {
// Behoben: Zuerst mit restriktiven Berechtigungen erstellen
mode_t old_umask = umask(0077); // Am restriktivsten
int fd = open(filename, O_CREAT | O_WRONLY | O_EXCL, desired_mode);
if (fd < 0) {
umask(old_umask);
return;
}
write(fd, content, strlen(content));
close(fd);
// Behoben: Explizites chmod() für exakte Berechtigungen verwenden
if (chmod(filename, desired_mode) != 0) {
perror("chmod fehlgeschlagen");
unlink(filename); // Datei entfernen wenn Berechtigungen nicht setzbar
}
umask(old_umask);
}
// Behoben: Referenztabelle für umask-Werte
/*
* UMASK REFERENZ:
*
* umask-Wert | Dateien mit 0666 | Verzeichnisse mit 0777
* ----------+--------------------------+----------------------
* 0000 | rw-rw-rw- (0666) | rwxrwxrwx (0777)
* 0022 | rw-r--r-- (0644) | rwxr-xr-x (0755) [typischer Benutzer]
* 0027 | rw-r----- (0640) | rwxr-x--- (0750) [typischer Daemon]
* 0077 | rw------- (0600) | rwx------ (0700) [privat]
*
* Merke: umask VERWEIGERT die angegebenen Berechtigungen
* Endgültiger Modus = angeforderter_modus & ~umask
*/
// Makros für Klarheit
#define UMASK_PRIVATE 0077 // Verweigere alle Gruppe/Ändere
#define UMASK_USER_DEFAULT 0022 // Verweigere Gruppe/Andere Schreiben
#define UMASK_DAEMON 0027 // Verweigere Gruppe Schreiben, alle Ändere
void example_usage() {
// Für private Dateien (Anmeldeinformationen, Schlüssel)
umask(UMASK_PRIVATE);
// Für normale Benutzerdateien
umask(UMASK_USER_DEFAULT);
// Für Daemon-Dateien
umask(UMASK_DAEMON);
}
CVE-Beispiele
Keine spezifischen CVEs für diese CWE, aber falsche umask-Verwendung hat zu zahlreichen lokalen Privilegieneskalations-Schwachstellen in Unix/Linux-Anwendungen beigetragen.
Referenzen
- MITRE Corporation. "CWE-560: Use of umask() with chmod-style Argument." https://cwe.mitre.org/data/definitions/560.html
- IEEE Std 1003.1 (POSIX). "umask - set and get the file mode creation mask."
- Linux man pages. "umask(2) - set file mode creation mask."