Zanieczyszczenie parametrów | Wstrzykiwanie JSON

Reading time: 8 minutes

Zanieczyszczenie parametrów

tip

Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Wsparcie HackTricks

Przegląd HTTP Parameter Pollution (HPP)

HTTP Parameter Pollution (HPP) to technika, w której atakujący manipulują parametrami HTTP, aby zmienić zachowanie aplikacji internetowej w niezamierzony sposób. Manipulacja ta polega na dodawaniu, modyfikowaniu lub duplikowaniu parametrów HTTP. Efekt tych manipulacji nie jest bezpośrednio widoczny dla użytkownika, ale może znacząco zmienić funkcjonalność aplikacji po stronie serwera, z zauważalnymi skutkami po stronie klienta.

Przykład HTTP Parameter Pollution (HPP)

URL transakcji aplikacji bankowej:

  • Oryginalny URL: https://www.victim.com/send/?from=accountA&to=accountB&amount=10000

Wstawiając dodatkowy parametr from:

  • Manipulowany URL: https://www.victim.com/send/?from=accountA&to=accountB&amount=10000&from=accountC

Transakcja może być błędnie obciążona na accountC zamiast accountA, co pokazuje potencjał HPP do manipulacji transakcjami lub innymi funkcjonalnościami, takimi jak resetowanie hasła, ustawienia 2FA czy żądania kluczy API.

Specyficzne dla technologii parsowanie parametrów

  • Sposób, w jaki parametry są analizowane i priorytetowane, zależy od używanej technologii internetowej, co wpływa na to, jak HPP może być wykorzystywane.
  • Narzędzia takie jak Wappalyzer pomagają zidentyfikować te technologie i ich zachowania w zakresie parsowania.

Wykorzystanie HPP w PHP

Przypadek manipulacji OTP:

  • Kontekst: Mechanizm logowania wymagający jednorazowego hasła (OTP) został wykorzystany.
  • Metoda: Poprzez przechwycenie żądania OTP za pomocą narzędzi takich jak Burp Suite, atakujący zduplikował parametr email w żądaniu HTTP.
  • Wynik: OTP, przeznaczone dla początkowego adresu e-mail, zostało zamiast tego wysłane na drugi adres e-mail podany w manipulowanym żądaniu. Ta luka umożliwiła nieautoryzowany dostęp, omijając zamierzony środek bezpieczeństwa.

Scenariusz ten podkreśla krytyczne niedopatrzenie w backendzie aplikacji, który przetwarzał pierwszy parametr email do generacji OTP, ale używał ostatniego do dostarczenia.

Przypadek manipulacji kluczem API:

  • Scenariusz: Aplikacja pozwala użytkownikom na aktualizację swojego klucza API za pośrednictwem strony ustawień profilu.
  • Wektor ataku: Atakujący odkrywa, że dodając dodatkowy parametr api_key do żądania POST, może manipulować wynikiem funkcji aktualizacji klucza API.
  • Technika: Wykorzystując narzędzie takie jak Burp Suite, atakujący tworzy żądanie, które zawiera dwa parametry api_key: jeden prawidłowy i jeden złośliwy. Serwer, przetwarzając tylko ostatnie wystąpienie, aktualizuje klucz API na wartość podaną przez atakującego.
  • Wynik: Atakujący zyskuje kontrolę nad funkcjonalnością API ofiary, potencjalnie uzyskując dostęp do prywatnych danych w sposób nieautoryzowany.

Ten przykład dodatkowo podkreśla konieczność bezpiecznego zarządzania parametrami, szczególnie w funkcjach tak krytycznych jak zarządzanie kluczem API.

Parsowanie parametrów: Flask vs. PHP

Sposób, w jaki technologie internetowe obsługują duplikaty parametrów HTTP, różni się, co wpływa na ich podatność na ataki HPP:

  • Flask: Przyjmuje wartość pierwszego napotkanego parametru, takiego jak a=1 w ciągu zapytania a=1&a=2, priorytetując początkową instancję nad kolejnymi duplikatami.
  • PHP (na serwerze Apache HTTP): Przeciwnie, priorytetowo traktuje ostatnią wartość parametru, wybierając a=2 w podanym przykładzie. To zachowanie może niezamierzenie ułatwić wykorzystanie HPP, honorując złośliwy parametr atakującego zamiast oryginalnego.

Zanieczyszczenie parametrów według technologii

Wyniki zostały zaczerpnięte z https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89

PHP 8.3.11 I Apache 2.4.62

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*l_Pf2JNCYhmfAvfk7UTEbQ.jpeg

  1. Ignoruj wszystko po %00 w nazwie parametru.
  2. Obsługuj name[] jako tablicę.
  3. _GET nie oznacza metody GET.
  4. Preferuj ostatni parametr.

Ruby 3.3.5 i WEBrick 1.8.2

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*kKxtZ8qEmgTIMS81py5hhg.jpeg

  1. Używa & i ; jako separatorów do dzielenia parametrów.
  2. Nie rozpoznaje name[].
  3. Preferuje pierwszy parametr.

Spring MVC 6.0.23 I Apache Tomcat 10.1.30

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*llG22MF1gPTYZYFVCmCiVw.jpeg

  1. POST RequestMapping == PostMapping & GET RequestMapping == GetMapping.
  2. POST RequestMapping & PostMapping rozpoznaje name[].
  3. Preferuj name, jeśli name i name[] istnieją.
  4. Łącz parametry, np. first,last.
  5. POST RequestMapping & PostMapping rozpoznaje parametr zapytania z Content-Type.

NodeJS 20.17.0 I Express 4.21.0

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*JzNkLOSW7orcHXswtMHGMA.jpeg

  1. Rozpoznaje name[].
  2. Łącz parametry, np. first,last.

GO 1.22.7

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*NVvN1N8sL4g_Gi796FzlZA.jpeg

  1. NIE rozpoznaje name[].
  2. Preferuj pierwszy parametr.

Python 3.12.6 I Werkzeug 3.0.4 I Flask 3.0.3

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*Se5467PFFjIlmT3O7KNlWQ.jpeg

  1. NIE rozpoznaje name[].
  2. Preferuj pierwszy parametr.

Python 3.12.6 I Django 4.2.15

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rf38VXut5YhAx0ZhUzgT8Q.jpeg

  1. NIE rozpoznaje name[].
  2. Preferuj ostatni parametr.

Python 3.12.6 I Tornado 6.4.1

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*obCn7xahDc296JZccXM2qQ.jpeg

  1. NIE rozpoznaje name[].
  2. Preferuj ostatni parametr.

Wstrzykiwanie JSON

Duplikaty kluczy

ini
obj = {"test": "user", "test": "admin"}

Frontend może uwierzyć w pierwsze wystąpienie, podczas gdy backend używa drugiego wystąpienia klucza.

Kolizja kluczy: Skracanie znaków i komentarze

Niektóre znaki nie będą poprawnie interpretowane przez frontend, ale backend je zinterpretuje i użyje tych kluczy, co może być przydatne do obejścia pewnych ograniczeń:

json
{"test": 1, "test\[raw \x0d byte]": 2} {"test": 1, "test\ud800": 2} {"test": 1, "test"": 2} {"test": 1, "te\st": 2}

Zauważ, że w tych przypadkach frontend może myśleć, że test == 1, a backend będzie myślał, że test == 2.

Może to być również użyte do obejścia ograniczeń wartości, takich jak:

json
{"role": "administrator\[raw \x0d byte]"} {"role":"administrator\ud800"} {"role": "administrator""} {"role": "admini\strator"}

Używanie skracania komentarzy

ini
obj = {"description": "Duplicate with comments", "test": 2, "extra": /*, "test": 1, "extra2": */}

Tutaj użyjemy serializatora z każdego parsera, aby zobaczyć jego odpowiedni wynik.

Serializer 1 (np. biblioteka GoJay w GoLang) wygeneruje:

  • description = "Duplicate with comments"
  • test = 2
  • extra = ""

Serializer 2 (np. biblioteka JSON-iterator w Javie) wygeneruje:

  • description = "Duplicate with comments"
  • extra = "/*"
  • extra2 = "*/"
  • test = 1

Alternatywnie, proste użycie komentarzy może być również skuteczne:

ini
obj = {"description": "Comment support", "test": 1, "extra": "a"/*, "test": 2, "extra2": "b"*/}

Biblioteka GSON w Javie:

json
{ "description": "Comment support", "test": 1, "extra": "a" }

Biblioteka simdjson w Ruby:

json
{ "description": "Comment support", "test": 2, "extra": "a", "extra2": "b" }

Niespójna Precedencja: Deserializacja vs. Serializacja

ini
obj = {"test": 1, "test": 2} obj["test"] // 1 obj.toString() // {"test": 2}

Float i Integer

Liczba

undefined
999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999

może być dekodowane do wielu reprezentacji, w tym:

undefined
999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 9.999999999999999e95 1E+96 0 9223372036854775807

Co może stworzyć niespójności

Referencje

tip

Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Wsparcie HackTricks