Zugriff auf kritische private Variable über öffentliche Methode
Beschreibung
Zugriff auf kritische private Variable über öffentliche Methode ist eine Kapselungsschwachstelle, bei der Software eine öffentliche Methode definiert, die eine private Variable ohne ordnungsgemäße Validierung oder Zugriffskontrolle liest oder ändert. Obwohl das Private-Machen von Variablen korrekt ist, negiert die Bereitstellung uneingeschränkter öffentlicher Accessoren (Getter/Setter) effektiv den Schutz. Angreifer können diese öffentlichen Methoden verwenden, um kritische Variablen auf unerwartete Werte zu ändern und Sicherheitsannahmen an anderer Stelle im Code zu verletzen.
Risiko
Diese Schwachstelle ermöglicht Angreifern die Manipulation des kritischen internen Zustands über die öffentliche Schnittstelle. Wenn öffentliche Methoden private sicherheitsrelevante Variablen ohne Validierung ändern, können Angreifer bösartige Werte einschleusen, die Sicherheitsprüfungen umgehen, den Kontrollfluss ändern oder Privilegien eskalieren. Ein öffentlicher Setter für eine Benutzerrollenvariable ohne Validierung könnte beispielsweise Privilegieneskalation ermöglichen. Das Exponieren privater Daten durch Getter kann sensible Informationen wie interne IDs oder Sitzungsdaten preisgeben.
Lösung
Implementieren Sie ordnungsgemäße Validierung in allen öffentlichen Methoden, die auf private Variablen zugreifen. Setter sollten Eingabebereiche, Typen und Geschäftsregeln vor der Änderung validieren. Erwägen Sie, Setter restriktiver zu gestalten oder für sicherheitskritische Felder ganz zu eliminieren. Getter sollten defensive Kopien für veränderliche Objekte zurückgeben und prüfen, ob die Daten wirklich exponiert werden müssen. Wenden Sie das Prinzip der geringsten Privilegien an - exponieren Sie nur notwendige Operationen.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Integrität | Bereich: Integrität Anwendungsdaten ändern - Öffentliche Methoden ermöglichen unbefugte Änderung kritischer privater Variablen bei fehlender Validierung. |
| Vertraulichkeit | Bereich: Vertraulichkeit Anwendungsdaten lesen - Öffentliche Getter-Methoden können sensible private Informationen ohne ordnungsgemäße Zugriffskontrolle exponieren. |
| Zugriffskontrolle | Bereich: Zugriffskontrolle Schutzmechanismus umgehen - Angreifer können sicherheitsrelevante private Variablen ändern, um Zugriffskontrollen zu umgehen oder Privilegien zu eskalieren. |
Beispielcode
Verwundbarer Code
// Verwundbar: Öffentlicher Setter ändert kritische private Variable ohne Validierung
class Product {
private:
float price;
int quantity;
bool isDiscounted;
public:
// Verwundbar: Keine Validierung bei Preisänderung
void setPrice(float newPrice) {
price = newPrice; // Kann auf negativ oder null gesetzt werden
}
// Verwundbar: Ermöglicht Manipulation des Rabattflags
void setDiscounted(bool discounted) {
isDiscounted = discounted; // Jeder kann Rabatte anwenden
}
float getPrice() const { return price; }
};
// Ausnutzung
void exploit(Product& p) {
p.setPrice(-100.0); // Negativer Preis - Rückerstattung beim Kauf?
p.setDiscounted(true); // Kostenlose Rabatte
}
// Verwundbar: Tippfehler bewirkt Änderung der falschen Variable
public class UserProfile {
private int profileId; // PID - normaler Benutzeridentifier
private int userId; // UID - System-Benutzeridentifier (privilegierter)
// Verwundbar: Tippfehler ermöglicht Änderung des falschen Feldes
public void setProfileId(int pid) {
this.userId = pid; // BUG: Sollte this.profileId = pid sein
// Dies ermöglicht dem Benutzer, seine System-userId zu ändern!
}
}
// Auch ohne Bugs sind unvalidierte Setter problematisch:
public class Session {
private String role;
private boolean authenticated;
// Verwundbar: Ermöglicht beliebige Rollenzuweisung
public void setRole(String role) {
this.role = role; // Kann auf "admin", "superuser" usw. gesetzt werden
}
// Verwundbar: Ermöglicht Umgehung der Authentifizierung
public void setAuthenticated(boolean auth) {
this.authenticated = auth; // Kann ohne echte Authentifizierung auf true gesetzt werden
}
}
Gefixter Code
// Gefixt: Ordnungsgemäße Validierung und kontrollierter Zugriff
class Product {
private:
float price;
int quantity;
bool isDiscounted;
const float MINIMUM_PRICE = 0.01f;
const float MAXIMUM_DISCOUNT = 0.50f;
public:
Product(float initialPrice, int initialQty)
: price(initialPrice), quantity(initialQty), isDiscounted(false) {
if (price < MINIMUM_PRICE) {
throw std::invalid_argument("Preis muss positiv sein");
}
}
// Gefixt: Validierter Setter mit Geschäftsregeln
bool setPrice(float newPrice) {
if (newPrice < MINIMUM_PRICE) {
return false; // Ungültigen Preis ablehnen
}
price = newPrice;
return true;
}
// Gefixt: Kein öffentlicher Setter für Rabatt - kontrollierte Methode verwenden
bool applyDiscount(float discountPercent, const std::string& authCode) {
if (!validateAuthCode(authCode)) {
return false; // Autorisierung erforderlich
}
if (discountPercent > MAXIMUM_DISCOUNT) {
return false; // Rabattbetrag begrenzen
}
isDiscounted = true;
price = price * (1.0f - discountPercent);
return true;
}
float getPrice() const { return price; }
bool hasDiscount() const { return isDiscounted; }
};
// Gefixt: Ordnungsgemäße Kapselung mit Validierung und Zugriffskontrolle
public class Session {
private String role;
private boolean authenticated;
private final long sessionId;
private static final Set<String> VALID_ROLES =
Set.of("guest", "user", "moderator"); // Admin hier nicht setzbar
public Session(long sessionId) {
this.sessionId = sessionId;
this.role = "guest";
this.authenticated = false;
}
// Gefixt: Kein Setter für Rolle - kontrollierte Beförderungsmethode verwenden
public boolean promoteToRole(String newRole, SecurityContext context) {
if (!context.canPromote(this.role, newRole)) {
throw new SecurityException("Unbefugte Rollenänderung");
}
if (!VALID_ROLES.contains(newRole)) {
return false;
}
this.role = newRole;
return true;
}
// Gefixt: Authentifizierung nur durch ordnungsgemäße Verifizierung
public boolean authenticate(String password, PasswordVerifier verifier) {
if (verifier.verify(this.sessionId, password)) {
this.authenticated = true;
return true;
}
return false;
}
public String getRole() {
return role;
}
public boolean isAuthenticated() {
return authenticated;
}
}
CVE-Beispiele
- CVE-2012-3400: Linux Kernel XFS erlaubte lokalen Benutzern Denial of Service über öffentliche Schnittstelle, die kritische interne Strukturmanipulation exponierte.
Referenzen
- MITRE Corporation. "CWE-767: Access to Critical Private Variable via Public Method." https://cwe.mitre.org/data/definitions/767.html
- CERT C++ Coding Standard. "OOP03-CPP. Use accessor and mutator methods for data encapsulation."
- Oracle Java Secure Coding Guidelines. "SECCODE-6: Minimize the scope of variables."