Keine Verwendung von Passwortalterung
Beschreibung
Keine Verwendung von Passwortalterung ist eine Schwachstelle, die auftritt, wenn ein Produkt keine Mechanismen zur Verwaltung von Passwortablauf und erzwungener Rotation hat. Passwortalterungsrichtlinien erfordern von Benutzern, ihre Passwörter nach einem definierten Zeitraum (z.B. alle 30, 60 oder 90 Tage) zu ändern, was das Zeitfenster für Angreifer begrenzt, die Anmeldedaten erhalten haben. Während moderne Sicherheitsrichtlinien von obligatorischer Passwortrotation aufgrund von Bedenken über Passwortermüdung und schwächere Passwortauswahl abgewichen sind, bleibt Passwortalterung für Compliance-Anforderungen (wie PCI DSS) und für Hochsicherheitsumgebungen relevant, in denen Anmeldedaten-Kompromittierungsrisiken erhöht sind.
Risiko
Das Fehlen von Passwortalterungsmechanismen erhöht das Risikofenster für Anmeldedaten-Kompromittierungsangriffe. Passwörter, die nie ablaufen, bieten Angreifern unbegrenzte Zeit, um erhaltene Passwort-Hashes durch Brute-Force- oder Wörterbuch-Angriffe zu knacken. Kompromittierte Anmeldedaten bleiben unbegrenzt gültig, was dauerhaften unbefugten Zugriff ermöglicht. In Umgebungen, in denen Passwortdiebstahl unentdeckt bleibt, behalten Angreifer Zugang, bis Passwörter aus anderen Gründen geändert werden. Das Risiko ist besonders akut für Service-Konten und administrative Anmeldedaten, die möglicherweise keinen regelmäßigen benutzergesteuerten Änderungen unterliegen. Es ist jedoch wichtig zu beachten, dass moderne Sicherheitsforschung nahelegt, dass der Fokus auf Passwortstärke, Breach-Erkennung und Multi-Faktor-Authentifizierung möglicherweise effektiver ist als obligatorische Rotation.
Lösung
Implementieren Sie Passwortalterungsrichtlinien, die Ihren Sicherheitsanforderungen und Compliance-Verpflichtungen entsprechen. Konfigurieren Sie Passwortablaufzeiträume basierend auf Risikobewertung – kürzere Zeiträume (30-90 Tage) für hochprivilegierte Konten und längere Zeiträume oder kein Ablauf für Standardkonten mit aktivierter MFA. Bieten Sie Benutzern vor dem Passwortablauf Vorankündigungen. Implementieren Sie Kontosperrung oder Zugriffsbeschränkungen, wenn Passwörter ablaufen. Führen Sie Passwortverläufe, um die Wiederverwendung kürzlicher Passwörter zu verhindern. Erwägen Sie Alternativen zur obligatorischen Rotation wie kompromittierte Anmeldedaten-Erkennungsdienste, Multi-Faktor-Authentifizierung und durch Breach-Benachrichtigung ausgelöste Passwortzurücksetzungen. Für Compliance-getriebene Anforderungen (PCI DSS, HIPAA) implementieren Sie die minimal erforderlichen Rotationszeiträume. Dokumentieren Sie Ausnahmen für Service-Konten mit entsprechenden kompensierenden Kontrollen.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Zugriffskontrolle | Bereich: Zugriffskontrolle Ohne Passwortalterung bleiben kompromittierte Anmeldedaten unbegrenzt gültig. Angreifer, die Passwörter durch Diebstahl, Knacken oder Social Engineering erhalten, behalten dauerhaften Zugang, bis das Passwort aus anderen Gründen geändert wird, was die Wahrscheinlichkeit von Privilegieneskalation und Identitätsannahme erhöht. |
Beispielcode
Anfälliger Code (Java/Spring Security)
Der folgende Code demonstriert ein System ohne Passwortalterung:
@Configuration
public class VulnerableSecurityConfig {
// Anfällig: Kein Passwortalterungsmechanismus
@Bean
public UserDetailsService userDetailsService() {
return new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String username) {
User user = userRepository.findByUsername(username);
// Keine Prüfung auf Passwortablauf
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
true, // enabled
true, // accountNonExpired
true, // credentialsNonExpired - IMMER TRUE!
true, // accountNonLocked
user.getAuthorities()
);
}
};
}
}
@Entity
public class VulnerableUser {
@Id
private Long id;
private String username;
private String password;
// Kein passwordLastChanged-Feld
// Kein passwordExpirationDate-Feld
// Kein Mechanismus zum Verfolgen oder Durchsetzen von Passwortalterung
}
-- Anfällig: Benutzertabelle ohne Passwortalterungsfelder
CREATE TABLE users (
id BIGINT PRIMARY KEY,
username VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
-- Keine password_last_changed-Spalte
-- Keine password_expires_at-Spalte
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Korrigierter Code (Java/Spring Security)
@Configuration
public class SecureSecurityConfig {
@Value("${security.password.max-age-days:90}")
private int passwordMaxAgeDays;
@Bean
public UserDetailsService userDetailsService() {
return new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String username) {
User user = userRepository.findByUsername(username);
// Prüfen ob Passwort abgelaufen ist
boolean credentialsNonExpired = !isPasswordExpired(user);
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
user.isEnabled(),
true, // accountNonExpired
credentialsNonExpired, // Basierend auf Passwortalter
!user.isLocked(),
user.getAuthorities()
);
}
};
}
private boolean isPasswordExpired(User user) {
if (user.getPasswordLastChanged() == null) {
return true; // Änderung erzwingen wenn nie gesetzt
}
LocalDateTime expirationDate = user.getPasswordLastChanged()
.plusDays(passwordMaxAgeDays);
return LocalDateTime.now().isAfter(expirationDate);
}
}
@Entity
public class SecureUser {
@Id
private Long id;
private String username;
private String password;
// Passwortalterungsfelder
@Column(name = "password_last_changed")
private LocalDateTime passwordLastChanged;
@Column(name = "password_expires_at")
private LocalDateTime passwordExpiresAt;
@Column(name = "force_password_change")
private boolean forcePasswordChange;
// Passwortverlauf verfolgen
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<PasswordHistory> passwordHistory;
public void setPassword(String newPassword) {
// Aktuelles Passwort zum Verlauf hinzufügen vor Änderung
if (this.password != null) {
PasswordHistory history = new PasswordHistory();
history.setUser(this);
history.setPasswordHash(this.password);
history.setChangedAt(this.passwordLastChanged);
passwordHistory.add(history);
}
this.password = newPassword;
this.passwordLastChanged = LocalDateTime.now();
this.passwordExpiresAt = LocalDateTime.now().plusDays(90);
this.forcePasswordChange = false;
}
}
@Service
public class PasswordAgingService {
@Value("${security.password.warning-days:14}")
private int warningDays;
public void checkPasswordExpiration(User user) {
if (user.getPasswordExpiresAt() == null) {
return;
}
LocalDateTime now = LocalDateTime.now();
LocalDateTime warningDate = user.getPasswordExpiresAt().minusDays(warningDays);
if (now.isAfter(user.getPasswordExpiresAt())) {
throw new CredentialsExpiredException("Passwort ist abgelaufen");
} else if (now.isAfter(warningDate)) {
long daysRemaining = ChronoUnit.DAYS.between(now, user.getPasswordExpiresAt());
// Benutzer über bevorstehenden Ablauf benachrichtigen
notificationService.sendPasswordExpirationWarning(user, daysRemaining);
}
}
// Passwort-Wiederverwendung verhindern
public boolean isPasswordInHistory(User user, String newPassword, int historyCount) {
return user.getPasswordHistory().stream()
.sorted(Comparator.comparing(PasswordHistory::getChangedAt).reversed())
.limit(historyCount)
.anyMatch(h -> passwordEncoder.matches(newPassword, h.getPasswordHash()));
}
}
-- Korrigiert: Benutzertabelle mit Passwortalterungsunterstützung
CREATE TABLE users (
id BIGINT PRIMARY KEY,
username VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
password_last_changed TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
password_expires_at TIMESTAMP,
force_password_change BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE password_history (
id BIGINT PRIMARY KEY,
user_id BIGINT REFERENCES users(id),
password_hash VARCHAR(255) NOT NULL,
changed_at TIMESTAMP NOT NULL
);
CREATE INDEX idx_password_expires ON users(password_expires_at);
Die Korrektur implementiert Passwortablaufverfolgung, Verlauf zur Verhinderung von Wiederverwendung, Warnbenachrichtigungen und erzwungene Passwortänderung bei Ablauf.
Ausgenutzt in der Praxis
Langzeit-Anmeldedaten-Diebstahl-Kampagnen (APT-Gruppen, Fortlaufend)
Advanced Persistent Threat-Gruppen haben den Zugang zu kompromittierten Netzwerken über Monate oder Jahre aufrechterhalten, indem sie gestohlene Anmeldedaten verwendeten, die nie abgelaufen sind. Ohne Passwortalterung, die Anmeldedaten-Rotation erzwingt, können Angreifer mit initialem Zugang durch Phishing oder andere Mittel dauerhafte Präsenz etablieren. Bemerkenswerte Beispiele umfassen die SolarWinds-Kampagne von APT29, bei der gestohlene Anmeldedaten während der gesamten Intrusion gültig blieben.
Veraltete Service-Konto-Kompromittierung (Mehrere Organisationen, Fortlaufend)
Service-Konten und Anwendungs-Anmeldedaten ohne Ablaufrichtlinien waren primäre Ziele für Angreifer. Einmal kompromittiert, bieten diese Anmeldedaten unbegrenzten Zugang, da sie selten geändert werden. Sicherheitsaudits entdecken häufig Service-Konten mit Passwörtern, die seit Jahren nicht geändert wurden.
PCI DSS Compliance-Verletzungen (Einzelhandelssektor, Mehrere Jahre)
Organisationen, die keine Passwortalterung wie von PCI DSS gefordert implementiert haben, erlitten Breaches, bei denen kompromittierte Zahlungssystem-Anmeldedaten über längere Zeiträume gültig blieben. Compliance-Audits haben Lücken bei der Passwortalterung als beitragende Faktoren bei Breach-Untersuchungen identifiziert.
Tools zum Testen/Ausnutzen
-
CrackMapExec — Testet auf Passwort-Wiederverwendung und identifiziert Konten mit lange unveränderten Passwörtern.
-
BloodHound — Active-Directory-Analysetool, das Konten mit Passwörtern identifiziert, die über längere Zeiträume nicht geändert wurden.
-
ADRecon — Generiert Berichte über Active-Directory-Passwortrichtlinien und identifiziert Konten, die Alterungsanforderungen nicht entsprechen.
CVE-Beispiele
-
CVE-2019-5544 — VMware ESXi OpenSLP-Dienst verwendete Anmeldedaten ohne Ablauf, was dauerhaften Zugang nach Kompromittierung ermöglichte.
-
CVE-2020-1472 — Zerologon-Schwachstellen-Ausnutzung wurde durch fehlende Anmeldedaten-Rotation, die Passwortänderungen erzwingt, verlangert.
Referenzen
-
MITRE Corporation. "CWE-262: Not Using Password Aging." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/262.html
-
NIST. "Digital Identity Guidelines: Authentication and Lifecycle Management." SP 800-63B. https://pages.nist.gov/800-63-3/sp800-63b.html
-
PCI Security Standards Council. "PCI DSS Requirements 8.2.4 - Password/Passphrase Changes." https://www.pcisecuritystandards.org/
-
Microsoft. "Password Guidance." https://www.microsoft.com/en-us/research/publication/password-guidance/