Übermäßige Verwendung von hartkodierten Literalen bei der Initialisierung
Beschreibung
Übermäßige Verwendung von hartkodierten Literalen bei der Initialisierung tritt auf, wenn Software Datenelemente mit hartkodierten Literalwerten initialisiert, die keine einfachen Ganzzahlen oder statischen Konstantenelemente sind. Dies umfasst das Einbetten komplexer Zeichenketten, Konfigurationswerte, Formatzeichenketten, regulärer Ausdrücke, SQL-Abfragen oder anderer nicht-trivialer Literale direkt im Code. Solche Hartkodierung macht den Code schwer zu warten, zu verstehen und zu ändern, da Änderungen das Auffinden und Aktualisieren mehrerer Vorkommen in der gesamten Codebasis erfordern.
Risiko
Obwohl primär ein Wartbarkeitsproblem, haben übermäßig hartkodierte Literale indirekte Sicherheitsimplikationen. Verstreute Literale erschweren Sicherheitsaudits, da Prüfer gesamte Codebasen nach sicherheitsrelevanten Werten durchsuchen müssen. Inkonsistente Aktualisierungen bei sich ändernden Sicherheitsanforderungen (wie Verstärkung von Passwortmustern) können einige Instanzen verwundbar lassen. Hartkodierte SQL-Fragmente erhöhen das SQL-Injection-Risiko durch inkonsistente Parametrisierung. Fehlermeldungen mit hartkodiertem Text können sensible Informationen preisgeben. Magic Strings für Authentifizierung oder Autorisierung können bei Sicherheitsüberprüfungen leicht übersehen werden.
Lösung
Definieren Sie Literale als benannte Konstanten auf Klassen- oder Modulebene. Verwenden Sie Konfigurationsdateien oder Ressourcenpakete für benutzersichtbare Zeichenketten. Erstellen Sie dedizierte Klassen oder Enums für zusammengehörige Konstantengruppen. Verwenden Sie Kompilierzeit-Konstanten, wo möglich. Extrahieren Sie Regex-Muster, SQL-Vorlagen und Formatzeichenketten in gut dokumentierte Konstanten. Erwägen Sie Builder-Muster für komplexe Zeichenkettenkonstr. Implementieren Sie zentralisierte Nachrichtenkataloge für Fehler- und Protokollmeldungen. Wenden Sie statische Analyseregeln an, um übermäßige Literalverwendung zu erkennen.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Sonstiges | Bereich: Sonstiges Reduzierte Wartbarkeit - Verstreute hartkodierte Literale machen Code-Änderungen schwierig und fehleranfällig. |
| Sonstiges | Bereich: Sonstiges Qualitätsverschlechterung - Inkonsistente Literalwerte in der Codebasis können zu Fehlern und Sicherheitslücken führen. |
Beispielcode und Lösung
Verwundbarer Code
// Verwundbar: Übermäßig hartkodierte Literale im gesamten Code
public class VerwundbarerBenutzerService {
public void validiereBenutzername(String benutzername, String passwort) {
// Verwundbar: Hartkodiertes Regex-Muster (schwer zu warten/auditieren)
if (!benutzername.matches("^[a-zA-Z0-9_]{3,20}$")) {
throw new ValidationException("Benutzername muss 3-20 alphanumerische Zeichen sein");
}
// Verwundbar: Hartkodierte Passwortregeln im Code verstreut
if (passwort.length() < 8) {
throw new ValidationException("Passwort muss mindestens 8 Zeichen haben");
}
if (!passwort.matches(".*[A-Z].*")) {
throw new ValidationException("Passwort muss Großbuchstaben enthalten");
}
if (!passwort.matches(".*[0-9].*")) {
throw new ValidationException("Passwort muss eine Zahl enthalten");
}
}
public User findeBenutzer(Connection conn, String benutzername) throws SQLException {
// Verwundbar: Hartkodierte SQL-Abfrage
PreparedStatement stmt = conn.prepareStatement(
"SELECT id, username, email, created_at FROM users WHERE username = ? AND status = 'ACTIVE'"
);
stmt.setString(1, benutzername);
// ...
}
}
# Verwundbar: Hartkodierte Literale überall
class VerwundbarerZahlungsProzessor:
def verarbeite_zahlung(self, betrag, kartennummer):
# Verwundbar: Hartkodierte Validierungsmuster
if not re.match(r'^\d{16}$', kartennummer):
raise ValueError("Ungültiges Kartennummernformat")
# Verwundbar: Hartkodierte Betragsgrenzen
if betrag < 0.01:
raise ValueError("Betrag muss mindestens 0,01 EUR sein")
if betrag > 10000.00:
raise ValueError("Betrag darf 10.000,00 EUR nicht überschreiten")
# Verwundbar: Hartkodierter API-Endpunkt (sollte Konfig sein)
response = requests.post(
"https://api.zahlungsanbieter.com/v2/charge",
json={
"amount": betrag,
"card": kartennummer,
"merchant_id": "MER123456", # Hartkodierte Anmeldedaten!
"currency": "EUR"
},
headers={
"Authorization": "Bearer sk_live_xxxxx", # Hartkodiertes Geheimnis!
"Content-Type": "application/json"
}
)
Sichere Lösung
// Sicher: Zentralisierte Konstanten und Konfiguration
public class SichererBenutzerService {
// Sicher: Zentralisierte Validierungsmuster
private static final class ValidationMuster {
static final Pattern BENUTZERNAME = Pattern.compile("^[a-zA-Z0-9_]{3,20}$");
static final Pattern HAT_GROSSBUCHSTABEN = Pattern.compile(".*[A-Z].*");
static final Pattern HAT_ZIFFER = Pattern.compile(".*[0-9].*");
}
// Sicher: Zentralisierte Einschränkungen
private static final class PasswortRichtlinie {
static final int MIN_LAENGE = 8;
static final int MAX_LAENGE = 128;
static final boolean GROSSBUCHSTABE_ERFORDERLICH = true;
static final boolean ZIFFER_ERFORDERLICH = true;
}
// Sicher: Nachrichtenkonstanten (könnten auch in Ressourcenpaket sein)
private static final class Nachrichten {
static final String UngültigER_BENUTZERNAME =
"Benutzername muss 3-20 alphanumerische Zeichen sein";
static final String PASSWORT_ZU_KURZ =
"Passwort muss mindestens " + PasswortRichtlinie.MIN_LAENGE + " Zeichen haben";
static final String PASSWORT_BRAUCHT_GROSSBUCHSTABEN =
"Passwort muss Großbuchstaben enthalten";
static final String PASSWORT_BRAUCHT_ZIFFER =
"Passwort muss eine Zahl enthalten";
}
// Sicher: SQL-Abfragen als Konstanten
private static final class Abfragen {
static final String FINDE_AKTIVEN_BENUTZER =
"SELECT id, username, email, created_at FROM users " +
"WHERE username = ? AND status = ?";
}
private static final String BENUTZER_STATUS_AKTIV = "ACTIVE";
public void validiereBenutzername(String benutzername, String passwort) {
if (!ValidationMuster.BENUTZERNAME.matcher(benutzername).matches()) {
throw new ValidationException(Nachrichten.UngültigER_BENUTZERNAME);
}
if (passwort.length() < PasswortRichtlinie.MIN_LAENGE) {
throw new ValidationException(Nachrichten.PASSWORT_ZU_KURZ);
}
if (PasswortRichtlinie.GROSSBUCHSTABE_ERFORDERLICH &&
!ValidationMuster.HAT_GROSSBUCHSTABEN.matcher(passwort).matches()) {
throw new ValidationException(Nachrichten.PASSWORT_BRAUCHT_GROSSBUCHSTABEN);
}
if (PasswortRichtlinie.ZIFFER_ERFORDERLICH &&
!ValidationMuster.HAT_ZIFFER.matcher(passwort).matches()) {
throw new ValidationException(Nachrichten.PASSWORT_BRAUCHT_ZIFFER);
}
}
}
# Sicher: Zentralisierte Konfiguration und Konstanten
from dataclasses import dataclass, field
from enum import Enum
import re
import os
class ZahlungsKonfig:
"""Zentralisierte Zahlungskonfiguration"""
MIN_BETRAG = 0.01
MAX_BETRAG = 10000.00
STANDARD_WÄHRUNG = "EUR"
# Aus sicherer Konfiguration geladen
API_ENDPOINT = os.environ['PAYMENT_API_ENDPOINT']
HÄNDLER_ID = os.environ['PAYMENT_MERCHANT_ID']
API_KEY = os.environ['PAYMENT_API_KEY']
class ValidationMuster:
"""Zentralisierte Validierungsmuster"""
KARTENNUMMER = re.compile(r'^\d{16}$')
CVV = re.compile(r'^\d{3,4}$')
ABLAUFDATUM = re.compile(r'^(0[1-9]|1[0-2])\/\d{2}$')
class ZahlungsNachrichten:
"""Benutzerseitige Zahlungsnachrichten"""
ERFOLG = "Zahlung erfolgreich"
ABGELEHNT = "Zahlung abgelehnt"
RATE_BEGRENZT = "Zu viele Anfragen, bitte später erneut versuchen"
ALLGEMEINER_FEHLER = "Zahlung fehlgeschlagen"
UngültigE_KARTE = "Ungültiges Kartennummernformat"
BETRAG_ZU_NIEDRIG = f"Betrag muss mindestens {ZahlungsKonfig.MIN_BETRAG:.2f} EUR sein"
BETRAG_ZU_HOCH = f"Betrag darf {ZahlungsKonfig.MAX_BETRAG:,.2f} EUR nicht überschreiten"
class SichererZahlungsProzessor:
def __init__(self, config: ZahlungsKonfig):
self.config = config
def verarbeite_zahlung(self, betrag: float, kartennummer: str) -> str:
self._validiere_eingabe(betrag, kartennummer)
response = requests.post(
self.config.API_ENDPOINT,
json={
"amount": betrag,
"card": kartennummer,
"merchant_id": self.config.HÄNDLER_ID,
"currency": self.config.STANDARD_WÄHRUNG
},
headers={
"Authorization": f"Bearer {self.config.API_KEY}",
"Content-Type": "application/json"
}
)
return self._verarbeite_antwort(response)
def _validiere_eingabe(self, betrag: float, kartennummer: str):
if not ValidationMuster.KARTENNUMMER.match(kartennummer):
raise ValueError(ZahlungsNachrichten.UngültigE_KARTE)
if betrag < ZahlungsKonfig.MIN_BETRAG:
raise ValueError(ZahlungsNachrichten.BETRAG_ZU_NIEDRIG)
if betrag > ZahlungsKonfig.MAX_BETRAG:
raise ValueError(ZahlungsNachrichten.BETRAG_ZU_HOCH)
CVE-Beispiele
Diese CWE beschreibt ein Code-Qualitätsproblem. Obwohl nicht direkt auf CVEs abgebildet, haben verstreute hartkodierte Literale zu Sicherheitsproblemen beigetragen, wenn Aktualisierungen inkonsistent angewendet wurden.
Referenzen
-
MITRE Corporation. "CWE-1052: Excessive Use of Hard-Coded Literals in Initialization." https://cwe.mitre.org/data/definitions/1052.html
-
Martin, Robert C. "Clean Code: A Handbook of Agile Software Craftsmanship."
-
Fowler, Martin. "Refactoring: Improving the Design of Existing Code."