BNB Chain to jeden z najpopularniejszych łańcuchów bloków w świecie Web3. Jego rozsądne opłaty, szybkie transakcje i bogaty ekosystem projektów przyciągają dużą liczbę użytkowników. Jak w przypadku każdego blockchaina, programiści BNB Chain powinni najpierw rozważyć kwestie bezpieczeństwa podczas procesu rozwoju: ponieważ jakakolwiek utrata środków doprowadzi do osłabienia zaufania użytkowników do protokołu i platformy, a luki w zabezpieczeniach i ataki hakerów są jednym z największych zagrożeń z jakimi borykają się deweloperzy.
W tym artykule przedstawiamy dziesięć praktycznych wskazówek dotyczących bezpieczeństwa, dzięki którym programiści mogą zmniejszyć ryzyko i opracować bezpieczniejsze inteligentne kontrakty w łańcuchu BNB.
01
╱Definicja ╱
Ataki powtórkowe, znane również jako ataki powtórkowe i ataki powtórkowe, są powszechnym typem ataku w środowisku blockchain. W cyberbezpieczeństwie „atak polegający na powtórzeniu” to rodzaj ataku sieciowego, podczas którego ważna transmisja danych jest złośliwie lub oszukańczo powtarzana lub opóźniana.
W kontekście Web3 i inteligentnych kontraktów oznacza to ogólnie, że osoba atakująca może powtórzyć transakcję lub działanie w ramach inteligentnego kontraktu bez zgody pierwotnego użytkownika. Może to prowadzić do różnych form oszustw, takich jak podwójne wydatki itp.
Ataki te mogą mieć poważne konsekwencje dla użytkowników i programistów, ponieważ umożliwiają atakującym ponowne wykorzystanie tego samego podpisu w celu uzyskania nieautoryzowanego dostępu do wszystkich środków lub innych zasobów inteligentnej umowy.
Aby zapobiec atakom poprzez powtórzenie, programiści muszą dokładnie zaprojektować i wdrożyć swój inteligentny kod kontraktu oraz przestrzegać weryfikacji podpisów, a także najlepszych w branży standardów bezpieczeństwa.
02
╱ Analiza przypadku ╱
Poniższy fragment kodu reprezentuje proces realizacji transferu tokena w łańcuchu BNB. Kod jest podatny na ataki typu „replay”, co pozwala atakującemu na ponowne użycie tego samego podpisu.
W tej funkcji brakuje ochrony przed jednorazowym lub ponownym odtwarzaniem, co pozwala atakującemu na wielokrotne „odtworzenie” podpisanego transferu. Osoba atakująca może przechwycić podpisaną transakcję i wysłać ją ponownie do tej samej lub innej umowy, a umowa nadal uzna ją za ważną, więc osoba atakująca będzie mogła wykorzystać tę lukę w celu kradzieży zasobów.
03
╱ Metody doskonalenia ╱
Dodaj wartość jednorazową do podpisu lub użyj zmiennych mapujących, aby zarejestrować podpis. Bardziej szczegółowe rozwiązania będą się różnić w zależności od projektu.
01
╱Definicja ╱
Atak ponownego wejścia ma miejsce, gdy złośliwy kontrakt wielokrotnie wywołuje kontrakt podatny na ataki przed zakończeniem pierwszego wywołania. Innymi słowy, osoba atakująca może „oszukać” podatną na ataki umowę, myśląc, że zakończyła jedną transakcję i może przejść do następnej, ale w rzeczywistości nadal wykonuje złośliwy kod atakującego.
Może to spowodować, że osoba atakująca będzie mogła manipulować stanem umowy w nieoczekiwany sposób i potencjalnie uzyskać nieautoryzowane środki.
02
╱ Analiza przypadku ╱
W poniższym fragmencie kodu użytkownicy mogą wypłacić środki ze swojego konta, wywołując funkcję wypłaty i określając kwotę, którą chcą wypłacić. Ponieważ jednak funkcja wycofania nie chroni przed rekurencyjnymi wywołaniami tej funkcji, jest ona podatna na ataki polegające na ponownym wejściu.
Osoba atakująca może wykorzystać tę lukę, tworząc złośliwą umowę, która wielokrotnie wywołuje funkcję wypłaty, zanim saldo zostanie faktycznie pobrane z konta. Funkcja msg.sender.call wysyła środki do szkodliwego kontraktu, a osoba atakująca wykorzystuje funkcję otrzymywania() złośliwego kontraktu w celu wielokrotnego wypłacania środków, zanim ich saldo spadnie do zera, wyczerpując w ten sposób wszystkie środki kontraktu ofiary.
03
╱ Metody doskonalenia ╱
Aktualizuj status przed wykonaniem jakichkolwiek połączeń zewnętrznych.
Wzorzec ten nosi nazwę wzorca „Sprawdź-Efekty-Interakcja” i jest wzorcem projektowym używanym do zapobiegania atakom polegającym na ponownym wejściu w inteligentne kontrakty. Ten wzorzec oddziela zmiany stanu od wywołań zewnętrznych do innych kontraktów, najpierw sprawdzając warunki wstępne, a następnie aktualizując stan przed wykonaniem jakichkolwiek wywołań zewnętrznych. W ten sposób, jeśli wywołanie zewnętrzne wywoła wywołanie zwrotne, które będzie próbowało oddzwonić do kontraktu, ale stan został już zaktualizowany, zapobiega się innym nieoczekiwanym efektom.
Postępując zgodnie z tym wzorcem, programiści mogą zapewnić, że ich umowy będą bezpieczniejsze i mniej podatne na ataki typu reentranty.
Innym możliwym rozwiązaniem jest użycie modyfikatora w celu ograniczenia wielu wywołań tej samej funkcji, podobnie jak w przypadku ReentrancyGuard OpenZeppelin.
01
╱Definicja ╱
Wyrocznie mogą pomóc inteligentnym kontraktom w uzyskiwaniu informacji spoza łańcucha bloków. Zwykle cena zdecentralizowanej giełdy (DEX) jest ustalana na podstawie ceny ustalonej przez wyrocznię z ostatniej udanej transakcji na DEX.
Problem jednak w tym, że ceną każdy może łatwo manipulować, co powoduje problemy z inteligentnym kontraktem. Często widzimy przypadki manipulacji wyroczniami cenowymi za pomocą pożyczek flash. Powodem jest to, że pożyczki typu flash pozwalają użytkownikom pożyczyć ogromne kwoty pieniędzy bez zabezpieczenia, pod warunkiem, że spłacają pożyczkę w tym samym bloku. Ułatwia to atakującym wywieranie wpływu na ceny lub nawet manipulowanie nimi, czerpiąc zyski z fałszywych likwidacji, nadmiernego udzielania pożyczek lub nieuczciwego handlu.
02
╱ Analiza przypadku ╱
Poniżej znajduje się fragment kodu, który jest podatny na ataki manipulacyjne Oracle.
Ta umowa umożliwia użytkownikom wymianę tokena A na token B przy użyciu umowy routingu, ale opiera się na zewnętrznej wyroczni (umowie Uniswap Pair) w celu uzyskania rezerw tokena A i tokena B w celu obliczenia ceny. Osoba atakująca była w stanie zmanipulować rezerwy kontraktu Uniswap Pair, a także funkcję getAmountOut, co ostatecznie spowodowało wykonanie zamiany po nieuzasadnionej cenie.
03
╱ Metody doskonalenia ╱
Aby zapobiec temu atakowi, programiści powinni korzystać ze zdecentralizowanej sieci Oracle, która może uzyskać średnią cenę ważoną wolumenem (VWAP) lub średnią cenę ważoną w czasie (TWAP) scentralizowanych i zdecentralizowanych giełd w łańcuchu. W ten sposób dane będą zbierane z wielu źródeł i w szerokim przedziale czasu, dzięki czemu kod będzie mniej podatny na ataki i manipulacje. Dla programistów ważne jest, aby móc usuwać z inteligentnych kontraktów wszelkie wektory ataku manipulujące Oracle, aby zapobiec potencjalnym lukom w zabezpieczeniach.
01
╱Definicja ╱
Odpowiednie ustawienie widoczności funkcji zapewnia bezpieczeństwo i integralność inteligentnych kontraktów. Użycie nieprawidłowych ustawień widoczności funkcji może pozwolić niezamierzonym użytkownikom na manipulowanie stanem umowy, co może prowadzić do poważnych problemów, takich jak kradzież środków lub kontrola funkcjonalności umowy.
Ustawiając widoczność funkcji na prywatną lub wewnętrzną, masz pewność, że programiści mają ograniczony dostęp do niektórych funkcji i że tylko upoważniony personel może wywoływać te funkcje. Funkcje prywatne można wywoływać tylko z samego kontraktu, natomiast funkcje wewnętrzne można również wywoływać z bieżącego kontraktu. Dzięki temu programiści mogą tworzyć potężniejsze i bardziej złożone kontrakty, zachowując jednocześnie kontrolę nad dostępem do funkcjonalności.
02
╱Analiza przypadku╱
Funkcja setAdmin() pozwala każdemu ustawić dowolny adres jako administrator kontraktu. W zależności od przyznanych w ramach umowy uprawnień do zarządzania adresami, może to spowodować utratę przez dewelopera kontroli nad samą umową, a nawet utratę środków.
Ustawiając widoczność funkcji na wewnętrzną, niektóre funkcje kontraktu mogą wewnętrznie umożliwiać ustawienie określonych użytkowników jako administratorów.
03
╱ Metody doskonalenia ╱
Modyfikatory dostępu to ważna funkcja bezpieczeństwa, która decyduje o tym, kto może uzyskać dostęp do określonych funkcji lub zmiennych w kontrakcie. Modyfikatorów tych można używać do ograniczania widoczności niektórych funkcji lub zmiennych do określonych ról lub adresów oraz zapobiegania uzyskiwaniu przez złośliwych aktorów nieautoryzowanego dostępu lub manipulacji stanem kontraktu.
Na przykład kontrakt może mieć funkcję, którą może wywołać tylko właściciel kontraktu, lub zmienną, do której dostęp może uzyskać tylko określony zestaw adresów.
Dostęp do funkcji setAdmin można ograniczyć do adresu właściciela umowy, zmieniając modyfikator widoczności na zewnętrzny i ustawiając modyfikator dostępu na onlyOwner. Zapobiegnie to przejęciu kontroli przez złośliwe strony zewnętrzne nad niektórymi uprzywilejowanymi funkcjami.
Właściwe użycie modyfikatorów widoczności i restrykcyjnych może ułatwić zarządzanie kontraktem i ograniczyć typowe ataki, takie jak ponowne wejście (osoba atakująca wielokrotnie wywołuje funkcję w celu manipulowania stanem kontraktu) lub ataki front-running (osoba atakująca monitoruje oczekujące transakcje i manipuluje stanem kontraktu przed legalnym transakcje są realizowane).
Dzięki odpowiedniemu wykorzystaniu tych funkcji programiści mogą zwiększyć bezpieczeństwo i niezawodność swoich umów, zmniejszyć ryzyko nieautoryzowanego dostępu oraz poprawić ogólną jakość i łatwość konserwacji swojego kodu.
01
╱Definicja ╱
Podejmując decyzję o modernizacji umowy w przyszłości, ważne jest, aby na początku dokładnie rozważyć projekt umowy. Możliwość aktualizacji kontraktu odnosi się do właściwości polegającej na tym, że logikę inteligentnego kontraktu można modyfikować lub aktualizować po jego wdrożeniu w łańcuchu bloków. Chociaż możliwość aktualizacji może zapewnić wiele korzyści (takich jak naprawianie błędów, poprawa wydajności lub dodawanie nowych funkcji), wiąże się również z pewnymi zagrożeniami. Aktualizacje umów mogą wprowadzać nowe luki w zabezpieczeniach, zwiększać złożoność umowy lub powodować niezamierzone konsekwencje.
Możliwość aktualizacji umów powoduje również problemy z zaufaniem, ponieważ administratorzy agentów mogą aktualizować umowy bez konsensusu społeczności. Deweloperzy muszą dokładnie rozważyć zalety i wady możliwości aktualizacji i określić, czy wprowadzenie umów z możliwością aktualizacji jest naprawdę konieczne dla ich projektu. W niektórych przypadkach bezpieczniej jest zaprojektować umowę, która będzie niezmienna od początku, zamiast polegać na możliwości późniejszej modyfikacji.
02
╱ Metody doskonalenia ╱
Jeśli chodzi o możliwość aktualizacji umowy, należy przestrzegać kilku ważnych praktyk. Przede wszystkim nie modyfikuj biblioteki proxy. Biblioteka kontraktów proxy jest niezwykle złożona, szczególnie pod względem zarządzania pamięcią masową i mechanizmów aktualizacji. Nawet małe błędy mogą znacząco wpłynąć na działanie kontraktów proxy i logicznych. W rzeczywistości wiele krytycznych błędów związanych z proxy wykrytych podczas audytu było spowodowanych niewłaściwymi modyfikacjami biblioteki proxy.
Innym kluczowym aspektem możliwości rozbudowy umowy jest uwzględnienie „luki” w zakresie przechowywania w umowie podstawowej. Kontrakty logiczne muszą zawierać lukę w pamięci w kodzie kontraktu, aby uwzględnić nowe zmienne, które mogą zostać wprowadzone podczas wdrażania nowych implementacji logiki. Po dodaniu nowych zmiennych stanu aktualizacja rozmiaru „przerwy” staje się jeszcze ważniejsza. Taka praktyka gwarantuje, że przyszłe aktualizacje będą przebiegać sprawnie i bez problemów.
Na koniec należy unikać używania funkcji selfdestruct() lub wykonywania delegatall()/call() w przypadku niezaufanych kontraktów. Osoba atakująca może wykorzystać te funkcje do obalenia implementacji logiki lub wykonania logiki niestandardowej. Aby temu zapobiec, ważne jest, aby zweryfikować dane wprowadzone przez użytkownika! Nie zezwalaj kontraktom na wykonywanie delegatall()/call() na niezaufanych kontraktach. Ponadto nie zaleca się używania delegcall() w kontraktach logicznych, ponieważ zarządzanie układem pamięci w wielu kontraktach może być trudne. Postępując zgodnie z tymi praktykami, programiści mogą zminimalizować luki w zabezpieczeniach i ryzyko związane z aktualizacjami umów.
01
╱Definicja ╱
Front-running zawsze był uporczywym i trudnym do rozwiązania problemem, w którym użytkownicy mogą czerpać korzyści z opóźnienia pomiędzy przesłaniem transakcji a potwierdzeniem jej na blockchainie. To opóźnienie jest spowodowane przez mempool.
mempool to tymczasowy obszar przechowywania używany do przechowywania niepotwierdzonych transakcji, które zostały rozgłoszone w sieci. Wszystkie węzły w sieci utrzymują pulę pamięci, dzięki której każdy może zobaczyć oczekujące transakcje i potencjalnie przechwycić je i czerpać z nich zyski. Mempool zapewnia także górnikom możliwość zmiany układu transakcji w celu maksymalizacji zysków, tworząc tak zwaną wartość górniczą (lub maksymalną) wydobywalną (MEV).
02
╱ Analiza przypadku ╱
Poniżej znajduje się przykład funkcji licytacji na aukcji, która ma skłonność do wyprzedzania.
Ta funkcja umożliwia użytkownikom licytowanie na aukcjach, ale może być przedmiotem ataków typu front-running. Załóżmy, że złośliwy użytkownik monitoruje łańcuch bloków i widzi, że inny użytkownik złożył wysoką ofertę. Złośliwy użytkownik może szybko złożyć wyższą ofertę i zyskać pierwszeństwo, ostatecznie wygrywając aukcję.
W kolejnej wersji użytkownicy przesyłają nieznane ceny ofertowe, a oferty te są przechowywane w pliku mapowania. Kwoty ofertowe są szyfrowane do końca okresu licytacji.
03
╱ Metody doskonalenia ╱
Pod koniec okresu licytacji użytkownicy mogą ujawnić swoją ofertę, podając pierwotną kwotę oferty i tajną wartość. Umowa sprawdza, czy kwota oferty i tajny skrót odpowiadają przechowywanej tajnej ofercie, zapewniając, że oferta została złożona przed końcem okresu aukcji. Jeżeli ta oferta jest wyższa niż aktualna oferta maksymalna, staje się nową ofertą maksymalną. Ta funkcja łagodzi ataki typu front-running, maskując kwoty ofert do końca okresu aukcji.
Front-running i MEV stały się głównymi problemami społeczności blockchain i zaproponowano różne rozwiązania, takie jak transakcje i usługi uczciwego zamawiania (FSS), aby rozwiązać te problemy. Transakcje mogą pomóc w zapobieganiu front-runningowi, ukrywając szczegóły transakcji przed innymi użytkownikami do czasu wykonania transakcji w łańcuchu bloków. Z drugiej strony FSS może zmniejszyć wpływ front-runningu i MEV poprzez bezpieczne zamawianie transakcji poza łańcuchem.
Posiadanie jasnego i kompleksowego planu reagowania ma kluczowe znaczenie w radzeniu sobie z awaryjnymi incydentami związanymi z bezpieczeństwem. Plan powinien być regularnie przeglądany, aktualizowany i testowany pod kątem skuteczności. Kiedy pojawia się zagrożenie bezpieczeństwa, czas odgrywa kluczową rolę. Dlatego plan powinien być dostosowany z wyprzedzeniem i zawierać szczegółowe etapy operacyjne służące identyfikacji, kontroli i łagodzeniu skutków.
Należy skutecznie wdrożyć plan, aby informować wszystkie zainteresowane strony. Jednocześnie ważne jest również regularne tworzenie kopii zapasowych danych, aby zapobiec ich utracie. Plan musi określać proces odzyskiwania danych i systemów do poprzedniego stanu. Członkowie zespołu powinni przechodzić systematyczne szkolenia w zakresie planu, aby upewnić się, że wszyscy rozumieją swoje role i obowiązki.
Dobrze przygotowany plan reakcji może nie rozwiązać problemu, ale może zminimalizować skutki incydentu i utrzymać zaufanie użytkowników i interesariuszy.
Regularne audyty kodu mają kluczowe znaczenie dla utrzymania bezpieczeństwa aplikacji. Współpraca z profesjonalnym audytorem specjalizującym się w inteligentnych zabezpieczeniach kontraktów to ważny krok w procesie rozwoju. Audytorzy sprawdzą kod pod kątem luk i przedstawią zalecenia dotyczące poprawy ogólnego bezpieczeństwa.
Ustalanie priorytetów i rozwiązywanie zidentyfikowanych problemów oraz utrzymywanie otwartej komunikacji z audytorami mają kluczowe znaczenie dla poprawy bezpieczeństwa.
Oprócz tego kluczowa jest także komunikacja z audytorami. Audytorzy mogą szczegółowo wyjaśnić wykryte problemy i luki oraz zapewnić wskazówki i praktyczną pomoc dotyczącą sposobu usunięcia danej luki. Dzięki współpracy z profesjonalnymi agencjami/personelem audytorskim bezpieczeństwo zostanie „przeniesione na wyższy poziom”.
Dla deweloperów sieci BNB przeprowadzanie regularnych audytów jest integralną częścią każdej kompleksowej strategii bezpieczeństwa. Proaktywne identyfikowanie i rozwiązywanie luk w kodzie może zminimalizować ryzyko naruszeń bezpieczeństwa.
Korzystanie z programu nagród to skuteczny sposób na zachęcenie hakerów pracujących w białych kapeluszach do zgłaszania luk w zabezpieczeniach kodu projektu. Zapewniając zachęty, takie jak tokeny lub inne nagrody, każdy projekt może zachęcić doświadczone osoby do przejrzenia kodu i zgłoszenia wszelkich potencjalnych problemów, które wykryją.
Ważne jest, aby mieć jasny i przejrzysty program nagród za błędy. Plan musi obejmować: jakie rodzaje wykrytych luk kwalifikują się do nagrody, w jaki sposób ocenić wartość tych luk itp. Jednocześnie włączenie renomowanej strony trzeciej do programu nagród za błędy może pomóc w zapewnieniu sprawnego działania programu i sprawiedliwego podziału nagród.
Jednocześnie ważne jest, aby mieć zróżnicowaną „grupę łowców nagród”. Różni hakerzy w białych kapeluszach mają różne obszary specjalizacji i mogą skupić się na wyszukiwaniu problemów, które inni mogą przeoczyć.
Wreszcie, po zgłoszeniu luk w zabezpieczeniach należy szybko i skutecznie podjąć działania, aby je usunąć. Programy nagród mogą być skutecznym narzędziem do identyfikowania luk w zabezpieczeniach, ale mają sens tylko wtedy, gdy zespół programistów faktycznie naprawi problem.
Edukacja użytkowników Web3 na temat bezpieczeństwa jest kluczowym krokiem w budowaniu bezpiecznego ekosystemu. Zapewnienie bezpieczeństwa klientom pomaga zapewnić bezpieczeństwo platformy. Użytkownicy powinni być edukowani w zakresie najlepszych praktyk w zakresie ochrony swoich kont i poufnych informacji.
Najważniejszą częścią jest nauczenie się, jak unikać oszustw typu phishing.
Oszuści wyłudzający informacje nakłaniają użytkowników do ujawnienia kluczy prywatnych lub haseł, podszywając się pod legalną witrynę lub usługę. CertiK zaleca, aby użytkownicy zawsze dwukrotnie sprawdzali adresy e-mail, źródła itp. adresy URL witryn używanych podczas otrzymywania jakichkolwiek informacji i nigdy nie wprowadzali kluczy prywatnych ani haseł na niezaufanych stronach internetowych.
Kolejną ważną częścią jest posiadanie bezpiecznych i silnych haseł. CertiK niniejszym zaleca, aby użytkownicy używali unikalnych i złożonych haseł do każdego konta i unikali ponownego używania haseł w różnych usługach. Ponadto hasła powinny być bezpiecznie przechowywane przy użyciu menedżera haseł lub innego mechanizmu bezpiecznego przechowywania.
Wreszcie ochrona kluczy prywatnych jest niezwykle ważna. Klucz prywatny jest równoznaczny z hasłem użytkownika i należy zagwarantować, że nikt inny nie będzie miał do niego dostępu w żadnym momencie. Użytkownicy powinni unikać udostępniania nikomu swoich kluczy prywatnych i przechowywać je w bezpiecznym miejscu.
Streszczać
Deweloperzy tworzący inteligentne kontrakty i aplikacje dApp w BNB Chain muszą zastosować kompleksowe podejście do bezpieczeństwa, aby zapewnić bezpieczeństwo środków i aktywów swoich użytkowników. W przypadku naruszeń bezpieczeństwa ważniejsze jest zachowanie proaktywności, a nie reagowania, posiadanie planu w momencie wystąpienia naruszenia lub nawet przed jego wystąpieniem oraz zapewnienie odpowiedniej edukacji w zakresie bezpieczeństwa wszystkim odpowiednim użytkownikom i zainteresowanym stronom. Łącząc wszystkie powyższe środki, projekty mogą znacznie zmniejszyć ryzyko naruszeń bezpieczeństwa i ataków hakerskich.
