Verwendung von redundantem Code
Beschreibung
Verwendung von redundantem Code tritt auf, wenn Software mehrere Funktionen, Methoden, Prozeduren, Makros oder Codeblöcke enthält, die identische oder nahezu identische Logik implementieren. Diese Codeduplizierung schafft Wartungsherausforderungen, da Änderungen oder Fixes an mehreren Stellen angewendet werden müssen, was das Risiko erhöht, dass einige Instanzen übersehen werden. Obwohl es sich hauptsächlich um ein Code-Qualitätsproblem handelt, kann redundanter Code indirekte Sicherheitsimplikationen haben, wenn Sicherheitspatches oder Fixes inkonsistent über duplizierte Codesegmente angewendet werden.
Risiko
Das Hauptrisiko ist eine reduzierte Wartbarkeit, die zu Sicherheitsschwachstellen führen kann. Wenn ein Sicherheitsfehler in dupliziertem Code entdeckt wird, können Entwickler eine Instanz beheben, während andere übersehen werden. Dieses inkonsistente Patching lässt einige Angriffsvektoren offen. Zusätzlich erhöht redundanter Code die Angriffsfläche, indem er mehrere potenzielle Exploitationspunkte bereitstellt. Codeduplizierung macht auch Sicherheitsaudits schwieriger und zeitaufwändiger, was die Wahrscheinlichkeit erhöht, dass Schwachstellen übersehen werden.
Lösung
Extrahieren Sie gemeinsame Funktionalität in einzelne, wiederverwendbare Funktionen oder Methoden. Wenden Sie das DRY-Prinzip (Don't Repeat Yourself) während der Entwicklung an. Verwenden Sie statische Analysetools zur Erkennung von Codeduplizierung. Refaktorisieren Sie existierenden duplizierten Code in gemeinsame Utilities. Implementieren Sie Code-Review-Prozesse, die Duplizierung kennzeichnen. Erstellen Sie gemeinsame Bibliotheken für häufig benötigte Funktionalität. Stellen Sie sicher, dass jeder sicherheitskritische Code an genau einer Stelle existiert, um Wartung und Auditing zu vereinfachen.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Andere | Bereich: Ändere Reduzierte Wartbarkeit - Duplizierter Code macht das Produkt schwerer zu warten, was das Risiko inkonsistenter Sicherheitspatches erhöht. |
| Integrität | Bereich: Integrität Qualitätsverschlechterung - Inkonsistente Updates an duplizierten Codesegmenten können zu Zuverlässigkeitsproblemen und potenziellen Sicherheitslücken führen. |
Beispielcode
Anfälliger Code
// ANFÄLLIG: Duplizierte Validierungslogik über mehrere Methoden
public class VulnerableUserService {
public boolean createUser(String username, String password, String email) {
// Duplizierte Validierungslogik - Instanz 1
if (username == null || username.length() < 3 || username.length() > 50) {
return false;
}
if (!username.matches("^[a-zA-Z0-9_]+$")) {
return false;
}
if (password == null || password.length() < 8) {
return false;
}
if (email == null || !email.contains("@")) {
return false;
}
// Benutzer erstellen...
return true;
}
public boolean updateUser(String username, String password, String email) {
// Duplizierte Validierungslogik - Instanz 2
// Wenn Sicherheitsfix benötigt, könnte hier vergessen werden
if (username == null || username.length() < 3 || username.length() > 50) {
return false;
}
if (!username.matches("^[a-zA-Z0-9_]+$")) {
return false;
}
if (password == null || password.length() < 8) {
return false;
}
if (email == null || !email.contains("@")) {
return false;
}
// Benutzer aktualisieren...
return true;
}
}
# ANFÄLLIG: Duplizierte Datenbankabfrage-Konstruktion
class VulnerableDataAccess:
def get_user_by_id(self, user_id, connection):
# Dupliziertes Abfragemuster - Instanz 1
cursor = connection.cursor()
query = "SELECT * FROM users WHERE id = '" + str(user_id) + "'"
cursor.execute(query)
return cursor.fetchone()
def get_user_by_email(self, email, connection):
# Dupliziertes Abfragemuster - Instanz 2
# Gleiche SQL-Injection-Schwachstelle
cursor = connection.cursor()
query = "SELECT * FROM users WHERE email = '" + email + "'"
cursor.execute(query)
return cursor.fetchone()
def get_user_by_username(self, username, connection):
# Dupliziertes Abfragemuster - Instanz 3
# Wenn Parametrisierung zu einem hinzugefügt, bleiben andere anfällig
cursor = connection.cursor()
query = "SELECT * FROM users WHERE username = '" + username + "'"
cursor.execute(query)
return cursor.fetchone()
Korrigierter Code
// KORRIGIERT: Zentralisierte Validierungslogik
public class FixedUserService {
private final UserValidator validator = new UserValidator();
public boolean createUser(String username, String password, String email) {
// Verwendet einzelne Validierungsmethode
if (!validator.validateUserInput(username, password, email)) {
return false;
}
// Benutzer erstellen...
return true;
}
public boolean updateUser(String username, String password, String email) {
// Gleiche Validierungsmethode überall verwendet
if (!validator.validateUserInput(username, password, email)) {
return false;
}
// Benutzer aktualisieren...
return true;
}
}
// Single Source of Truth für Validierung
class UserValidator {
private static final int MIN_USERNAME_LENGTH = 3;
private static final int MAX_USERNAME_LENGTH = 50;
private static final int MIN_PASSWORD_LENGTH = 8;
private static final Pattern USERNAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_]+$");
private static final Pattern EMAIL_PATTERN = Pattern.compile("^[^@]+@[^@]+\\.[^@]+$");
public boolean validateUserInput(String username, String password, String email) {
return validateUsername(username)
&& validatePassword(password)
&& validateEmail(email);
}
public boolean validateUsername(String username) {
if (username == null) return false;
if (username.length() < MIN_USERNAME_LENGTH) return false;
if (username.length() > MAX_USERNAME_LENGTH) return false;
return USERNAME_PATTERN.matcher(username).matches();
}
public boolean validatePassword(String password) {
if (password == null) return false;
if (password.length() < MIN_PASSWORD_LENGTH) return false;
return true;
}
public boolean validateEmail(String email) {
if (email == null) return false;
return EMAIL_PATTERN.matcher(email).matches();
}
}
# KORRIGIERT: Zentralisierte, parametrisierte Abfrageausführung
class FixedDataAccess:
def _execute_query(self, connection, query, params):
"""Einzelne Methode für alle Datenbankabfragen mit korrekter Parametrisierung"""
cursor = connection.cursor()
cursor.execute(query, params) # Parametrisierte Abfrage
return cursor
def get_user_by_id(self, user_id, connection):
# Verwendet zentralisierte Abfragemethode
query = "SELECT * FROM users WHERE id = %s"
cursor = self._execute_query(connection, query, (user_id,))
return cursor.fetchone()
def get_user_by_email(self, email, connection):
# Gleiches sicheres Muster
query = "SELECT * FROM users WHERE email = %s"
cursor = self._execute_query(connection, query, (email,))
return cursor.fetchone()
def get_user_by_username(self, username, connection):
# Konsistente Sicherheit über alle Methoden
query = "SELECT * FROM users WHERE username = %s"
cursor = self._execute_query(connection, query, (username,))
return cursor.fetchone()
CVE-Beispiele
Diese CWE ist hauptsächlich ein Code-Qualitätsproblem und ist für direkte CVE-Zuordnung als VERBOTEN markiert. Inkonsistente Sicherheitspatches in dupliziertem Code haben jedoch zu verschiedenen Schwachstellen beigetragen, bei denen Fixes unvollständig angewendet wurden.
Verwandte CWEs
- CWE-710: Improper Adherence to Coding Standards (Eltern)
- CWE-1006: Bad Coding Practices (Kategoriemitglied)
- CWE-398: Indicator of Poor Code Quality (verwandt)
Referenzen
-
MITRE Corporation. "CWE-1041: Use of Redundant Code." https://cwe.mitre.org/data/definitions/1041.html
-
Martin, Robert C. "Clean Code: A Handbook of Agile Software Craftsmanship."
-
Hunt, Andrew und Thomas, David. "The Pragmatic Programmer" - DRY-Prinzip.