Funktionsaufruf mit falscher Variable oder Referenz als Argument
Beschreibung
Funktionsaufruf mit falscher Variable oder Referenz als Argument ist ein Programmierfehler, bei dem Code eine Funktion mit der falschen Variable oder Referenz als Argument aufruft. Im Gegensatz zu Typ- oder Wertfehlern tritt dies auf, wenn ein Programmierer versehentlich eine andere Variable als beabsichtigt übergibt - oft durch Tippfehler, Copy-Paste-Fehler oder Verwechslung zwischen ähnlich benannten Variablen. Die übergebene Variable kann den korrekten Typ und sogar einen vernünftigen Wert haben, aber es ist einfach nicht die Variable, mit der die Funktion arbeiten sollte. Dies kann dazu führen, dass Funktionen die falschen Daten verarbeiten, mit ernsthaften Sicherheitsauswirkungen.
Risiko
Das Übergeben der falschen Variable an Funktionen erzeugt ernsthafte Sicherheitsrisiken, die schwer zu erkennen sind. Autorisierungsprüfungen, die falsche Rollen-Arrays verwenden, gewähren möglicherweise unangemessenen Zugriff. Sicherheitsfunktionen, die auf falschen Datenstrukturen arbeiten, liefern möglicherweise falsche Validierung. Speicheroperationen auf falschen Puffern können Korruption oder Informationslecks verursachen. Das Risiko wird verstärkt, weil diese Bugs oft syntaktisch und typkorrekt erscheinen und Compiler-Prüfungen sowie oberflächliche Code-Reviews passieren. In Sicherheitskontexten kann die Verwendung der falschen Variable - wie das Übergeben von Admin-Rollen statt Benutzerrollen - Zugangskontrollsysteme vollständig untergraben.
Lösung
Verwenden Sie aussagekräftige und unterscheidbare Variablennamen, die den Zweck klar anzeigen. Vermeiden Sie es, Variablen ähnlich wie globale oder statische Variablen zu benennen. Minimieren Sie den Variablenbereich, um die Chance zu reduzieren, falsche Variablen zu verwenden. Verwenden Sie IDE-Funktionen, die die Variablenverwendung hervorheben. Führen Sie sorgfältige Code-Reviews durch, die speziell nach Copy-Paste-Fehlern und Variablennamenverwechslungen suchen. Implementieren Sie umfassende Unit-Tests, die verifizieren, dass Funktionen auf den beabsichtigten Daten arbeiten. Verwenden Sie statische Analysetools, die verdächtige Variablenverwendungsmuster erkennen können. Erwägen Sie die Verwendung benannter Parameter, wo die Sprache dies unterstützt.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Sonstiges | Bereich: Sonstiges Qualitätsverschlechterung - Funktionen arbeiten auf falschen Daten und produzieren falsche und unvorhersehbare Ergebnisse. |
| Zugriffskontrolle | Bereich: Zugriffskontrolle Privilegien erlangen oder Identität annehmen - Die Verwendung falscher Rollen- oder Berechtigungsvariablen kann unbefugten Zugriff gewähren. |
| Vertraulichkeit | Bereich: Vertraulichkeit Anwendungsdaten lesen - Die Verarbeitung falscher Puffer oder Datenstrukturen kann sensible Informationen preisgeben. |
Beispielcode
Anfälliger Code
// Anfällig: Statische Admin-Rollen statt der tatsächlichen Benutzerrollen verwenden
public class VulnerableAccessControl {
// Statisches Admin-Rollen-Array als Referenz
private static final String[] ADMIN_ROLES = {"admin", "superuser", "root"};
public boolean checkAccess(String resource, String[] userRoles) {
// Anfällig: Versehentlich ADMIN_ROLES statt userRoles verwenden!
return accessGranted(resource, ADMIN_ROLES); // FALSCHE VARIABLE!
// Jeder Benutzer erhält Admin-Level Zugriffsprüfung
// Sollte sein: return accessGranted(resource, userRoles);
}
private boolean accessGranted(String resource, String[] roles) {
for (String role : roles) {
if (hasPermission(role, resource)) {
return true;
}
}
return false;
}
}
// Anfällig: Copy-Paste-Fehler mit ähnlichen Variablennamen
public class VulnerableCopyPaste {
public void processUserData(User sourceUser, User targetUser) {
// Berechtigungen des Quellbenutzers validieren
validatePermissions(sourceUser);
// Anfällig: Copy-Paste-Fehler - sourceUser zweimal verwenden
copyData(sourceUser, sourceUser); // FALSCH! Sollte targetUser sein
// Daten von Quelle zu sich selbst kopiert statt zum Ziel
}
public void updateRecords(Record oldRecord, Record newRecord) {
// Anfällig: Variablen vertauscht
database.delete(newRecord); // FALSCH! Löscht neu statt alt
database.insert(oldRecord); // FALSCH! Fügt alt wieder ein statt neu
}
}
// Anfällig: Falscher Puffer in Kernel-Code verwendet (CVE-2005-2548 Muster)
#include <string.h>
struct packet_header {
int type;
int length;
char data[256];
};
struct packet_header global_header; // Globale Vorlage
// Anfällig: Falsche Variable im ersten Argument
void vulnerable_init_packet(struct packet_header* user_packet) {
// Anfällig: global_header als Ziel statt user_packet verwenden
memcpy(&global_header, &global_header, sizeof(struct packet_header));
// Kopiert global zu sich selbst - user_packet unverändert!
// Sollte sein: memcpy(user_packet, &global_header, sizeof(...))
}
// Anfällig: Falscher Pointer verursacht NULL-Dereferenzierung
void vulnerable_process(struct data* input, struct data* output) {
struct data* temp = NULL;
if (validate(input)) {
temp = allocate_data();
// ... Verarbeitung ...
}
// Anfällig: 'input' verwendet wo 'temp' beabsichtigt war
if (input != NULL) { // Sollte 'temp' prüfen
copy_data(output, input); // Verwendet möglicherweise unvalidiertes temp
}
}
# Anfällig: Falsche Liste in Schleife verwenden
def vulnerable_batch_process(pending_items, completed_items):
processed = []
# Anfällig: Über completed_items iterieren statt pending_items
for item in completed_items: # FALSCHE LISTE!
result = process(item)
processed.append(result)
# Verarbeitet bereits abgeschlossene Elemente erneut, verpasst ausstehende
return processed
# Anfällig: Falsches Dictionary im Sicherheitskontext
class VulnerableAuth:
def __init__(self):
self.valid_tokens = {} # Benutzer-Tokens
self.revoked_tokens = {} # Ungültig gemachte Tokens
def validate_token(self, token):
# Anfällig: Falsches Dictionary prüfen
if token in self.revoked_tokens: # FALSCH! Sollte valid_tokens prüfen
return True # Akzeptiert widerrufene Tokens!
return False
# Anfällig: Ähnliche Variablennamen
def calculate_discount(base_price, discount_rate, discounted_price):
# Anfällig: discounted_price statt base_price verwenden
calculated = discounted_price * (1 - discount_rate) # FALSCH!
# Wendet Rabatt auf bereits rabattierten Preis an
# Sollte base_price verwenden
return calculated
// Anfällig: Falsche Objekteigenschaft verwenden
function vulnerableUserUpdate(currentUser, newData) {
const adminDefaults = {
role: 'admin',
permissions: ['all']
};
const userDefaults = {
role: 'user',
permissions: ['read']
};
// Anfällig: adminDefaults statt userDefaults verwenden
return Object.assign({}, adminDefaults, newData); // FALSCH!
// Normale Benutzer erhalten Admin-Standardwerte
}
// Anfällig: Falsches Array in splice
function vulnerableRemoveItem(activeList, archiveList, itemId) {
const index = activeList.findIndex(item => item.id === itemId);
if (index !== -1) {
// Anfällig: Aus archiveList entfernen statt activeList
archiveList.splice(index, 1); // FALSCHES ARRAY!
// Entfernt falsches Element aus falscher Liste
}
}
Lösung
// Korrigiert: Korrekte Variablen mit klarer Benennung verwenden
public class SecureAccessControl {
private static final String[] ADMIN_ROLES = {"admin", "superuser", "root"};
public boolean checkAccess(String resource, String[] requestingUserRoles) {
// Korrigiert: Korrekt benannten Parameter verwenden
return accessGranted(resource, requestingUserRoles);
}
// Alternative: Methode schwieriger falsch zu verwenden machen
public boolean checkAccessForUser(String resource, User user) {
String[] userRoles = user.getRoles(); // Rollen vom Benutzerobjekt holen
return accessGranted(resource, userRoles);
}
private boolean accessGranted(String resource, String[] roles) {
for (String role : roles) {
if (hasPermission(role, resource)) {
return true;
}
}
return false;
}
}
// Korrigiert: Unterscheidbare Variablennamen verhindern Copy-Paste-Fehler
public class SecureCopyPaste {
public void processUserData(User fromUser, User toUser) {
// Korrigiert: Unterscheidbare Namen machen Fehler offensichtlich
validatePermissions(fromUser);
copyData(fromUser, toUser);
}
public void updateRecords(Record recordToDelete, Record recordToInsert) {
// Korrigiert: Namen zeigen Zweck an
database.delete(recordToDelete);
database.insert(recordToInsert);
}
}
// Korrigiert: Korrekte Variablen mit klarer Dokumentation
#include <string.h>
struct packet_header {
int type;
int length;
char data[256];
};
static const struct packet_header DEFAULT_HEADER = {0, 0, {0}};
// Korrigiert: Korrekte Zielvariable
void secure_init_packet(struct packet_header* dest_packet) {
// Korrigiert: Von Vorlage ZUM Ziel kopieren
memcpy(dest_packet, &DEFAULT_HEADER, sizeof(struct packet_header));
}
// Korrigiert: Korrekter Pointer mit klarer Benennung
void secure_process(struct data* input_data, struct data* output_data) {
struct data* processed_temp = NULL;
if (validate(input_data)) {
processed_temp = allocate_data();
// ... Verarbeitung ...
}
// Korrigiert: Die richtige Variable prüfen
if (processed_temp != NULL) {
copy_data(output_data, processed_temp);
free_data(processed_temp);
}
}
// const verwenden um versehentliche Modifikation zu verhindern
void init_from_template(struct packet_header* dest,
const struct packet_header* template) {
// template ist const - kann nicht versehentlich als Ziel verwendet werden
memcpy(dest, template, sizeof(struct packet_header));
}
# Korrigiert: Klare Variablenbenennung
def secure_batch_process(items_to_process, already_completed):
processed = []
# Korrigiert: Klarer Name zeigt Absicht an
for item in items_to_process:
result = process(item)
processed.append(result)
return processed
# Korrigiert: Explizite Validierungslogik
class SecureAuth:
def __init__(self):
self.active_tokens = {}
self.revoked_tokens = {}
def validate_token(self, token):
# Korrigiert: Explizite zweistufige Validierung
is_active = token in self.active_tokens
is_revoked = token in self.revoked_tokens
# Token muss aktiv UND nicht widerrufen sein
return is_active and not is_revoked
# Korrigiert: Eindeutige Parameternamen
def calculate_discount(original_price, discount_percentage, existing_discount=0):
# Korrigiert: Klar welcher Preis zu verwenden ist
price_before_discount = original_price
calculated = price_before_discount * (1 - discount_percentage)
return calculated
// Korrigiert: Explizite Variablenauswahl
function secureUserUpdate(currentUser, newData, isAdmin = false) {
const adminDefaults = {
role: 'admin',
permissions: ['all']
};
const userDefaults = {
role: 'user',
permissions: ['read']
};
// Korrigiert: Explizite Auswahl basierend auf Bedingung
const defaultsToUse = isAdmin ? adminDefaults : userDefaults;
return Object.assign({}, defaultsToUse, newData);
}
// Korrigiert: Auf korrektem Array mit Validierung arbeiten
function secureRemoveItem(sourceList, targetList, itemId) {
const index = sourceList.findIndex(item => item.id === itemId);
if (index !== -1) {
// Korrigiert: Aus Quelle entfernen, optional zu Ziel verschieben
const [removed] = sourceList.splice(index, 1);
if (targetList) {
targetList.push(removed); // Archivieren wenn Ziel angegeben
}
}
}
// Best Practice: Objektparameter verwenden um Variablenverwechslung zu verhindern
function updateItem({ fromList, toList, itemId }) {
// Benannte Parameter machen klar welches welches ist
const index = fromList.findIndex(item => item.id === itemId);
if (index !== -1) {
const [item] = fromList.splice(index, 1);
toList.push(item);
}
}
CVE-Beispiele
- CVE-2005-2548: Linux-Kernel-Code spezifizierte die falsche Variable in einem initialen Argument, was zu einer NULL-Pointer-Dereferenzierungs-Schwachstelle führte.
- CVE-2006-1052: Falsche Variable im Vergleich verwendet, führte zur Authentifizierungsumgehung.
Referenzen
- MITRE Corporation. "CWE-688: Function Call With Incorrect Variable or Reference as Argument." https://cwe.mitre.org/data/definitions/688.html
- CERT C Coding Standard. "EXP37-C. Call functions with the correct number and type of arguments."