Übermäßige Angriffsfläche
Beschreibung
Übermäßige Angriffsfläche tritt auf, wenn ein Produkt eine Angriffsfläche hat, deren quantitative Messung ein wünschenswertes Maximum überschreitet. Eine Angriffsfläche umfasst alle Punkte, an denen nicht vertrauenswürdige Eingaben in das System gelangen können, und alle Punkte, an denen potenziell sensible Ausgaben das System verlassen. Eine größere Angriffsfläche bietet mehr potenzielle Einstiegspunkte für Angreifer und mehr Möglichkeiten für Entwickler, Schwachstellen einzuführen. Dies umfasst unnötig exponierte Endpunkte, ungenutzte Funktionen, übermäßig breite Schnittstellen, exzessive Berechtigungen und Code, der erreichbar, aber für die Kernfunktionalität des Produkts nicht erforderlich ist.
Risiko
Eine übermäßige Angriffsfläche erhöht direkt das Sicherheitsrisiko. Mehr Einstiegspunkte bedeuten mehr potenzielle Schwachstellen. Ungenutzte Funktionen erhalten möglicherweise keine Sicherheitsupdates. Breite Schnittstellen sind schwerer zu sichern und zu prüfen. Überberechtigte Komponenten können für Rechteeskalation ausgenutzt werden. Legacy- oder Debug-Funktionalität kann Schwachstellen enthalten. Größere Codebasen haben mehr potenzielle Fehler. Testabdeckung wird unpraktisch. Sicherheitsüberwachung wird komplexer. Defense in Depth ist schwerer umzusetzen.
Lösung
Wenden Sie das Prinzip der minimalen Funktionalität an – exponieren Sie nur das Notwendige. Entfernen oder deaktivieren Sie ungenutzte Funktionen, Endpunkte und Dienste. Implementieren Sie strikte Eingabevalidierung an allen Einstiegspunkten. Minimieren Sie die Anzahl exponierter Schnittstellen. Erfordern Sie Authentifizierung für alle nicht-öffentlichen Endpunkte. Wenden Sie das Prinzip der minimalen Privilegien auf Komponenten an. Entfernen Sie Debug- und Testfunktionalität aus der Produktion. Verwenden Sie Netzwerksegmentierung, um die Exposition zu begrenzen. Führen Sie regelmäßige Angriffsflächen-Analysen durch. Entfernen Sie veraltete Funktionalität, anstatt sie nur zu deaktivieren. Überwachen und protokollieren Sie alle Einstiegspunkte.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Sonstiges | Bereich: Sonstiges Variiert je nach Kontext – Die Auswirkung hängt davon ab, welche Funktionalität unnötig exponiert ist und welche Schwachstellen innerhalb dieser Angriffsfläche existieren. |
| Vertraulichkeit | Bereich: Vertraulichkeit Informationsoffenlegung – Unnötige Ausgaben können sensible Informationen preisgeben. |
| Integrität | Bereich: Integrität Unautorisierte Aktionen – Unnötige Einstiegspunkte können unautorisierte Änderungen ermöglichen. |
Beispielcode und Lösung
Verwundbarer Code
// VERWUNDBAR: Übermäßige Angriffsfläche durch unnötige Endpunkte
@RestController
@RequestMapping("/api")
public class VulnerableAPIController {
// Produktions-Endpunkte
@PostMapping("/users")
public User createUser(@RequestBody UserRequest request) {
return userService.create(request);
}
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
// UNNÖTIG: Debug-Endpunkte in Produktion belassen
@GetMapping("/debug/users/all") // Exponiert alle Benutzerdaten!
public List<User> getAllUsers() {
return userService.findAll();
}
@GetMapping("/debug/config") // Exponiert Konfiguration!
public Map<String, String> getConfig() {
return configService.getAllSettings();
}
@PostMapping("/debug/sql") // SQL Injection wartet nur darauf!
public Object executeSQL(@RequestBody String sql) {
return jdbcTemplate.queryForList(sql);
}
// UNNÖTIG: Legacy-Endpunkte, die entfernt werden sollten
@GetMapping("/v1/users/{id}") // Alte API-Version, kann Schwachstellen haben
public OldUserFormat getOldUser(@PathVariable Long id) {
return legacyService.findUser(id);
}
// UNNÖTIG: Übermäßig breiter Admin-Endpunkt
@PostMapping("/admin/execute") // Akzeptiert jeden Befehl!
@PreAuthorize("hasRole('ADMIN')")
public Object executeAdminCommand(@RequestBody AdminCommand cmd) {
return commandExecutor.execute(cmd); // Welche Befehle sind erlaubt?
}
// UNNÖTIG: Metriken ohne Authentifizierung
@GetMapping("/metrics") // Exponiert Systeminformationen für jeden!
public SystemMetrics getMetrics() {
return metricsService.collect();
}
// UNNÖTIG: Health-Check gibt zu viele Informationen preis
@GetMapping("/health")
public HealthInfo detailedHealth() {
return new HealthInfo(
dbConnection.status(),
cacheConnection.status(),
externalApis.status(),
System.getenv() // Exponiert alle Umgebungsvariablen!
);
}
}
# VERWUNDBAR: Python-Anwendung mit übermäßiger Angriffsfläche
from flask import Flask, request, jsonify
import os
import subprocess
app = Flask(__name__)
# Produktions-Endpunkte
@app.route('/api/data', methods=['POST'])
def handle_data():
return process_data(request.json)
# UNNÖTIG: Entwicklungs-Endpunkte in Produktion
@app.route('/dev/reload') # Erlaubt Hot-Reloading in Produktion!
def dev_reload():
os.execv(sys.executable, ['python'] + sys.argv)
@app.route('/dev/env') # Exponiert Umgebungsvariablen!
def show_env():
return jsonify(dict(os.environ))
@app.route('/dev/shell', methods=['POST']) # Remote-Shell!
def dev_shell():
cmd = request.json.get('cmd')
return subprocess.check_output(cmd, shell=True)
# UNNÖTIG: Catch-All-Dateibereitstellung
@app.route('/files/<path:filepath>') # Path-Traversal-Risiko!
def serve_file(filepath):
return send_file(filepath)
# UNNÖTIG: Reflexions-/Introspektions-Endpunkte
@app.route('/api/inspect/<module>')
def inspect_module(module):
import importlib
mod = importlib.import_module(module)
return jsonify({
'functions': dir(mod),
'source': inspect.getsource(mod)
})
# UNNÖTIG: Datenbankzugriff ohne angemessene Kontrollen
@app.route('/api/query', methods=['POST'])
def raw_query():
query = request.json.get('query')
return db.execute(query) # SQL Injection!
# UNNÖTIG: Zu viele Authentifizierungsmethoden
@app.route('/login/password', methods=['POST'])
def login_password(): ...
@app.route('/login/token', methods=['POST'])
def login_token(): ...
@app.route('/login/oauth', methods=['POST'])
def login_oauth(): ...
@app.route('/login/saml', methods=['POST'])
def login_saml(): ...
@app.route('/login/ldap', methods=['POST']) # Alle brauchen Wartung!
def login_ldap(): ...
@app.route('/login/legacy', methods=['POST']) # Legacy = wahrscheinlich verwundbar
def login_legacy(): ...
// VERWUNDBAR: Node.js mit übermäßig exponierter Funktionalität
const express = require('express');
const app = express();
// Produktions-Routen
app.post('/api/orders', createOrder);
app.get('/api/orders/:id', getOrder);
// UNNÖTIG: Debug-Routen in Produktion
app.get('/debug/memory', (req, res) => {
res.json(process.memoryUsage()); // Exponiert Speicherinformationen
});
app.get('/debug/heap', (req, res) => {
const heapdump = require('heapdump');
heapdump.writeSnapshot((err, filename) => {
res.download(filename); // Gibt Heap-Inhalte preis!
});
});
app.post('/debug/eval', (req, res) => {
const result = eval(req.body.code); // Remote Code Execution!
res.json({ result });
});
// UNNÖTIG: Übermäßig permissive CORS
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*'); // Erlaubt jeden Ursprung
res.header('Access-Control-Allow-Methods', '*'); // Erlaubt jede Methode
res.header('Access-Control-Allow-Headers', '*'); // Erlaubt jeden Header
next();
});
// UNNÖTIG: GraphQL mit aktivierter Introspektion
const { graphqlHTTP } = require('express-graphql');
app.use('/graphql', graphqlHTTP({
schema: schema,
graphiql: true, // Interaktive UI in Produktion!
introspection: true, // Exponiert gesamtes Schema!
}));
// UNNÖTIG: Admin ohne Rate Limiting
app.use('/admin', adminRoutes); // Kein Rate Limiting für Admin
// UNNÖTIG: Datei-Upload ohne Einschränkungen
app.post('/upload', upload.any(), (req, res) => {
// Akzeptiert jeden Dateityp, jede Größe, jede Anzahl von Dateien!
res.json({ files: req.files });
});
// UNNÖTIG: WebSocket ohne Authentifizierung
wss.on('connection', (ws) => {
// Keine Authentifizierungsprüfung!
ws.on('message', (msg) => {
broadcast(msg); // Jeder kann Nachrichten senden
});
});
Sichere Lösung
// SICHER: Minimale Angriffsfläche mit nur notwendigen Endpunkten
@RestController
@RequestMapping("/api/v2") // Eine einzelne, aktuelle API-Version
public class SecureAPIController {
/**
* Neuen Benutzer erstellen.
* Authentifizierung erforderlich, Eingabe validiert.
*/
@PostMapping("/users")
@PreAuthorize("hasRole('ADMIN')")
@RateLimited(requests = 10, period = "1m")
public ResponseEntity<UserResponse> createUser(
@Valid @RequestBody UserRequest request,
@AuthenticationPrincipal User currentUser) {
// Operation für Audit protokollieren
auditLog.logUserCreation(currentUser, request);
User user = userService.create(request);
return ResponseEntity.status(HttpStatus.CREATED)
.body(UserResponse.from(user));
}
/**
* Benutzer nach ID abrufen.
* Gibt nur eigene Daten oder Admin-Daten zurück.
*/
@GetMapping("/users/{id}")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<UserResponse> getUser(
@PathVariable @Positive Long id,
@AuthenticationPrincipal User currentUser) {
// Zugriffskontrolle: Benutzer können nur eigene Daten abrufen
if (!currentUser.isAdmin() && !currentUser.getId().equals(id)) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
return userService.findById(id)
.map(user -> ResponseEntity.ok(UserResponse.from(user)))
.orElse(ResponseEntity.notFound().build());
}
// KEINE Debug-Endpunkte
// KEINE Legacy-Endpunkte
// KEINE Rohabfrage-Endpunkte
// KEINE übermäßig breiten Admin-Befehle
/**
* Health-Check – nur minimale Informationen.
* Keine Authentifizierung erforderlich, gibt aber nur Status zurück.
*/
@GetMapping("/health")
public ResponseEntity<HealthStatus> healthCheck() {
// Nur minimalen Status zurückgeben, keine Details
boolean healthy = healthChecker.isHealthy();
return ResponseEntity.ok(new HealthStatus(healthy));
}
}
/**
* Admin-Endpunkte in separatem, geschütztem Controller.
*/
@RestController
@RequestMapping("/admin")
@PreAuthorize("hasRole('ADMIN')")
@RateLimited(requests = 5, period = "1m")
public class AdminController {
private static final Set<String> ALLOWED_ADMIN_ACTIONS = Set.of(
"refresh_cache",
"clear_temp_files",
"rotate_logs"
);
/**
* Begrenzten Satz von Admin-Aktionen ausführen.
*/
@PostMapping("/action")
public ResponseEntity<?> executeAction(
@RequestParam String action,
@AuthenticationPrincipal User admin) {
// Nur bestimmte, vordefinierte Aktionen erlauben
if (!ALLOWED_ADMIN_ACTIONS.contains(action)) {
auditLog.logUnauthorizedAction(admin, action);
return ResponseEntity.badRequest()
.body("Unbekannte Aktion: " + action);
}
auditLog.logAdminAction(admin, action);
adminService.execute(action);
return ResponseEntity.ok().build();
}
}
# SICHER: Python mit minimaler Angriffsfläche
from flask import Flask, request, jsonify
from functools import wraps
import os
app = Flask(__name__)
# Nur Produktionskonfiguration
app.config.from_object('config.ProductionConfig')
# Authentifizierungs-Dekorator
def require_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
token = request.headers.get('Authorization')
if not validate_token(token):
return jsonify({'error': 'Unauthorized'}), 401
return f(*args, **kwargs)
return decorated
# Rate-Limiting-Dekorator
def rate_limit(max_requests, window_seconds):
# Implementierung von Rate Limiting
pass
# Nur notwendige Produktions-Endpunkte
@app.route('/api/v1/data', methods=['POST'])
@require_auth
@rate_limit(100, 60)
def handle_data():
"""Daten mit Validierung und Rate Limiting verarbeiten."""
data = request.json
# Eingabeschema validieren
validation_error = validate_data_schema(data)
if validation_error:
return jsonify({'error': validation_error}), 400
result = process_data(data)
return jsonify(result)
@app.route('/api/v1/health')
def health_check():
"""Minimaler Health-Check – keine sensiblen Informationen."""
is_healthy = check_service_health()
return jsonify({'status': 'healthy' if is_healthy else 'unhealthy'})
# KEINE Dev/Debug-Endpunkte
# KEINE Shell/Eval-Endpunkte
# KEINE rohe Dateibereitstellung
# KEINE Introspektions-Endpunkte
# KEINE rohen Datenbankabfrage-Endpunkte
# Strikte CORS-Konfiguration
@app.after_request
def add_cors_headers(response):
allowed_origins = os.environ.get('ALLOWED_ORIGINS', '').split(',')
origin = request.headers.get('Origin')
if origin in allowed_origins:
response.headers['Access-Control-Allow-Origin'] = origin
response.headers['Access-Control-Allow-Methods'] = 'GET, POST'
response.headers['Access-Control-Allow-Headers'] = 'Authorization, Content-Type'
return response
# Eine einzelne, gut gewartete Authentifizierungsmethode
@app.route('/api/v1/auth/login', methods=['POST'])
@rate_limit(5, 60) # Striktes Rate Limiting für Authentifizierung
def login():
"""Einzelner Authentifizierungs-Endpunkt mit Standard-OAuth2."""
credentials = request.json
if not validate_credentials(credentials):
# Nicht verraten, welches Feld falsch war
return jsonify({'error': 'Invalid credentials'}), 401
token = generate_token(credentials['username'])
return jsonify({'token': token})
# Fehlerbehandlung – keine Informationen preisgeben
@app.errorhandler(Exception)
def handle_error(error):
app.logger.error(f'Unbehandelter Fehler: {error}')
# Generische Fehlermeldung – keine Details
return jsonify({'error': 'Internal server error'}), 500
if __name__ == '__main__':
# Produktions-Serverkonfiguration
if os.environ.get('FLASK_ENV') == 'production':
# KEIN Debug-Modus in Produktion
app.run(debug=False, host='127.0.0.1') # Nur an localhost binden
CVE-Beispiele
Dieses CWE ist für die direkte CVE-Zuordnung als VERBOTEN markiert, da es ein Qualitätsproblem darstellt. Jedoch ist eine übermäßige Angriffsfläche ein beitragender Faktor bei vielen Schwachstellen:
- Debug-Endpunkte: Viele CVEs resultieren aus Debug-Funktionalität, die in der Produktion aktiviert bleibt
- Legacy-APIs: Ungepatchte alte API-Versionen sind häufige Quellen für Schwachstellen
- Übermäßig permissive CORS: Führt zu Cross-Site Request Forgery-Möglichkeiten
Verwandte CWEs
- CWE-1120: Excessive Code Complexity (übergeordnet)
- CWE-1226: Complexity Issues (Kategoriemitglied)
- CWE-489: Active Debug Code (verwandt – spezifischer Fall übermäßiger Angriffsfläche)
- CWE-749: Exposed Dangerous Method or Function (verwandt)
Referenzen
- MITRE Corporation. "CWE-1125: Excessive Attack Surface." https://cwe.mitre.org/data/definitions/1125.html
- OWASP Attack Surface Analysis Cheat Sheet
- Microsoft – Reducing Attack Surface
- OWASP Top Ten 2025 – A06:2025 Insecure Design