Erstellung temporärer Datei mit unsicheren Berechtigungen
Beschreibung
Erstellung temporärer Datei mit unsicheren Berechtigungen ist eine Schwachstelle, die auftritt, wenn eine Anwendung temporäre Dateien mit Berechtigungen erstellt, die unbeabsichtigten Zugriff durch andere Benutzer oder Prozesse ermöglichen. Viele Standardbibliotheksfunktionen zum Erstellen temporärer Dateien verwenden Standardberechtigungen, die zu freizügig sind, wodurch die Datei von allen Benutzern auf dem System lesbar oder beschreibbar ist. Dies ist besonders problematisch in gemeinsam genutzten Verzeichnissen wie /tmp auf Unix-Systemen oder C:\Windows\Temp unter Windows, wo mehrere Benutzer Zugang haben.
Risiko
Temporäre Dateien mit unsicheren Berechtigungen offenbaren sensible Daten an lokale Angreifer. Alle Daten, die in für alle lesbare temporäre Dateien geschrieben werden, können von anderen Benutzern auf dem System abgerufen werden. Wenn die Dateien beschreibbar sind, können Angreifer den Inhalt modifizieren, was potenziell zu Codeausführung führt, wenn die Anwendung dem Dateiinhalt vertraut. Sensible Informationen wie Session-Tokens, Verschlüsselungsschlüssel, Anmeldedaten oder Benutzerdaten können offengelegt werden. In Mehrbenutzerumgebungen wie gemeinsam genutzten Servern ist diese Schwachstelle besonders schwerwiegend, da jeder Benutzer auf die temporären Dateien eines anderen Benutzers zugreifen kann.
Lösung
Verwenden Sie zeitgemäße Sprachfunktionen, die die temporäre Dateierstellung mit restriktiven Berechtigungen ordnungsgemäß handhaben. Setzen Sie Dateiberechtigungen, die nur dem besitzenden Prozess Zugriff erlauben (Modus 0600 auf Unix). Erstellen Sie temporäre Dateien in Benutzer-spezifischen Verzeichnissen statt gemeinsam genutzten Systemverzeichnissen. Verwenden Sie mkstemp() in C/C++, das Dateien standardmäßig mit Modus 0600 erstellt. In Java verwenden Sie Files.createTempFile() mit expliziten PosixFilePermission-Attributen. Verifizieren Sie Berechtigungen sofort nach Dateierstellung. Erwägen Sie die Verwendung von speicherbasiertem temporärem Storage für kleine Mengen sensibler Daten.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Umfang: Vertraulichkeit Angreifer können temporäre Dateien lesen, die sensible Informationen enthalten. |
| Integrität | Umfang: Integrität Wenn von Angreifern beschreibbar, könnten Dateien modifiziert werden, um Datenstrukturen und Prozessbesitz zu ändern. |
| Autorisierung | Umfang: Autorisierung Modifizierte Dateien könnten verschoben werden, um unautorisierten Ressourcenzugang zu erlangen. |
Beispielcode
Anfälliger Code
// Anfällig: tmpfile() erstellt Dateien mit unsicheren Berechtigungen
void vulnerable_tmpfile() {
FILE *fp = tmpfile(); // Kann Datei mit 0666 Berechtigungen erstellen
if (fp) {
fprintf(fp, "Geheimer Schlüssel: %s\n", secret_key);
// Andere Benutzer können dies lesen!
fclose(fp);
}
}
// Anfällig: open() mit freizügigem Modus verwenden
void vulnerable_open_temp() {
char template[] = "/tmp/myapp.XXXXXX";
int fd = mkstemp(template);
if (fd >= 0) {
// Anfällig: Berechtigungen auf für alle lesbar ändern
chmod(template, 0644); // Jetzt kann jeder lesen!
write(fd, secret_data, strlen(secret_data));
close(fd);
}
}
// Anfällig: File.createTempFile() hat unsichere Standardberechtigungen
import java.io.*;
public class VulnerableTempPermissions {
public void storeSecret(String secret) throws IOException {
// Anfällig: Erstellt mit -rw-r--r-- (644) auf Unix
File temp = File.createTempFile("secret", ".tmp");
try (PrintWriter writer = new PrintWriter(temp)) {
writer.println(secret); // Für alle lesbar!
}
}
public void storeInSharedDir(String data) throws IOException {
// Anfällig: Gemeinsames Verzeichnis mit Standardberechtigungen
File temp = new File("/tmp", "app_" + System.currentTimeMillis());
temp.createNewFile(); // Standardmäßig für alle lesbar
Files.writeString(temp.toPath(), data);
}
}
# Anfällig: os.open mit freizügigem Modus
import os
import tempfile
def vulnerable_temp_permissions():
# Anfällig: Für alle lesbare Berechtigungen
fd = os.open('/tmp/myapp.tmp', os.O_CREAT | os.O_WRONLY, 0o644)
os.write(fd, b"sensible daten")
os.close(fd)
def vulnerable_named_temp():
# Anfällig: Kann unsichere Standardberechtigungen haben
with open('/tmp/secrets.txt', 'w') as f:
f.write("password=secret123")
# Datei mit umask erstellt, möglicherweise für alle lesbar
Korrigierter Code
// Korrigiert: mkstemp() mit sicheren Standardberechtigungen
void secure_temp_file() {
char template[] = "/tmp/myapp.XXXXXX";
int fd;
// Korrigiert: mkstemp erstellt mit Modus 0600
fd = mkstemp(template);
if (fd < 0) {
perror("mkstemp");
return;
}
// Sofort unlinken um vor anderen Prozessen zu verbergen
unlink(template);
write(fd, secret_data, strlen(secret_data));
close(fd);
}
// Korrigiert: Explizite restriktive Berechtigungen
void secure_explicit_perms() {
char template[] = "/tmp/myapp.XXXXXX";
int fd;
mode_t old_umask;
// Korrigiert: Restriktive umask setzen
old_umask = umask(0077);
fd = mkstemp(template);
// Ursprüngliche umask wiederherstellen
umask(old_umask);
if (fd >= 0) {
// Verifizieren dass Berechtigungen korrekt sind
struct stat st;
fstat(fd, &st);
if ((st.st_mode & 0777) != 0600) {
close(fd);
unlink(template);
return; // Unerwartete Berechtigungen
}
write(fd, secret_data, strlen(secret_data));
close(fd);
}
}
// Korrigiert: Files.createTempFile mit expliziten Berechtigungen
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.util.Set;
public class SecureTempPermissions {
public void storeSecret(String secret) throws IOException {
// Korrigiert: Explizit restriktive Berechtigungen setzen
Set<PosixFilePermission> perms =
PosixFilePermissions.fromString("rw-------");
FileAttribute<Set<PosixFilePermission>> attr =
PosixFilePermissions.asFileAttribute(perms);
Path temp = Files.createTempFile("secret", ".tmp", attr);
try {
Files.writeString(temp, secret);
} finally {
Files.deleteIfExists(temp);
}
}
public void storeInSecureDir(String data) throws IOException {
// Korrigiert: Zuerst privates Verzeichnis erstellen
Path privateDir = Paths.get(System.getProperty("user.home"), ".myapp", "tmp");
if (!Files.exists(privateDir)) {
Set<PosixFilePermission> dirPerms =
PosixFilePermissions.fromString("rwx------");
Files.createDirectories(privateDir,
PosixFilePermissions.asFileAttribute(dirPerms));
}
// Korrigiert: Temp-Datei im privaten Verzeichnis erstellen
Set<PosixFilePermission> filePerms =
PosixFilePermissions.fromString("rw-------");
Path temp = Files.createTempFile(privateDir, "app_", ".tmp",
PosixFilePermissions.asFileAttribute(filePerms));
Files.writeString(temp, data);
}
}
# Korrigiert: Sichere temporäre Dateierstellung
import os
import tempfile
import stat
def secure_temp_permissions():
# Korrigiert: os.open mit restriktiven Berechtigungen verwenden
fd = os.open('/tmp/myapp.tmp',
os.O_CREAT | os.O_WRONLY | os.O_EXCL,
0o600)
try:
os.write(fd, b"sensible daten")
finally:
os.close(fd)
def secure_named_temp():
# Korrigiert: tempfile.NamedTemporaryFile ist standardmäßig sicher
with tempfile.NamedTemporaryFile(mode='w', delete=True) as f:
f.write("password=secret123")
# Datei mit Modus 0600 erstellt
process_file(f.name)
def secure_mkstemp():
# Korrigiert: mkstemp erstellt sichere Datei
fd, path = tempfile.mkstemp(suffix='.tmp', prefix='secure_')
try:
# Berechtigungen verifizieren
mode = os.stat(path).st_mode
assert (mode & 0o777) == 0o600, "Unerwartete Berechtigungen"
os.write(fd, b"sensible daten")
finally:
os.close(fd)
os.unlink(path)
CVE-Beispiele
- CVE-2022-24823 — Die Verwendung von Javas createTempFile() durch ein Netzwerk-Anwendungsframework erstellte Dateien, die von anderen lokalen Systembenutzern lesbar waren.
Referenzen
- MITRE Corporation. "CWE-378: Creation of Temporary File With Insecure Permissions." https://cwe.mitre.org/data/definitions/378.html
- OWASP. "Insecure Temporary File." https://owasp.org/www-community/vulnerabilities/Insecure_Temporary_File