
0. Rückblick
- Das Solana-Ökosystem sichern (1) — Hallo Solana
- Das Solana-Ökosystem sichern (2) — Aufrufe zwischen Programmen
- Das Solana-Ökosystem sichern (3) — Programm-Upgrade
1. Überblick
Im vorherigen Blogbeitrag haben wir besprochen, wie ein Programm aktualisiert wird. In diesem Beitrag stellen wir die Probleme im Zusammenhang mit der Zugriffskontrolle vor, einem der häufigsten und grundlegendsten Sicherheitsthemen im Bereich DeFi.
2. Anweisungen
In Solana exportiert jedes Programm einen einzigen entrypoint, der mit entrypoint! definiert ist. Im Gegensatz zu Ethereum können Clients nur eine einzige Funktion aufrufen, die als entrypoint definiert ist und normalerweise process_instruction genannt wird. Die entrypoint-Funktion empfängt drei Parameter: die ProgramID des Smart Contracts, die Konten, auf denen das Programm operieren wird, und die Instruktionsdaten. Die Instruktionsdaten geben an, welche Instruktion aufgerufen wird. Die folgende Abbildung zeigt ein Beispiel. Durch Entpacken der Instruktionsdaten werden verschiedene Instruktionen (z. B. Lock, Unlock) ausgewählt. Somit sind die von entrypoint erreichbaren Instruktionen für jeden öffentlich und können mit angegebenen Instruktionsdaten ausgeführt werden.

3. Kontenvalidierung
Wie bereits erwähnt, empfängt das Programm die Konten, die es lesen oder schreiben muss. Dieses Design wirft zwei Fragen auf. Wie kann für zu lesende Konten garantiert werden, dass die darin gespeicherten Daten vertrauenswürdig sind? Wie kann für zu schreibende Konten garantiert werden, dass nur privilegierte Benutzer die Anweisungen aufrufen können, um in die Konten zu schreiben? Im Folgenden illustrieren wir das Problem der Zugriffskontrolle. Alle Testcodes finden Sie hier.
3.1 Code-Review (PrivilegeOwner)


Wir definieren zunächst zwei Strukturen: Door und Config. Nur das in der Struktur door definierte Schlüsselkonto (Zeile 17) kann die erstellte door öffnen. Die Tür kann jedoch nicht geöffnet werden, wenn der Systemzustand gesperrt ist, was in der Struktur Config (Zeile 81) angegeben ist.

Wie erwähnt, gibt das Config-Konto an, ob die Tür geöffnet werden kann. In diesem Fall sollte es nur ein Config-Konto im Programm geben. Um dies zu erreichen, verwenden wir PDA, um die Daten von Config zu speichern. Nach der Initialisierung des Config-Kontos setzen wir das Attribut is_initialized auf true, damit es nicht von Angreifern erneut initialisiert werden kann (Zeile 108 - Zeile 110).

Die Anweisung Open() wird zum Öffnen der Türen verwendet. Die Anweisung empfängt mehrere Konten, einschließlich des zu öffnenden Tür-Kontos, des config-Kontos und des owner-Kontos, das die door öffnen soll. Um sicherzustellen, dass die Tür dem Programm gehört und die Konfiguration gültig ist, überprüfen wir den Eigentümer des door-Kontos und des config-Kontos (Zeile 204 - Zeile 205). Dies verhindert, dass böswillige Benutzer gefälschte Konten übergeben. Dies beantwortet unsere erste Frage: Um sicherzustellen, dass das zu lesende Konto vertrauenswürdig ist, müssen wir den Eigentümer des Kontos überprüfen! Beachten Sie, dass nur der Eigentümer des door-Kontos die Tür öffnen kann. In diesem Fall prüfen wir, ob das Eigentümer-Konto der tatsächliche owner der door ist und, was noch wichtiger ist, ob die Anweisung vom Eigentümer autorisiert ist (Zeile 217 - Zeile 219).

In der Funktion validate_owner() prüfen wir zunächst, ob die öffentlichen Schlüssel dieser beiden Konten gleich sind, und dann die Signatur des Eigentümers. Dies beantwortet die zweite Frage: Um sicherzustellen, dass nur privilegierte Benutzer die open-Anweisung aufrufen können, müssen wir den Eigentümer und den Unterzeichner des Kontos überprüfen. Die close-Anweisung ähnelt der open-Anweisung, und die Details finden Sie im Code.
Wir haben das Programm auf dem Testnetz bereitgestellt und es kann unter folgendem Link gefunden werden:
https://explorer.solana.com/address/2Q7FFMWCthBvc6ubLQRx9TRswvaimmd66VaCAfHwsYuC?cluster=testnet
Alle Testtransaktionen sind unten aufgelistet. Der gesamte Ablauf dieser Transaktionen ist Allocate PDA()-> InitializeDoor()-> InitializeConfig()-> Unlock() -> Open() -> Close().
https://explorer.solana.com/tx/2X9CyMrHTNEvbzXTE95gem2j8spnvsQsabFeSpV8hiNpYjiQPPzLRqt5KN86ZYRjnQvydvs7y5eUjJK7no8knDhk?cluster=testnet
https://explorer.solana.com/tx/2XfVWiXeQeHbpqAEYm3AH2RU6hunnqtr155EC4EAM5Bq9VVZNP6QocAav9cPjEQdJFcQrbsSSxiKadr4HPMov8pz?cluster=testnet
https://explorer.solana.com/tx/5Em41sg7yFXeNpnEJnhUQJanfLWKwjMqiBeNAqEEzFrSN9P8zKKafcv5F7RKT2pseB171qeoa8Uz4fKgazzayCnW?cluster=testnet
https://explorer.solana.com/tx/2PMtzpSgjnKDLGmRWBdUSFBPimWnudCPekUYbWzPzokENFYa4N4ab4HCtynfGrzswFPTgGYKHU8PccUMHv3mXHkR?cluster=testnet
https://explorer.solana.com/tx/3kviP9MqkWGMV4yA7k7yPQ5BGfXmcYLcctmY1u2D7n56eT1nx8jMtDumkUNJy8yA3KkmzrmfQLjqpigc8ehGZzBN?cluster=testnet
https://explorer.solana.com/tx/38iEaJBzuGMLbfcszdVB8pkniezH8JrA3XGq7JdADZTQ4hNQC82GSTUA2bmcypdVy3t7htWnUzkZ4F8EakmNvqz8?cluster=testnet
3.2 Angreifertransaktion
Um die Bedeutung der Eigentümer- und Signaturprüfungen zu verdeutlichen, verwenden wir zwei Angreiferszenarien als Beispiele.
Erstes Szenario
Das erste Szenario ist, dass der "Tür"-Eigentümer versucht, die Tür zu öffnen, wenn die config gesperrt ist. Um dies zu erreichen, erstellen wir ein gefälschtes config-Konto in einem anderen Programm und weisen dem Attribut is_lock den Wert false zu. Der Code des benutzerdefinierten Programms ist unten dargestellt.
Wir senden die Transaktion zur Erstellung des gefälschten config-Kontos. Die öffentliche Adresse des gefälschten config-Kontos lautet: 2MtSrbWp24VjPZQcSUkiWrvNro7qqKemVCsh3Yxc8LTy.
https://explorer.solana.com/tx/2qSyrL5gdQXmgGCFzmzMm1StFQRkDgWpss9A9jV11q2fgDGM5C1XRuXvbX1N5Dt3q2pRqnmyXHVtXGF5dqadAzpJ?cluster=testnet
Sobald das gefälschte config-Konto erstellt ist, übergeben wir es an das Programm (Zeile 423).

Das Ergebnis ist unten gezeigt. Die Protokollmeldung lautet incorrect program id for instruction, was bedeutet, dass der Eigentümer des config-Kontos das Programm sein muss. Somit kann der Angreifer diese Prüfung nicht umgehen.

Zweites Szenario
Das zweite Szenario ist, dass ein böswilliger Benutzer versucht, die Tür zu öffnen, wenn die Tür nicht gesperrt ist.

In diesem Fall übergeben wir das echte Eigentümerkonto an das Programm (Zeile 419) und senden die Transaktion. Das Ergebnis ist unten gezeigt.

Die Meldung lautet Signature verification failed, was bedeutet, dass der echte Eigentümer die Transaktion zur Öffnung der Tür unterzeichnen muss, sodass auch unser zweiter Angriff fehlschlägt.
4. Zusammenfassung
In Solana implementieren Instruktionen basierend auf verschiedenen Konten, die von Clients oder anderen Programmen bereitgestellt werden, spezifische Logik. Daher ist die ordnungsgemäße Überprüfung der Konten sehr wichtig.
In diesem Artikel stellen wir vor, wie Konten ordnungsgemäß überprüft werden, und illustrieren anhand von zwei Angreiferszenarien die Bedeutung dieser Überprüfungen. Bleiben Sie dran, weitere Artikel werden folgen.
Lesen Sie andere Artikel dieser Reihe:
- Das Solana-Ökosystem sichern (1) — Hallo Solana
- Das Solana-Ökosystem sichern (2) — Aufrufe zwischen Programmen
- Das Solana-Ökosystem sichern (3) — Programm-Upgrade
- Das Solana-Ökosystem sichern (5) — Multi-Sig
- Das Solana-Ökosystem sichern (6) — Multi-Sig2
- Das Solana-Ökosystem sichern (7) — Typenverwechslung
Über BlockSec
BlockSec ist ein führendes Blockchain-Sicherheitsunternehmen, das 2021 von einer Gruppe weltweit renommierter Sicherheitsexperten gegründet wurde. Das Unternehmen engagiert sich für die Verbesserung der Sicherheit und Benutzerfreundlichkeit der aufstrebenden Web3-Welt, um deren massenhafte Einführung zu fördern. Zu diesem Zweck bietet BlockSec Sicherheitsaudits für Smart Contracts und EVM-Chains, die Phalcon-Plattform für die Sicherheitsentwicklung und proaktive Bedrohungsabwehr, die MetaSleuth-Plattform für Geldverfolgung und -untersuchung sowie die MetaSuites-Erweiterung für Web3-Entwickler, um effizient in der Krypto-Welt zu surfen.
Bis heute hat das Unternehmen über 300 angesehene Kunden wie MetaMask, Uniswap Foundation, Compound, Forta und PancakeSwap betreut und in zwei Finanzierungsrunden von namhaften Investoren wie Matrix Partners, Vitalbridge Capital und Fenbushi Capital zweistellige Millionenbeträge erhalten.
Offizielle Website: https://blocksec.com/ Offizieller Twitter-Account: https://twitter.com/BlockSecTeam




