Gewährleistungsfehler bei Zugriffskontrollen treten auf, wenn ein Solidity-Vertrag einem unzuverlässigen Anrufer die Möglichkeit gibt, eine zustandsändernde Fähigkeit zu nutzen, die eigentlich eingeschränkt sein sollte, wie z.B. Vermögensbewegungen, Änderungen an der Implementierung, Rollenzuweisungen oder die Konfiguration eines vertrauenswürdigen Adresskontos. Der Angreifer muss keine Kryptografie brechen: Er nutzt eine fehlende, fehlerhafte oder zu breit gefasste Zugriffsprüfung aus, um effektive Privilegienerweiterungen zu erzielen.
Die Auswirkungen können protokollübergreifend sein, da privilegierte Funktionen oft Treuhandfonds oder governance-kritische Konfigurationen steuern. Poly Network verlor am 10.08.2021 611,0 Mio. USD auf Ethereum, BSC und Polygon in einem Vorfall, der laut DefiLlama als Unzureichende Zugriffskontrolle klassifiziert wurde. Zugriffsrechte sind daher kein UI-Thema oder eine administrative Feinheit. Sie sind Teil der Kern-Sicherheitsgrenze eines Vertrags.
Was ist eine Schwachstelle bei der Zugriffskontrolle in Solidity?
Eine Sicherheitslücke bei der Zugriffskontrolle besteht, wenn ein Vertrag nicht zuverlässig überprüft, ob msg.sender für eine privilegierte Aktion autorisiert ist, oder wenn das Autorisierungsmodell mehr Befugnisse gewährt, als für die Aktion notwendig sind. In Solidity zeigt sich dies meist bei extern aufrufbaren Funktionen, die sensible Speicherbereiche modifizieren, Vermögenswerte transferieren, Code upgraden oder vertrauenswürdige Gegenparteien ändern.
Ein Vertrag kann auch dann anfällig sein, wenn eine owner-Variabel existiert. Entscheidend ist jedoch, ob jeder einzelne Pfad für privilegierte Ausführungen korrekt überprüft, wer die Berechtigung besitzt — inklusive Hilfsfunktionen, Initialisierer, Rollenmanagement-Funktionen und Upgrade-Hooks.
Eine typische Angriffskette bei unzureichender Zugriffskontrolle folgt diesem Ablauf:
- Der Angreifer identifiziert eine extern aufrufbare Funktion mit privilegierten Konsequenzen.
- Die Funktion führt keine Überprüfung des Anrufers durch, prüft die falsche Adresse oder vertraut auf vom Angreifer kontrollierten Zustand.
- Der Angreifer ruft die Funktion direkt auf, um Frontend-Beschränkungen zu umgehen.
- Der Aufruf gewährt eine Rolle, ändert eine vertrauenswürdige Adresse oder initiiert eine Vermögensbewegung.
- Der Angreifer nutzt die dadurch gewonnenen Rechte, um Gelder zu extrahieren oder das Protokollverhalten zu verändern.
- Der Vertrag akzeptiert die Transaktion, weil die EVM nur On-Chain-Checks durchführt.
Frontend-Buttons, Dokumentationen oder der vorgesehenen Betriebsvorgaben schränken direkte Vertragsaufrufe nicht ein. Jeder Account kann calldata an eine öffentliche oder externe Funktion schicken. Solidity-Code muss daher die Zugriffsrichtlinien exakt an der Stelle durchsetzen, an der eine sensible Zustandsänderung erfolgt.
Welche Solidity-Muster führen zu Angriffen auf die Zugriffskontrolle und Privilegienerweiterungen?
Fehlerhafte Zugriffskontroll-Implementierungen entstehen häufig, wenn Entwickler Konfigurations-Setter, Verwaltungs-Hilfsfunktionen oder Initialisierungswege offenlegen, ohne die Tatsache zu berücksichtigen, dass jede öffentliche Funktion eine API für Angreifer darstellt. Das gefährliche Muster ist nicht nur das Fehlen eines onlyOwner-Modifiers; es umfasst auch Zugriffsrechte, die veränderbar durch beliebige Anrufer sind, falsch vererbte Rechte, inkonsistent angewendete Zugriffsprüfung oder Rechte, die zu breit für die jeweilige Operation sind.
Häufige Fehler sind:
- Öffentliche Setter, die jedem erlauben, eine Treasury, Oracle, Implementierung, Operator oder Begünstigten zu ersetzen.
- Rollenmanagement-Funktionen ohne einen Administrator-Check.
- Initialisierer, die nach Deployment aufgerufen werden können oder von unbefugten Konten.
- Funktionen, die
tx.originprüfen anstattmsg.sender. - Eine privilegierte interne Funktion, die durch einen ungeschützten externen Wrapper aufgerufen werden kann.
- Eine einzige Administratorrolle, die alle Operationen ausführen kann, was den Schadensradius erhöht.
- Autorisierung basierend auf einer vom Nutzer bereitgestellten Adresse anstatt auf eine unveränderliche oder kontrollierte Rollenzuordnung.
- Upgrade-Funktionen, die den Aufrufer validieren, aber nicht die neue Implementierung oder den Upgrade-Pfad.
Dieses Muster ist besonders subtil:
function setOperator(address newOperator) external {
operator = newOperator;
}
Die Zahlungsfunktion erfordert vielleicht korrekt msg.sender == operator, aber die Zugriffskontrollgrenze ist bereits durchbrochen, weil jeder sich selbst zum Operator ernennen kann. Entwickler sollten alle sensiblen Funktionen rückverfolgen, um zu prüfen, wer die erforderliche Rolle erwerben kann.
Soken sieht die Rollenzuweisung und die Konfiguration vertrauenswürdiger Adressen als eigenständige privilegierte Operationen. Ein sicheres Zugriffsdesign schützt sowohl die endgültige Vermögensübertragung als auch jede Route, um sie freizuschalten.
Wie sieht eine Schwachstelle bei Zugriffskontrolle in Solidity-Code aus?
Dieses verwundbare Vault prüft den Anrufer vor Auszahlung, aber die Funktion setPayoutOperator ist öffentlich. Ein Angreifer kann sich selbst als Operator zuweisen und anschließend pay aufrufen, wodurch die nachfolgende Autorisierungsüberprüfung ihre Bedeutung verliert.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract VulnerablePayoutVault {
address public payoutOperator;
constructor(address initialOperator) {
payoutOperator = initialOperator;
}
receive() external payable {}
function setPayoutOperator(address newOperator) external {
// ANFÄLLIG: Jeder kann sich selbst Auszahlungsrecht gewähren.
payoutOperator = newOperator;
}
function pay(address payable recipient, uint256 amount) external {
require(msg.sender == payoutOperator, "nicht operator");
require(address(this).balance >= amount, "nicht genug Guthaben");
(bool sent, ) = recipient.call{value: amount}("");
require(sent, "Zahlung fehlgeschlagen");
}
}
Die Lösung trennt Verwaltung von Operationen. Nur der Eigentümer kann die Rolle für Auszahlungen beschränken oder aufheben, während ein Auszahlungsmann nicht Rollen verwalten oder Eigentum ändern kann.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract FixedPayoutVault {
address public owner;
mapping(address => bool) public payoutOperators;
modifier onlyOwner() {
require(msg.sender == owner, "nicht Eigentümer");
_;
}
modifier onlyPayoutOperator() {
require(payoutOperators[msg.sender], "nicht payout-Operator");
_;
}
constructor(address initialOwner, address initialOperator) {
require(initialOwner != address(0), "Nulladresse Eigentümer");
require(initialOperator != address(0), "Nulladresse Operator");
owner = initialOwner;
payoutOperators[initialOperator] = true;
}
receive() external payable {}
function setPayoutOperator(address operator, bool allowed) external onlyOwner {
require(operator != address(0), "Nulladresse");
// FIX: Nur der Eigentümer kann privilegierte Rollen ändern.
payoutOperators[operator] = allowed;
}
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "Nulladresse");
owner = newOwner;
}
function pay(address payable recipient, uint256 amount)
external
onlyPayoutOperator
{
require(address(this).balance >= amount, "nicht genug Guthaben");
(bool sent, ) = recipient.call{value: amount}("");
require(sent, "Zahlung fehlgeschlagen");
}
}
Wenn Rollenänderungen, Upgrade-Berechtigungen oder Abhebungen vom Treasury in deinem System vorhanden sind, sollte eine Smart-Contract-Sicherheitsüberprüfung mit Fokus auf Zugriffskontrolle nachvollziehen, ob alle Wege zu diesen Fähigkeiten richtig eingeschränkt sind.
Wie können Solidity-Entwickler unzureichende Zugriffskontroll-Schwachstellen verhindern?
Vermeidung von Fehlern bei Zugriffskontrollen erfordert ein explizites Berechtigungsmodell, nicht nur verstreute require-Prüfungen nach der Implementierung. Es ist notwendig, genau festzulegen, welcher Akteur welche sensiblen Operationen ausführen darf, warum diese Befugnisse bestehen und welche kleineren Rollen Routineaufgaben sicher erledigen können.
| Technik | Was sie verhindert | Gas- oder Komplexitätskosten | Einschränkungen |
|---|---|---|---|
onlyOwner-Modifier |
Unbefugte Verwaltung von Owner-only-Funktionen | Ein Speicherzugriff pro geschütztem Call | Ein kompromittierter Eigentümer besitzt weiterhin volle Eigentümerrechte |
Rollenzuordnungen oder OpenZeppelin AccessControl |
Unbefugte Nutzung separater Betriebsrollen | Speicherzugriffe und Rollenmanagement-Logik | Schlechte Rollengestaltung kann zu übermäßigen Privilegien führen |
| Least-privilege-Rollen | Ein Betreiber oder Operator nutzt unzugehörige admin-Rechte | Mehr Funktionen und Rollendefinitionen pflegen | Klare Betriebsgrenzen erforderlich |
| Timelocks für kritische Änderungen | Sofortige bösartige Upgrades oder Parameteränderungen | Verzögerte Ausführung und zusätzliche Verträge | Keine Verhinderung bösartiger Aktionen nach der Verzögerung, außer Nutzer können reagieren |
| Multisignatur-verwaltung | Ein einzelner Schlüssel ändert privilegierten Status unilateral | Koordination der Signaturen und Betriebsaufwand | Gemeinsame Signaturen oder schwache Policies bleiben riskant |
| Einmalige Initialisierungsprüfungen | Unbefugte oder wiederholte Initialisierung | Ein Speicher-Flag und Initialisierungs-Logik | Deployment-Verfahren müssen weiterhin die gewünschte Autorität setzen |
Nutze gut geprüfte Ownership- und Rollen-Bibliotheken, aber behandle diese nicht als vollständiges Sicherheitsmodell. Beispiel: OpenZeppelin Ownable schafft Eigentümermechanismen, die Protokoll-Teams müssen aber weiterhin entscheiden, ob Eigentum Kontrolle über Pausen, Upgrades, Gebühren, Oracle-Austausch oder Notfallwiederherstellung übernehmen soll.
Vermeide tx.origin bei der Autorisierung. Es lässt sich durch Zwischenverträge beeinflussen und identifiziert nicht den unmittelbaren Anrufer. Nutze msg.sender und überprüfe diesen anhand einer festgelegten Eigentümer-, Rollen-, Multi-Sig- oder vertragspezifischen Autorisierungsregel.
Welche echten Vorfälle verdeutlichen die Folgen von Zugriffskontrollangriffen?
Laut DefiLlama wurden zwischen 2020 und 2026 130 Sicherheitsvorfälle bei Smart Contracts registriert, die als Unzureichende Zugriffskontrolle klassifiziert sind, ohne Börsen- oder Wallet-Hacks, mit Gesamtschäden von 909,7 Mio. USD. Die folgenden bestätigten Fälle zeigen, dass Mängel bei der Zugriffskontrolle Brücken, DeFi-Protokolle, Bots und Anwendungen auf mehreren Chains treffen können.
| Protokoll | Datum | Betrag | Chain |
|---|---|---|---|
| Poly Network | 2021-08-10 | 611,0 Mio. USD | Ethereum, BSC, Polygon |
| Mirror | 2021-10-08 | 90,0 Mio. USD | Terra |
| Wintermute | 2022-06-05 | 17,6 Mio. USD | Optimism |
| ValueDefi | 2021-05-05 | 10,0 Mio. USD | BSC |
| Cork V1 | 2025-05-28 | 12,0 Mio. USD | Ethereum |
| SUPERFORTUNE AI | 2026-05-27 | 15,2 Mio. USD | Ethereum |
| The Sandbox | 2026-08-22 | 675K USD | Base, BSC, Ethereum |
| Radix | 2026-08-31 | 1,2 Mio. USD | Radix |
Diese Vorfälle liefern eine klare Sicherheitslehre: Der wirtschaftliche Wert eines Protokolls ist gefährdet, wenn die Autoritätsgrenze eines Vertrags nicht dem beabsichtigten Vertrauensmodell entspricht. Die konkrete betroffene Funktion kann variieren, aber die Fehlerklasse bleibt gleich: Ein Akteur erlangt oder übt Befugnisse aus, die eigentlich vom Design her vorenthalten werden sollten.
Wie erkennt man Schwachstellen bei Zugriffskontrolle vor dem Deployment?
Die Erkennung von Zugriffskontrollfehlern erfordert die Zuordnung sensibler Zustandsänderungen zu ihren Autorisationsbedingungen und den Nachweis, dass keine alternative Aufrufroute diese Bedingungen umgehen kann. Automatisierte Tools helfen, verdächtige Muster zu identifizieren, aber menschliche Reviews sind essenziell, um Business-Authority, Vertrauensannahmen und Privilegienketten zu verstehen.
Nutze dazu diese Checkliste:
- Liste alle Funktionen auf, die Vermögenswerte transferieren, Rollen ändern, Code upgraden, Aktivitäten pausieren oder vertrauenswürdige Adressen ändern.
- Bestimme den vorgesehenen Anrufer und die Autorisierungsregel für jede Funktion.
- Verfolge jede Funktion, die diese Autorität gewähren, widerrufen, übertragen oder initialisieren kann.
- Überprüfe alle externen Wrappers, die zu privilegierten internen Funktionen führen.
- Stelle sicher, dass Initialisierungen nur einmal und nur unter dem vorgesehenen Deployment durchgeführt werden.
- Überprüfe, ob Notfallrollen keine routine- oder Governance-Aktivitäten mit ungeeigneter Berechtigung ausführen können.
- Teste Rollenwiderruf, Eigentümer-Transfer und Null-Adressen-Handling.
- Analysiere Proxies, vererbte Verträge und
delegatecall-Wege im Rahmen derselben Autoritätsgrenze.
Slither kann fehlende Autorisierungen, gefährlichen tx.origin-Einsatz und inkonsistente Modifier kennzeichnen, aber die Ergebnisse sind manuell zu validieren. Foundry-Fuzzing ist hilfreich, um Aufrufe von beliebigen Adressen zu generieren und sicherzustellen, dass unautorisierte Anrufer keine privilegierten Zustände ändern können.
Invariant-Tests sind besonders effektiv. Beispielsweise kann eine Vault-Invariante festlegen, dass eine Adresse ohne Rollen für Auszahlungen niemals den Kontostand durch pay verringern darf. Eine weitere Invariante stellt sicher, dass nur der Eigentümer Rollenmitgliedschaften ändern kann. Diese Eigenschaften testen die Sicherheitsregeln direkt, anstatt nur erwartete Nutzerflüsse.
Sicherheits-Insight, Soken-Methodik: Betrachte Autorisierung als Capabilty-Graph, nicht nur als eine Liste von Modifiers. Jede privilegierte Handlung muss einen absichtlich geplanten und auditierbaren Pfad zur Autorität haben, und jeder unbeabsichtigte Pfad ist potenziell eine Eskalationsroute.
Schwachstellen bei Zugriffskontrolle werden vermieden, indem die Autorität explizit gemacht, jeder Rolle nur die minimal notwendigen Befugnisse zugewiesen und Funktionen, die diese Befugnisse verwalten, so sorgfältig wie Funktionen zum Vermögenstransfer geschützt werden. Eine korrekt eingeschränkte Abhebefunktion ist nicht sicher, wenn jeder den Abzuhandelner ernennen kann.
Beginne mit der Erstellung einer Autoritätskarte für deine deployten und geplanten Verträge, inklusive Proxies und Betriebs-Accounts. Wandelt jede Regel in einen Modifier und einen invarianten Test um. Für tiefergehende Solidity-Sicherheitsforschung und angrenzende Schwachstellenklassen besuche das Soken Hub.