Fehlende Administrator-Kontrolle über Sicherheit
Beschreibung
Fehlende Administrator-Kontrolle über Sicherheit tritt auf, wenn ein Produkt Administratoren keine ausreichende Kontrolle zur Verwaltung von Sicherheitseinstellungen und -konfigurationen bietet. Dies umfasst hartcodierte Sicherheitsrichtlinien, Unfähigkeit Standard-Anmeldedaten zu ändern, fehlende Audit-Kontrollen, fehlende Schalter für Sicherheitsfunktionen und das Fehlen granularer Berechtigungsverwaltung. Administratoren können die Sicherheitshaltung nicht an die Bedürfnisse ihrer Organisation anpassen.
Risiko
Organisationen können Sicherheitsrichtlinien nicht durchsetzen. Standard-Anmeldedaten bleiben unverändert. Sicherheitsfunktionen können nicht nach Bedarf aktiviert/deaktiviert werden. Keine Möglichkeit, regulatorische Anforderungen zu erfüllen. Unfähigkeit, auf Sicherheitsvorfälle zu reagieren. Audit- und Überwachungslücken. Einheits-Sicherheit für alle Umgebungen ungeeignet.
Lösung
Bieten Sie umfassende Sicherheitskonfigurationsschnittstellen. Ermöglichen Sie Anmeldedaten-Management und -Rotation. Implementieren Sie granulare rollenbasierte Zugriffskontrolle. Stellen Sie Sicherheits-Audit-Logging mit konfigurierbaren Stufen bereit. Ermöglichen Sie Aktivieren/Deaktivieren von Sicherheitsfunktionen über Konfiguration. Dokumentieren Sie alle Sicherheitseinstellungen. Unterstützen Sie Anpassung von Sicherheitsrichtlinien.
Häufige Konsequenzen
| Auswirkung | Details |
|---|---|
| Sicherheit | Bereich: Unfähigkeit zur Anpassung Sicherheit kann nicht an Umgebung angepasst werden. |
| Compliance | Bereich: Regulatorisches Versagen Kann Sicherheits-Audit-Anforderungen nicht erfüllen. |
| Betrieb | Bereich: Vorfallreaktion Kann nicht effektiv auf Sicherheitsereignisse reagieren. |
Beispielcode + Lösungscode
Verwundbarer Code
// VERWUNDBAR: Keine administrativen Sicherheitskontrollen
public class VulnerableSecurityConfig {
// VERWUNDBAR: Hartcodierte Anmeldedaten, keine Änderungsmöglichkeit
private static final String ADMIN_USERNAME = "admin";
private static final String ADMIN_PASSWORD = "admin123";
public boolean authenticate(String username, String password) {
// VERWUNDBAR: Kann diese Anmeldedaten nicht ändern
return ADMIN_USERNAME.equals(username) &&
ADMIN_PASSWORD.equals(password);
}
// VERWUNDBAR: Hartcodiertes Session-Timeout
private static final int SESSION_TIMEOUT = 3600; // 1 Stunde, unveränderlich
// VERWUNDBAR: Hartcodierte Passwort-Richtlinie
public boolean isPasswordValid(String password) {
return password.length() >= 6; // Fest, kann nicht verstärkt werden
}
// VERWUNDBAR: Keine Audit-Kontrolle
public void performAdminAction(String action) {
// Kein Logging, keine Audit-Spur
executeAction(action);
}
// VERWUNDBAR: Alles-oder-nichts-Berechtigungen
public boolean hasPermission(User user, String resource) {
// Nur Admin oder regulärer Benutzer, keine Granularität
return user.isAdmin();
}
// VERWUNDBAR: Sicherheitsfunktionen hartcodiert
private boolean mfaEnabled = false; // Kann nicht geändert werden
private boolean bruteForceProtection = false; // Keine Möglichkeit zu aktivieren
}
// VERWUNDBAR: Keine Sicherheitskonfigurations-API
@RestController
public class VulnerableAdminController {
// Keine Endpoints für:
// - Ändern von Sicherheitseinstellungen
// - Verwalten von Benutzern/Rollen
// - Anzeigen von Audit-Logs
// - Konfigurieren der Authentifizierung
}
# VERWUNDBAR: Python-Anwendung ohne Sicherheitskontrollen
class VulnerableApp:
# VERWUNDBAR: Hartcodierte Einstellungen
SECRET_KEY = "hardcoded_secret_key_12345"
ADMIN_PASSWORD = "admin"
# VERWUNDBAR: Keine konfigurierbaren Sicherheitsrichtlinien
PASSWORD_MIN_LENGTH = 4 # Fest, zu schwach
SESSION_DURATION = 86400 # 24 Stunden, unveränderlich
MAX_LOGIN_ATTEMPTS = None # Kein Rate-Limiting
def __init__(self):
# VERWUNDBAR: Keine Konfigurationsmöglichkeit
self.debug_mode = True # Immer an
self.ssl_verify = False # Kann nicht aktivieren
# VERWUNDBAR: Keine Audit-Logging-Konfiguration
def admin_action(self, action, user):
# Keine Option zum Loggen, keine Schweregrade
self.execute(action)
# VERWUNDBAR: Fester Authentifizierungsmechanismus
def authenticate(self, username, password):
# Keine MFA-Option
# Keine OAuth/SAML-Integration
# Einzelne feste Auth-Methode
return self.check_password(username, password)
# VERWUNDBAR: Keine Rollenanpassung
def check_permission(self, user, action):
# Hartcodierte Rollen, kann keine benutzerdefinierten erstellen
return user.role == 'admin'
# VERWUNDBAR: Keine Sicherheitskonfigurationsdatei-Unterstützung
# Keine Möglichkeit, Sicherheitseinstellungen aus Konfig zu laden
# Keine umgebungsspezifischen Sicherheitsprofile
// VERWUNDBAR: Node.js-App ohne Sicherheitskontrollen
const express = require('express');
const app = express();
// VERWUNDBAR: Hartcodierte Sicherheitseinstellungen
const config = {
jwtSecret: 'hardcoded_jwt_secret', // Kann nicht ändern
sessionTimeout: 3600, // Fest
corsOrigin: '*', // Kann nicht einschränken
rateLimitEnabled: false // Kann nicht aktivieren
};
// VERWUNDBAR: Keine Möglichkeit, Sicherheitsheader zu modifizieren
app.use((req, res, next) => {
// Hartcodierte Header, nicht konfigurierbar
res.setHeader('X-Frame-Options', 'SAMEORIGIN');
// Admin kann nicht auf DENY ändern
next();
});
// VERWUNDBAR: Feste Authentifizierung
class VulnerableAuth {
constructor() {
// Keine Konfigurationsoptionen
this.hashRounds = 10; // Fest
this.tokenExpiry = '1h'; // Fest
this.mfaEnabled = false; // Kann nicht aktivieren
}
// Keine Admin-Methoden für:
// - Ändern von Sicherheitseinstellungen
// - Verwalten von API-Schlüsseln
// - Anzeigen von Sicherheitslogs
// - Konfigurieren von Rate-Limits
}
// VERWUNDBAR: Kein Sicherheits-Dashboard oder Management-UI
// VERWUNDBAR: Keine API für Sicherheitskonfiguration
// VERWUNDBAR: Kein Audit-Log-Zugriff
<?php
// VERWUNDBAR: PHP-Anwendung ohne Admin-Kontrollen
class VulnerableConfig {
// VERWUNDBAR: Hartcodierte Sicherheitskonstanten
const ADMIN_USER = 'admin';
const ADMIN_PASS = 'password123';
const SESSION_LIFETIME = 3600;
const PASSWORD_ALGO = PASSWORD_DEFAULT;
const MIN_PASSWORD_LENGTH = 4;
// Keine Möglichkeit, diese zur Laufzeit zu ändern
// Keine Admin-Schnittstelle zum Modifizieren
}
// VERWUNDBAR: Keine konfigurierbaren Sicherheitsfunktionen
class VulnerableSecurityManager {
private $features = [
'csrf_protection' => true, // Hartcodiert
'xss_filtering' => false, // Kann nicht aktivieren
'sql_escaping' => true,
'rate_limiting' => false, // Kann nicht aktivieren
'ip_blocking' => false, // Kann nicht aktivieren
];
// Keine Setter, keine Admin-Schnittstelle
public function isEnabled($feature) {
return $this->features[$feature] ?? false;
}
// VERWUNDBAR: Keine Audit-Fähigkeiten
public function logSecurityEvent($event) {
// Logging ist hartcodiert aus, keine Möglichkeit zu aktivieren
// Keine Log-Level-Konfiguration
// Keine Log-Ziel-Optionen
}
}
// VERWUNDBAR: Keine Benutzer/Rollen-Verwaltung
class VulnerableUserManager {
// Hartcodierte Rollen
private $roles = ['admin', 'user']; // Kann keine benutzerdefinierten Rollen hinzufügen
// Hartcodierte Berechtigungen
private $permissions = [
'admin' => ['*'],
'user' => ['read']
];
// Kann nicht modifizieren, keine RBAC-Schnittstelle
}
?>
Lösungscode
// SICHER: Umfassende administrative Sicherheitskontrollen
@Configuration
public class SecureSecurityConfig {
@Value("${security.session.timeout:3600}")
private int sessionTimeout;
@Value("${security.password.minLength:12}")
private int minPasswordLength;
@Value("${security.mfa.enabled:false}")
private boolean mfaEnabled;
@Value("${security.bruteforce.protection:true}")
private boolean bruteForceProtection;
// SICHER: Anmeldedaten aus sicherer Konfiguration
@Value("${admin.password.hash}")
private String adminPasswordHash;
// SICHER: Konfigurierbare Passwort-Richtlinie
@Bean
public PasswordPolicy passwordPolicy() {
return PasswordPolicy.builder()
.minLength(minPasswordLength)
.requireUppercase(configService.getBoolean("password.requireUppercase", true))
.requireNumber(configService.getBoolean("password.requireNumber", true))
.requireSpecial(configService.getBoolean("password.requireSpecial", false))
.build();
}
}
// SICHER: Admin-Sicherheitsverwaltungs-API
@RestController
@RequestMapping("/admin/security")
@PreAuthorize("hasRole('SECURITY_ADMIN')")
public class SecurityAdminController {
@Autowired
private SecurityConfigService securityConfigService;
@Autowired
private AuditService auditService;
// SICHER: Sicherheitseinstellungen aktualisieren
@PutMapping("/settings")
public ResponseEntity<?> updateSecuritySettings(@RequestBody SecuritySettings settings) {
auditService.log("SECURITY_SETTINGS_CHANGE", settings);
securityConfigService.update(settings);
return ResponseEntity.ok().build();
}
// SICHER: Passwort-Richtlinie konfigurieren
@PutMapping("/password-policy")
public ResponseEntity<?> updatePasswordPolicy(@RequestBody PasswordPolicy policy) {
auditService.log("PASSWORD_POLICY_CHANGE", policy);
securityConfigService.updatePasswordPolicy(policy);
return ResponseEntity.ok().build();
}
// SICHER: MFA aktivieren/deaktivieren
@PostMapping("/mfa/toggle")
public ResponseEntity<?> toggleMFA(@RequestParam boolean enabled) {
auditService.log("MFA_TOGGLE", enabled);
securityConfigService.setMFAEnabled(enabled);
return ResponseEntity.ok().build();
}
// SICHER: Sicherheits-Audit-Logs anzeigen
@GetMapping("/audit")
public ResponseEntity<List<AuditEvent>> getAuditLogs(
@RequestParam(required = false) String startDate,
@RequestParam(required = false) String endDate,
@RequestParam(required = false) String eventType) {
return ResponseEntity.ok(auditService.query(startDate, endDate, eventType));
}
// SICHER: Sicherheitsfunktionen verwalten
@GetMapping("/features")
public ResponseEntity<Map<String, Boolean>> getSecurityFeatures() {
return ResponseEntity.ok(securityConfigService.getAllFeatures());
}
@PutMapping("/features/{feature}")
public ResponseEntity<?> toggleFeature(
@PathVariable String feature,
@RequestParam boolean enabled) {
auditService.log("FEATURE_TOGGLE", feature + ":" + enabled);
securityConfigService.setFeature(feature, enabled);
return ResponseEntity.ok().build();
}
}
// SICHER: Rollenbasierte Zugriffskontrollverwaltung
@RestController
@RequestMapping("/admin/rbac")
public class RBACAdminController {
@PostMapping("/roles")
public ResponseEntity<?> createRole(@RequestBody Role role) {
return ResponseEntity.ok(rbacService.createRole(role));
}
@PutMapping("/roles/{roleId}/permissions")
public ResponseEntity<?> updatePermissions(
@PathVariable Long roleId,
@RequestBody List<Permission> permissions) {
return ResponseEntity.ok(rbacService.updatePermissions(roleId, permissions));
}
}
# SICHER: Python mit umfassenden Admin-Kontrollen
from dataclasses import dataclass
from typing import Dict, Any, Optional
import yaml
@dataclass
class SecuritySettings:
session_timeout: int = 3600
password_min_length: int = 12
password_require_uppercase: bool = True
password_require_number: bool = True
password_require_special: bool = True
mfa_enabled: bool = False
rate_limiting_enabled: bool = True
max_login_attempts: int = 5
lockout_duration: int = 900
audit_level: str = 'INFO'
class SecurityConfigService:
def __init__(self, config_path: str = '/etc/app/security.yaml'):
self.config_path = config_path
self.settings = self._load_settings()
self.audit_logger = AuditLogger()
def _load_settings(self) -> SecuritySettings:
"""Einstellungen aus Konfigurationsdatei laden"""
try:
with open(self.config_path) as f:
config = yaml.safe_load(f)
return SecuritySettings(**config.get('security', {}))
except FileNotFoundError:
return SecuritySettings()
def update_setting(self, key: str, value: Any, admin_user: str):
"""Admin kann jede Sicherheitseinstellung aktualisieren"""
old_value = getattr(self.settings, key, None)
# Änderung protokollieren
self.audit_logger.log(
event='SECURITY_SETTING_CHANGE',
user=admin_user,
details={
'setting': key,
'old_value': old_value,
'new_value': value
}
)
setattr(self.settings, key, value)
self._save_settings()
def _save_settings(self):
"""Einstellungen in Konfigurationsdatei speichern"""
with open(self.config_path, 'w') as f:
yaml.dump({'security': asdict(self.settings)}, f)
def get_all_settings(self) -> Dict[str, Any]:
"""Alle Einstellungen für Admin-UI abrufen"""
return asdict(self.settings)
# SICHER: Admin-API für Sicherheitsverwaltung
from flask import Flask, request, jsonify
from functools import wraps
app = Flask(__name__)
security_service = SecurityConfigService()
def require_security_admin(f):
@wraps(f)
def decorated(*args, **kwargs):
user = get_current_user()
if not user.has_role('SECURITY_ADMIN'):
return jsonify({'error': 'Verboten'}), 403
return f(*args, **kwargs)
return decorated
@app.route('/admin/security/settings', methods=['GET'])
@require_security_admin
def get_security_settings():
"""Alle Sicherheitseinstellungen abrufen"""
return jsonify(security_service.get_all_settings())
@app.route('/admin/security/settings/<key>', methods=['PUT'])
@require_security_admin
def update_security_setting(key):
"""Eine Sicherheitseinstellung aktualisieren"""
value = request.json.get('value')
admin_user = get_current_user().username
security_service.update_setting(key, value, admin_user)
return jsonify({'success': True})
@app.route('/admin/security/audit', methods=['GET'])
@require_security_admin
def get_audit_logs():
"""Sicherheits-Audit-Logs abfragen"""
start = request.args.get('start')
end = request.args.get('end')
event_type = request.args.get('type')
logs = audit_service.query(start, end, event_type)
return jsonify(logs)
@app.route('/admin/security/features', methods=['GET', 'PUT'])
@require_security_admin
def manage_features():
"""Sicherheitsfunktionen-Schalter verwalten"""
if request.method == 'GET':
return jsonify(security_service.get_features())
else:
feature = request.json.get('feature')
enabled = request.json.get('enabled')
security_service.toggle_feature(feature, enabled, get_current_user())
return jsonify({'success': True})
# SICHER: Rollen- und Berechtigungsverwaltung
@app.route('/admin/rbac/roles', methods=['GET', 'POST'])
@require_security_admin
def manage_roles():
if request.method == 'GET':
return jsonify(rbac_service.get_all_roles())
else:
role = request.json
created = rbac_service.create_role(role)
return jsonify(created), 201
// SICHER: Node.js mit Admin-Sicherheitskontrollen
const express = require('express');
const fs = require('fs');
const yaml = require('js-yaml');
class SecurityConfigService {
constructor(configPath = '/etc/app/security.yaml') {
this.configPath = configPath;
this.settings = this.loadSettings();
this.auditLogger = new AuditLogger();
}
loadSettings() {
try {
const config = yaml.load(fs.readFileSync(this.configPath));
return {
sessionTimeout: config.session?.timeout ?? 3600,
passwordMinLength: config.password?.minLength ?? 12,
mfaEnabled: config.mfa?.enabled ?? false,
rateLimitEnabled: config.rateLimit?.enabled ?? true,
maxLoginAttempts: config.rateLimit?.maxAttempts ?? 5,
corsOrigins: config.cors?.origins ?? [],
auditLevel: config.audit?.level ?? 'INFO',
...config
};
} catch (e) {
return this.getDefaultSettings();
}
}
updateSetting(key, value, adminUser) {
const oldValue = this.settings[key];
this.auditLogger.log({
event: 'SECURITY_SETTING_CHANGE',
user: adminUser,
setting: key,
oldValue,
newValue: value
});
this.settings[key] = value;
this.saveSettings();
}
saveSettings() {
fs.writeFileSync(this.configPath, yaml.dump(this.settings));
}
getAllSettings() {
return { ...this.settings };
}
}
// SICHER: Admin-Sicherheits-API
const router = express.Router();
const securityService = new SecurityConfigService();
// Middleware für Sicherheits-Admin-Prüfung
const requireSecurityAdmin = (req, res, next) => {
if (!req.user?.hasRole('SECURITY_ADMIN')) {
return res.status(403).json({ error: 'Verboten' });
}
next();
};
router.use(requireSecurityAdmin);
// Alle Sicherheitseinstellungen abrufen
router.get('/settings', (req, res) => {
res.json(securityService.getAllSettings());
});
// Sicherheitseinstellung aktualisieren
router.put('/settings/:key', (req, res) => {
const { key } = req.params;
const { value } = req.body;
securityService.updateSetting(key, value, req.user.username);
res.json({ success: true });
});
// Sicherheitsfunktionen verwalten
router.get('/features', (req, res) => {
res.json(securityService.getFeatures());
});
router.put('/features/:feature', (req, res) => {
const { feature } = req.params;
const { enabled } = req.body;
securityService.toggleFeature(feature, enabled, req.user);
res.json({ success: true });
});
// Audit-Logs abfragen
router.get('/audit', async (req, res) => {
const { start, end, type } = req.query;
const logs = await auditService.query(start, end, type);
res.json(logs);
});
// RBAC-Verwaltung
router.get('/roles', (req, res) => {
res.json(rbacService.getAllRoles());
});
router.post('/roles', (req, res) => {
const role = rbacService.createRole(req.body);
res.status(201).json(role);
});
router.put('/roles/:roleId/permissions', (req, res) => {
rbacService.updatePermissions(req.params.roleId, req.body.permissions);
res.json({ success: true });
});
module.exports = router;
Ausgenutzt in der Praxis
Hartcodierte Anmeldedaten
Standardpasswörter, die nicht geändert werden können, werden im großen Stil ausgenutzt.
Compliance-Versagen
Organisationen scheitern an Audits wegen unflexibler Sicherheit.
Vorfallreaktionslücken
Unfähigkeit, auf Verstöße zu reagieren wegen fehlender Kontrollen.
Werkzeuge zum Testen/Ausnutzen
-
Sicherheitskonfigurationsscanner.
-
Compliance-Audit-Tools.
-
Standard-Anmeldedaten-Scanner.
CVE-Beispiele
-
Zahlreiche CVEs durch hartcodierte Anmeldedaten.
-
IoT-Geräte mit unveränderlichen Passwörtern.
Referenzen
-
MITRE. "CWE-671: Lack of Administrator Control over Security." https://cwe.mitre.org/data/definitions/671.html
-
NIST-Sicherheitskonfigurationsrichtlinien.