Unzureichende Isolation von Definitionen symbolischer Konstanten

Beschreibung

Unzureichende Isolation von Definitionen symbolischer Konstanten tritt auf, wenn Quellcode symbolische Konstanten verwendet, ohne deren Definitionen an einem zentralisierten oder isolierten Ort zu platzieren. Wenn Konstanten in der gesamten Codebasis verstreut sind, anstatt in dedizierten Konfigurationsdateien, Headern oder Klassen organisiert zu sein, wird es schwierig, sie konsistent zu verwalten, ihre Beziehungen zu verstehen und sie sicher zu aktualisieren.

Risiko

Verstreute Konstantendefinitionen haben indirekte Sicherheitsimplikationen. Verwandte Sicherheitskonstanten können inkonsistente Werte haben, wenn sie an mehreren Stellen definiert sind. Das Finden aller sicherheitsrelevanten Konstanten für Audits ist schwierig. Änderungen an Sicherheitsparametern können manche Definitionen übersehen. Konstanten mit ähnlichen Zwecken können im Laufe der Zeit divergieren. Code-Review kann Sicherheitskonstantenwerte nicht leicht verifizieren. Konfigurationsmanagement wird durch verstreute Definitionen erschwert. Versehentliches Shadowing von Konstanten kann unerwartetes Verhalten verursachen.

Lösung

Zentralisieren Sie Konstantendefinitionen in dedizierten Dateien oder Klassen. Gruppieren Sie verwandte Konstanten logisch zusammen. Verwenden Sie eine konsistente Namenskonvention für Konstanten. Erstellen Sie hierarchische Organisation für große Projekte (Sicherheitskonstanten, Netzwerkkonstanten usw.). Verwenden Sie Single-Source-of-Truth für Konstanten, die konsistent sein müssen. Wenden Sie Zugriffskontrollen an, um versehentliche Modifikation zu verhindern. Dokumentieren Sie den Zweck und gültigen Bereich jeder Konstante. Verwenden Sie Build-Zeit-Validierung, um Konstantenkonsistenz sicherzustellen.

Häufige Auswirkungen

AuswirkungDetails
AndereBereich: Ändere

Reduzierte Wartbarkeit - Verstreute Konstanten sind schwerer zu verwalten und zu aktualisieren.
IntegritätBereich: Integrität

Inkonsistenter Zustand - Gleiche Konstante an verschiedenen Stellen unterschiedlich definiert.
AndereBereich: Ändere

Erhöhte analytische Komplexität - Schwierig, alle Konstantenwerte zu auditieren.

Beispielcode

Anfälliger Code

// Anfällig: Konstanten über mehrere Dateien verstreut

// Datei: UserValidator.java
public class UserValidator {
    // Konstanten hier definiert
    private static final int MIN_PASSWORD_LENGTH = 8;
    private static final int MAX_PASSWORD_LENGTH = 128;

    public void validatePassword(String password) {
        if (password.length() < MIN_PASSWORD_LENGTH) {
            throw new ValidationException("Passwort zu kurz");
        }
    }
}

// Datei: RegistrationService.java
public class RegistrationService {
    // Gleiche Konstante erneut definiert - kann aus dem Sync geraten!
    private static final int MIN_PASSWORD_LENGTH = 8;
    private static final int MAX_PASSWORD_LEN = 100;  // Anderer Wert!

    public void register(String username, String password) {
        // Verwendet lokal definierte Konstante
        if (password.length() < MIN_PASSWORD_LENGTH) {
            throw new RegistrationException("Passwort zu kurz");
        }
    }
}

// Datei: PasswordResetService.java
public class PasswordResetService {
    // Noch eine weitere Definition
    private static final int MINIMUM_PASSWORD_LENGTH = 6;  // Wieder anders!

    public void resetPassword(String newPassword) {
        // Inkonsistente Validierung
        if (newPassword.length() < MINIMUM_PASSWORD_LENGTH) {
            throw new ValidationException("Passwort zu kurz");
        }
    }
}

// Datei: SecurityConfig.java
public class SecurityConfig {
    // Einige Sicherheitskonstanten hier
    public static final int MAX_LOGIN_ATTEMPTS = 5;
}

// Datei: AuthenticationService.java
public class AuthenticationService {
    // Doppelte Konstante
    private static final int MAX_ATTEMPTS = 3;  // Anders als SecurityConfig!

    public void authenticate(String username, String password) {
        if (failedAttempts > MAX_ATTEMPTS) {
            lockAccount();
        }
    }
}

// Datei: ApiController.java
public class ApiController {
    // API-bezogene Konstanten hier verstreut
    private static final int API_RATE_LIMIT = 100;
    private static final int API_TIMEOUT_SECONDS = 30;
}

// Datei: ExternalApiClient.java
public class ExternalApiClient {
    // Gleiche Konstanten unterschiedlich definiert
    private static final int RATE_LIMIT = 50;  // Anders!
    private static final int TIMEOUT = 60;     // Anders!
}
# Anfällig: Python mit verstreuten Konstanten

# Datei: validators/user_validator.py
MIN_PASSWORD_LENGTH = 8
MAX_PASSWORD_LENGTH = 128

def validate_password(password):
    if len(password) < MIN_PASSWORD_LENGTH:
        raise ValueError("Passwort zu kurz")


# Datei: services/registration_service.py
# Gleiche Konstanten erneut definiert
MIN_PASSWORD_LEN = 8
MAX_PASSWORD_LEN = 100  # Anders!

def register_user(username, password):
    if len(password) < MIN_PASSWORD_LEN:
        raise ValueError("Passwort zu kurz")


# Datei: services/auth_service.py
# Mehr verstreute Konstanten
MAX_LOGIN_ATTEMPTS = 5
LOCKOUT_DURATION_MINUTES = 30


# Datei: api/rate_limiter.py
# API-Konstanten hier verstreut
RATE_LIMIT_REQUESTS = 100
RATE_LIMIT_WINDOW_SECONDS = 60


# Datei: api/external_client.py
# Duplikat mit anderen Werten
RATE_LIMIT = 50  # Anders!
TIMEOUT_SECONDS = 30


# Datei: models/user.py
# Modell-spezifische Konstanten
USERNAME_MIN_LENGTH = 3
USERNAME_MAX_LENGTH = 50


# Datei: handlers/user_handler.py
# Gleiche Konstanten dupliziert
MIN_USERNAME_LEN = 3
MAX_USERNAME_LEN = 30  # Anders!
// Anfällig: C# mit verstreuten Konstanten

// Datei: Validators/PasswordValidator.cs
public class PasswordValidator
{
    private const int MinLength = 8;
    private const int MaxLength = 128;

    public bool Validate(string password) =>
        password.Length >= MinLength && password.Length <= MaxLength;
}

// Datei: Services/UserService.cs
public class UserService
{
    // Doppelte Konstante mit anderem Wert
    private const int MinPasswordLength = 6;  // Anders!
    private const int MaxPasswordLength = 100; // Anders!

    public void CreateUser(string password)
    {
        if (password.Length < MinPasswordLength)
            throw new ArgumentException("Passwort zu kurz");
    }
}

// Datei: Controllers/AuthController.cs
public class AuthController : Controller
{
    private const int MaxLoginAttempts = 5;
    private const int LockoutMinutes = 15;

    // ...
}

// Datei: Services/AuthService.cs
public class AuthService
{
    // Gleiche Konstante, anderer Wert
    private const int MaxAttempts = 3;  // Anders!

    // ...
}

Korrigierter Code

// Korrigiert: Zentralisierte Konstantendefinitionen

// Datei: constants/SecurityConstants.java
// Single Source of Truth für sicherheitsrelevante Konstanten
public final class SecurityConstants {

    // Passwortanforderungen
    public static final int MIN_PASSWORD_LENGTH = 8;
    public static final int MAX_PASSWORD_LENGTH = 128;
    public static final int PASSWORD_HISTORY_SIZE = 10;

    // Authentifizierung
    public static final int MAX_LOGIN_ATTEMPTS = 5;
    public static final int LOCKOUT_DURATION_MINUTES = 30;
    public static final int SESSION_TIMEOUT_MINUTES = 60;

    // Kontosicherheit
    public static final int MAX_CONCURRENT_SESSIONS = 3;
    public static final int PASSWORD_EXPIRY_DAYS = 90;

    // Instanziierung verhindern
    private SecurityConstants() {
        throw new UnsupportedOperationException("Konstantenklasse");
    }
}

// Datei: constants/ValidationConstants.java
// Validierungsbezogene Konstanten
public final class ValidationConstants {

    // Benutzername
    public static final int MIN_USERNAME_LENGTH = 3;
    public static final int MAX_USERNAME_LENGTH = 50;

    // Email
    public static final int MAX_EMAIL_LENGTH = 254;  // RFC 5321

    // Allgemeiner Text
    public static final int MAX_TEXT_FIELD_LENGTH = 1000;

    private ValidationConstants() {}
}

// Datei: constants/ApiConstants.java
// API-bezogene Konstanten
public final class ApiConstants {

    // Rate-Limiting
    public static final int RATE_LIMIT_REQUESTS = 100;
    public static final int RATE_LIMIT_WINDOW_SECONDS = 60;

    // Timeouts
    public static final int CONNECT_TIMEOUT_MILLIS = 5000;
    public static final int READ_TIMEOUT_MILLIS = 30000;

    // Paginierung
    public static final int DEFAULT_PAGE_SIZE = 20;
    public static final int MAX_PAGE_SIZE = 100;

    private ApiConstants() {}
}

// Datei: validators/UserValidator.java
// Verwendet zentralisierte Konstanten
public class UserValidator {

    public void validatePassword(String password) {
        if (password.length() < SecurityConstants.MIN_PASSWORD_LENGTH) {
            throw new ValidationException(String.format(
                "Passwort muss mindestens %d Zeichen haben",
                SecurityConstants.MIN_PASSWORD_LENGTH));
        }
        if (password.length() > SecurityConstants.MAX_PASSWORD_LENGTH) {
            throw new ValidationException(String.format(
                "Passwort darf %d Zeichen nicht überschreiten",
                SecurityConstants.MAX_PASSWORD_LENGTH));
        }
    }

    public void validateUsername(String username) {
        if (username.length() < ValidationConstants.MIN_USERNAME_LENGTH ||
            username.length() > ValidationConstants.MAX_USERNAME_LENGTH) {
            throw new ValidationException(String.format(
                "Benutzername muss zwischen %d und %d Zeichen sein",
                ValidationConstants.MIN_USERNAME_LENGTH,
                ValidationConstants.MAX_USERNAME_LENGTH));
        }
    }
}

// Alle anderen Services verwenden die gleichen zentralisierten Konstanten
public class AuthenticationService {

    public void authenticate(String username, String password) {
        // Verwendet zentralisierte Konstante
        if (failedAttempts > SecurityConstants.MAX_LOGIN_ATTEMPTS) {
            lockAccount(SecurityConstants.LOCKOUT_DURATION_MINUTES);
        }
    }
}
# Korrigiert: Python mit zentralisierten Konstanten

# Datei: constants/__init__.py
# Exportiert alle Konstanten für einfachen Import
from .security import *
from .validation import *
from .api import *


# Datei: constants/security.py
"""Sicherheitsrelevante Konstanten. Single Source of Truth."""
from typing import Final


class SecurityConstants:
    """Authentifizierungs- und Autorisierungskonstanten."""

    # Passwortanforderungen
    MIN_PASSWORD_LENGTH: Final[int] = 8
    MAX_PASSWORD_LENGTH: Final[int] = 128
    PASSWORD_HISTORY_SIZE: Final[int] = 10

    # Authentifizierung
    MAX_LOGIN_ATTEMPTS: Final[int] = 5
    LOCKOUT_DURATION_MINUTES: Final[int] = 30
    SESSION_TIMEOUT_MINUTES: Final[int] = 60

    # Token-Einstellungen
    ACCESS_TOKEN_EXPIRY_MINUTES: Final[int] = 15
    REFRESH_TOKEN_EXPIRY_DAYS: Final[int] = 7


# Datei: constants/validation.py
"""Validierungskonstanten."""
from typing import Final


class ValidationConstants:
    """Eingabevalidierungslimits."""

    # Benutzername
    MIN_USERNAME_LENGTH: Final[int] = 3
    MAX_USERNAME_LENGTH: Final[int] = 50

    # Email (RFC 5321)
    MAX_EMAIL_LENGTH: Final[int] = 254

    # Allgemeiner Text
    MAX_TEXT_LENGTH: Final[int] = 1000
    MAX_DESCRIPTION_LENGTH: Final[int] = 5000


# Datei: constants/api.py
"""API-bezogene Konstanten."""
from typing import Final


class ApiConstants:
    """API-Konfigurationskonstanten."""

    # Rate-Limiting
    RATE_LIMIT_REQUESTS: Final[int] = 100
    RATE_LIMIT_WINDOW_SECONDS: Final[int] = 60

    # Timeouts
    CONNECT_TIMEOUT_SECONDS: Final[int] = 5
    READ_TIMEOUT_SECONDS: Final[int] = 30

    # Paginierung
    DEFAULT_PAGE_SIZE: Final[int] = 20
    MAX_PAGE_SIZE: Final[int] = 100


# Datei: validators/user_validator.py
# Verwendet zentralisierte Konstanten
from constants import SecurityConstants, ValidationConstants


def validate_password(password: str) -> None:
    """Passwort gegen Sicherheitsanforderungen validieren."""
    if len(password) < SecurityConstants.MIN_PASSWORD_LENGTH:
        raise ValueError(
            f"Passwort muss mindestens {SecurityConstants.MIN_PASSWORD_LENGTH} Zeichen haben"
        )
    if len(password) > SecurityConstants.MAX_PASSWORD_LENGTH:
        raise ValueError(
            f"Passwort darf {SecurityConstants.MAX_PASSWORD_LENGTH} Zeichen nicht überschreiten"
        )


def validate_username(username: str) -> None:
    """Benutzernamenslänge validieren."""
    if not (ValidationConstants.MIN_USERNAME_LENGTH <= len(username) <=
            ValidationConstants.MAX_USERNAME_LENGTH):
        raise ValueError(
            f"Benutzername muss zwischen {ValidationConstants.MIN_USERNAME_LENGTH} "
            f"und {ValidationConstants.MAX_USERNAME_LENGTH} Zeichen sein"
        )


# Datei: services/auth_service.py
# Verwendet gleiche zentralisierte Konstanten
from constants import SecurityConstants


def authenticate(username: str, password: str, failed_attempts: int) -> bool:
    """Benutzer mit Kontosperrschutz authentifizieren."""
    if failed_attempts >= SecurityConstants.MAX_LOGIN_ATTEMPTS:
        lockout_account(SecurityConstants.LOCKOUT_DURATION_MINUTES)
        return False

    return verify_credentials(username, password)
// Korrigiert: C# mit zentralisierten Konstanten

// Datei: Constants/SecurityConstants.cs
namespace MyApp.Constants
{
    /// <summary>
    /// Sicherheitsrelevante Konstanten. Single Source of Truth.
    /// </summary>
    public static class SecurityConstants
    {
        // Passwortanforderungen
        public const int MinPasswordLength = 8;
        public const int MaxPasswordLength = 128;
        public const int PasswordHistorySize = 10;

        // Authentifizierung
        public const int MaxLoginAttempts = 5;
        public const int LockoutDurationMinutes = 30;
        public const int SessionTimeoutMinutes = 60;

        // Tokens
        public const int AccessTokenExpiryMinutes = 15;
        public const int RefreshTokenExpiryDays = 7;
    }
}

// Datei: Constants/ValidationConstants.cs
namespace MyApp.Constants
{
    /// <summary>
    /// Eingabevalidierungskonstanten.
    /// </summary>
    public static class ValidationConstants
    {
        // Benutzername
        public const int MinUsernameLength = 3;
        public const int MaxUsernameLength = 50;

        // Email
        public const int MaxEmailLength = 254;  // RFC 5321

        // Allgemein
        public const int MaxTextLength = 1000;
    }
}

// Datei: Constants/ApiConstants.cs
namespace MyApp.Constants
{
    /// <summary>
    /// API-Konfigurationskonstanten.
    /// </summary>
    public static class ApiConstants
    {
        // Rate-Limiting
        public const int RateLimitRequests = 100;
        public const int RateLimitWindowSeconds = 60;

        // Timeouts
        public const int ConnectTimeoutMillis = 5000;
        public const int ReadTimeoutMillis = 30000;

        // Paginierung
        public const int DefaultPageSize = 20;
        public const int MaxPageSize = 100;
    }
}

// Datei: Validators/PasswordValidator.cs
// Verwendet zentralisierte Konstanten
using MyApp.Constants;

public class PasswordValidator : IValidator<string>
{
    public ValidationResult Validate(string password)
    {
        if (password.Length < SecurityConstants.MinPasswordLength)
        {
            return ValidationResult.Error(
                $"Passwort muss mindestens {SecurityConstants.MinPasswordLength} Zeichen haben");
        }

        if (password.Length > SecurityConstants.MaxPasswordLength)
        {
            return ValidationResult.Error(
                $"Passwort darf {SecurityConstants.MaxPasswordLength} Zeichen nicht überschreiten");
        }

        return ValidationResult.Success();
    }
}

// Datei: Services/AuthService.cs
// Verwendet gleiche zentralisierte Konstanten
using MyApp.Constants;

public class AuthService : IAuthService
{
    public async Task<AuthResult> AuthenticateAsync(
        string username, string password, int failedAttempts)
    {
        // Verwendet zentralisierte Konstante
        if (failedAttempts >= SecurityConstants.MaxLoginAttempts)
        {
            await LockAccountAsync(
                username,
                TimeSpan.FromMinutes(SecurityConstants.LockoutDurationMinutes));

            return AuthResult.AccountLocked();
        }

        return await VerifyCredentialsAsync(username, password);
    }
}

CVE-Beispiele

Diese CWE ist für direkte CVE-Zuordnung als VERBOTEN markiert, da sie ein Codequalitätsproblem und keine direkte Sicherheitsschwachstelle darstellt.


Verwandte CWEs

  • CWE-1078: Inappropriate Source Code Style or Formatting (Eltern)
  • CWE-1006: Bad Coding Practices (Kategoriemitglied)
  • CWE-1106: Insufficient Use of Symbolic Constants (verwandt)

Referenzen

  1. MITRE Corporation. "CWE-1107: Insufficient Isolation of Symbolic Constant Definitions." https://cwe.mitre.org/data/definitions/1107.html
  2. Martin, Robert C. "Clean Code" - Constants and Configuration.