Race Condition
Last updated
Last updated
Użyj Trickest, aby łatwo budować i automatyzować przepływy pracy zasilane przez najbardziej zaawansowane narzędzia społecznościowe na świecie. Uzyskaj dostęp już dziś:
Aby uzyskać głębokie zrozumienie tej techniki, sprawdź oryginalny raport w https://portswigger.net/research/smashing-the-state-machine
Główną przeszkodą w wykorzystaniu warunków wyścigu jest upewnienie się, że wiele żądań jest obsługiwanych jednocześnie, z bardzo małą różnicą w czasie ich przetwarzania—idealnie, mniej niż 1ms.
Tutaj znajdziesz kilka technik synchronizacji żądań:
HTTP/2: Obsługuje wysyłanie dwóch żądań przez jedno połączenie TCP, zmniejszając wpływ jittera sieciowego. Jednak z powodu różnic po stronie serwera, dwa żądania mogą nie wystarczyć do spójnego wykorzystania warunków wyścigu.
HTTP/1.1 'Synchronizacja Ostatniego Bajtu': Umożliwia wstępne wysyłanie większości części 20-30 żądań, wstrzymując mały fragment, który jest następnie wysyłany razem, osiągając jednoczesne dotarcie do serwera.
Przygotowanie do Synchronizacji Ostatniego Bajtu obejmuje:
Wysyłanie nagłówków i danych ciała bez ostatniego bajtu bez kończenia strumienia.
Wstrzymanie na 100ms po początkowym wysłaniu.
Wyłączenie TCP_NODELAY, aby wykorzystać algorytm Nagle'a do grupowania ostatnich ramek.
Pingowanie w celu rozgrzania połączenia.
Następne wysłanie wstrzymanych ramek powinno skutkować ich dotarciem w jednym pakiecie, co można zweryfikować za pomocą Wireshark. Ta metoda nie dotyczy plików statycznych, które zazwyczaj nie są zaangażowane w ataki RC.
Zrozumienie architektury celu jest kluczowe. Serwery front-end mogą różnie kierować żądania, co wpływa na czas. Prewencyjne rozgrzewanie połączeń po stronie serwera, poprzez nieistotne żądania, może znormalizować czas żądań.
Frameworki takie jak handler sesji PHP serializują żądania według sesji, co może zaciemniać luki. Wykorzystanie różnych tokenów sesji dla każdego żądania może obejść ten problem.
Jeśli rozgrzewanie połączeń jest nieskuteczne, celowe wywołanie opóźnień ograniczeń częstotliwości lub zasobów serwerów WWW poprzez zalewanie ich fałszywymi żądaniami może ułatwić atak jednopakietowy, wywołując opóźnienie po stronie serwera sprzyjające warunkom wyścigu.
Tubo Intruder - atak jednopakietowy HTTP2 (1 punkt końcowy): Możesz wysłać żądanie do Turbo intruder (Extensions
-> Turbo Intruder
-> Send to Turbo Intruder
), możesz zmienić w żądaniu wartość, którą chcesz złamać dla %s
jak w csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s
i następnie wybrać examples/race-single-packer-attack.py
z rozwijanej listy:
Jeśli zamierzasz wysłać różne wartości, możesz zmodyfikować kod tym, który używa listy słów z schowka:
Jeśli strona internetowa nie obsługuje HTTP2 (tylko HTTP1.1), użyj Engine.THREADED
lub Engine.BURP
zamiast Engine.BURP2
.
Tubo Intruder - atak pojedynczym pakietem HTTP2 (Kilka punktów końcowych): W przypadku, gdy musisz wysłać żądanie do 1 punktu końcowego, a następnie wiele do innych punktów końcowych, aby wywołać RCE, możesz zmienić skrypt race-single-packet-attack.py
na coś takiego:
Jest również dostępne w Repeater za pomocą nowej opcji 'Wyślij grupę równolegle' w Burp Suite.
Dla limit-overrun możesz po prostu dodać ten sam żądanie 50 razy w grupie.
Dla connection warming możesz dodać na początku grupy kilka żądań do nie statycznej części serwera webowego.
Aby opóźnić proces między przetwarzaniem jednego żądania a drugim w 2 krokach substanu, możesz dodać dodatkowe żądania między obydwoma żądaniami.
Dla multi-endpoint RC możesz zacząć wysyłać żądanie, które przechodzi do ukrytego stanu, a następnie 50 żądań tuż po nim, które wykorzystują ukryty stan.
Zautomatyzowany skrypt python: Celem tego skryptu jest zmiana adresu e-mail użytkownika, jednocześnie weryfikując go, aż token weryfikacyjny nowego e-maila dotrze do ostatniego e-maila (to dlatego, że w kodzie widziano RC, gdzie możliwe było modyfikowanie e-maila, ale weryfikacja była wysyłana na stary, ponieważ zmienna wskazująca e-mail była już wypełniona pierwszym). Gdy słowo "objetivo" zostanie znalezione w otrzymanych e-mailach, wiemy, że otrzymaliśmy token weryfikacyjny zmienionego e-maila i kończymy atak.
W oryginalnych badaniach wyjaśniono, że atak ten ma limit 1,500 bajtów. Jednak w tym poście wyjaśniono, jak możliwe jest rozszerzenie ograniczenia 1,500 bajtów ataku pojedynczego pakietu do 65,535 B ograniczenia okna TCP poprzez użycie fragmentacji na poziomie IP (dzielenie pojedynczego pakietu na wiele pakietów IP) i wysyłanie ich w różnej kolejności, co pozwala na zapobieżenie ponownemu złożeniu pakietu, aż wszystkie fragmenty dotrą do serwera. Ta technika pozwoliła badaczowi na wysłanie 10,000 żądań w około 166 ms.
Zauważ, że chociaż ta poprawa sprawia, że atak jest bardziej niezawodny w RC, który wymaga, aby setki/tysiące pakietów dotarły w tym samym czasie, może również mieć pewne ograniczenia programowe. Niektóre popularne serwery HTTP, takie jak Apache, Nginx i Go, mają surowe ustawienie SETTINGS_MAX_CONCURRENT_STREAMS
na 100, 128 i 250. Jednak inne, takie jak NodeJS i nghttp2, mają to ustawienie nieograniczone.
To zasadniczo oznacza, że Apache weźmie pod uwagę tylko 100 połączeń HTTP z jednego połączenia TCP (ograniczając ten atak RC).
Możesz znaleźć kilka przykładów używających tej techniki w repozytorium https://github.com/Ry0taK/first-sequence-sync/tree/main.
Przed wcześniejszymi badaniami używano kilku ładunków, które po prostu próbowały wysłać pakiety tak szybko, jak to możliwe, aby spowodować RC.
Repeater: Sprawdź przykłady z poprzedniej sekcji.
Intruder: Wyślij żądanie do Intruder, ustaw liczbę wątków na 30 w menu Opcje i wybierz jako ładunek Null payloads i wygeneruj 30.
Turbo Intruder
Python - asyncio
To jest najprostszy typ warunków wyścigu, gdzie luki pojawiają się w miejscach, które ograniczają liczbę razy, kiedy możesz wykonać akcję. Na przykład używanie tego samego kodu rabatowego w sklepie internetowym kilka razy. Bardzo łatwy przykład można znaleźć w tym raporcie lub w tym błędzie.
Istnieje wiele wariantów tego rodzaju ataku, w tym:
Wykorzystywanie karty podarunkowej wiele razy
Ocena produktu wiele razy
Wypłacanie lub transferowanie gotówki przekraczającej saldo konta
Ponowne użycie jednego rozwiązania CAPTCHA
Ominięcie limitu szybkości anty-brute-force
Wykorzystywanie złożonych warunków wyścigu często polega na wykorzystaniu krótkich okazji do interakcji z ukrytymi lub niezamierzonymi podstanami maszyny. Oto jak podejść do tego:
Zidentyfikuj potencjalne ukryte podstany
Zacznij od wskazania punktów końcowych, które modyfikują lub interagują z krytycznymi danymi, takimi jak profile użytkowników lub procesy resetowania hasła. Skup się na:
Przechowywaniu: Preferuj punkty końcowe, które manipulują danymi trwałymi po stronie serwera, zamiast tych obsługujących dane po stronie klienta.
Akcji: Szukaj operacji, które zmieniają istniejące dane, które są bardziej prawdopodobne do stworzenia warunków do wykorzystania w porównaniu do tych, które dodają nowe dane.
Kluczowaniu: Udane ataki zazwyczaj obejmują operacje kluczowane na tym samym identyfikatorze, np. nazwa użytkownika lub token resetowania.
Przeprowadź wstępne badania
Testuj zidentyfikowane punkty końcowe za pomocą ataków warunków wyścigu, obserwując wszelkie odchylenia od oczekiwanych wyników. Nieoczekiwane odpowiedzi lub zmiany w zachowaniu aplikacji mogą sygnalizować lukę.
Zademonstruj lukę
Zawęż atak do minimalnej liczby żądań potrzebnych do wykorzystania luki, często tylko dwóch. Ten krok może wymagać wielu prób lub automatyzacji z powodu precyzyjnego czasu.
Precyzja w czasowaniu żądań może ujawnić luki, szczególnie gdy przewidywalne metody, takie jak znaczniki czasu, są używane do tokenów zabezpieczających. Na przykład generowanie tokenów resetowania hasła na podstawie znaczników czasu może pozwolić na identyczne tokeny dla równoczesnych żądań.
Aby wykorzystać:
Użyj precyzyjnego czasowania, jak atak jednego pakietu, aby złożyć równoczesne żądania resetowania hasła. Identyczne tokeny wskazują na lukę.
Przykład:
Zażądaj dwóch tokenów resetowania hasła w tym samym czasie i porównaj je. Pasujące tokeny sugerują błąd w generowaniu tokenów.
Sprawdź to PortSwigger Lab aby to wypróbować.
Sprawdź to PortSwigger Lab, aby zobaczyć, jak zapłacić w sklepie i dodać dodatkowy przedmiot, za który nie będziesz musiał płacić.
Pomysł polega na zweryfikowaniu adresu e-mail i jednoczesnej zmianie go na inny, aby sprawdzić, czy platforma weryfikuje nowy zmieniony adres.
Zgodnie z tym badaniem Gitlab był podatny na przejęcie w ten sposób, ponieważ mógł wysłać token weryfikacji e-maila jednego e-maila do drugiego e-maila.
Sprawdź to PortSwigger Lab aby to wypróbować.
Jeśli używane są 2 różne zapisy, aby dodać informacje do bazy danych, istnieje krótki okres czasu, w którym tylko pierwsze dane zostały zapisane w bazie danych. Na przykład, podczas tworzenia użytkownika nazwa użytkownika i hasło mogą być zapisane, a następnie token do potwierdzenia nowo utworzonego konta jest zapisywany. Oznacza to, że przez krótki czas token do potwierdzenia konta jest pusty.
Dlatego rejestrowanie konta i wysyłanie kilku żądań z pustym tokenem (token=
lub token[]=
lub jakakolwiek inna wariacja) w celu natychmiastowego potwierdzenia konta mogłoby pozwolić na potwierdzenie konta, nad którym nie masz kontroli nad e-mailem.
Sprawdź to PortSwigger Lab aby to wypróbować.
Poniższy pseudokod jest podatny na warunki wyścigu, ponieważ w bardzo krótkim czasie 2FA nie jest egzekwowane, podczas gdy sesja jest tworzona:
Istnieje kilka dostawców OAUth. Te usługi pozwolą Ci stworzyć aplikację i uwierzytelnić użytkowników, których dostawca zarejestrował. Aby to zrobić, klient będzie musiał zezwolić Twojej aplikacji na dostęp do niektórych swoich danych w ramach dostawcy OAUth. Do tego momentu to tylko zwykłe logowanie za pomocą google/linkedin/github... gdzie pojawia się strona z komunikatem: "Aplikacja <InsertCoolName> chce uzyskać dostęp do Twoich informacji, czy chcesz to umożliwić?"
authorization_code
Problem pojawia się, gdy zaakceptujesz to i automatycznie wysyła authorization_code
do złośliwej aplikacji. Następnie ta aplikacja nadużywa Warunku Wyścigu w dostawcy usługi OAUth, aby wygenerować więcej niż jeden AT/RT (Token Uwierzytelniający/Token Odświeżający) z authorization_code
dla Twojego konta. W zasadzie nadużyje faktu, że zaakceptowałeś aplikację, aby uzyskać dostęp do swoich danych, aby utworzyć kilka kont. Następnie, jeśli przestaniesz zezwalać aplikacji na dostęp do swoich danych, jedna para AT/RT zostanie usunięta, ale pozostałe będą nadal ważne.
Refresh Token
Gdy uzyskasz ważny RT, możesz spróbować nadużyć go, aby wygenerować kilka AT/RT i nawet jeśli użytkownik anuluje uprawnienia dla złośliwej aplikacji do uzyskania dostępu do jego danych, kilka RT nadal będzie ważnych.
W WS_RaceCondition_PoC możesz znaleźć PoC w Javie do wysyłania wiadomości websocket w równoległych w celu nadużycia Warunków Wyścigu również w Web Sockets.
Użyj Trickest, aby łatwo budować i automatyzować przepływy pracy zasilane przez najbardziej zaawansowane narzędzia społecznościowe na świecie. Uzyskaj dostęp już dziś:
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)