Jak działa ta kontrola
Scanaris wysyła żądanie POST z najmniejszym możliwym zapytaniem introspekcji, {__schema{queryType{name}}}, na trzy ścieżki, pod którymi zwykle mieszka endpoint GraphQL: /graphql, /api/graphql i /v1/graphql. Jeśli któraś odpowiada 200, a treść zawiera __schema lub queryType, introspekcja jest włączona i otwiera ustalenie o średniej wadze ze ścieżką. Jeśli na Twojej stronie nie ma GraphQL, żadna ścieżka tak nie odpowiada i nie ma ustalenia. Zapytanie jest tylko do odczytu, nie dotyka danych i podlega tym samym limitom czasu i rozmiaru co reszta skanu.
Dlaczego to ważne
Introspekcja to funkcja GraphQL, która pozwala zapytać API o jego własny schemat: wszystkie typy, wszystkie pola każdego typu, wszystkie dostępne zapytania i mutacje wraz z argumentami. W fazie rozwoju jest niezbędna: korzystają z niej playground, autouzupełnianie w edytorze i generatory kodu. Na produkcji, otwarta dla każdego, to kompletna mapa Twojego backendu. Atakujący widzi, że istnieje mutacja deleteUser(id) albo pole internalNotes, nie musząc zgadywać, i od razu sprawdza, czy autoryzacja każdego z nich jest zrobiona dobrze. Dlatego waga średnia: sama nie ujawnia danych, ale sprawia, że każdą inną lukę w uprawnieniach znajduje się trywialnie.
Jak ją wyłączyć na produkcji
- Apollo Server:
introspection: "production" !== 'production'przy tworzeniu serwera. Od Apollo 4 jest już wyłączona, gdyNODE_ENVtoproduction; jeśli widzisz ją włączoną, sprawdź, czy ta zmienna rzeczywiście dociera do wdrożenia. Wyłącz też landing page lub playground na produkcji. - GraphQL Yoga i Envelop: wtyczka
useDisableIntrospection()z@envelop/disable-introspection, uzależniona od środowiska. - Hasura (ścieżka /v1/graphql): w ustawieniach bezpieczeństwa projektu jest kontrola introspekcji per rola (Cloud i Enterprise). Upewnij się też, że rola publiczna ma minimalne uprawnienia, a sekret administratora nigdy nie trafia do przeglądarki.
- graphql-ruby:
disable_introspection_entry_pointsw klasie schematu. - Python (Graphene, Strawberry, Ariadne): dodaj regułę
NoSchemaIntrospectionCustomRulezgraphql-coredo reguł walidacji na produkcji. - .NET (Hot Chocolate):
.AllowIntrospection(false)albo opcja sterowania introspekcją per żądanie na podstawie nagłówka lub roli.
Wyłączenie introspekcji nie zastępuje autoryzacji: każde zapytanie i mutacja muszą sprawdzać, kto pyta. Dołóż limity głębokości i złożoności zapytań (zapobiegają zagnieżdżonym zapytaniom, które kładą serwer), a jeśli Twój serwer to oferuje, wyłącz też podpowiedzi pól („Did you mean…"), które zdradzają nazwy nawet przy zamkniętej introspekcji.
Sprawdź, czy naprawione
curl -s -X POST https://twojadomena.pl/graphql -H "Content-Type: application/json" -d '{"query":"{__schema{queryType{name}}}"}'
Powtórz z /api/graphql i /v1/graphql. Oczekiwane: błąd typu „introspection is not allowed", 400 lub 403, albo 404, jeśli nie ma tam GraphQL. Jeśli widzisz "queryType":{"name":"Query"}, nadal jest otwarta.
Często zadawane pytania
Moje API jest publiczne i udokumentowane. Czy to mnie dotyczy?
Jeśli publikujesz schemat celowo, otwarta introspekcja nie ujawnia nic nowego i możesz oznaczyć ustalenie jako zaakceptowane. Większość API aplikacji nie jest w tej sytuacji: mają wewnętrzne mutacje, o których nikt nie powinien wiedzieć.
Mój endpoint jest pod inną ścieżką. Nie jest sprawdzany?
Testowane są tylko trzy najczęstsze ścieżki. Jeśli Twój mieszka gdzie indziej, uruchom powyższy test ze swoją prawdziwą ścieżką. Innych paneli i endpointów deweloperskich, które nie powinny odpowiadać na produkcji, szuka wystawione endpointy.
A jeśli endpoint wymaga uwierzytelniania?
Wtedy introspekcja odpowiada 401 i nie jest oznaczana. To prawidłowa sytuacja: atakujący bez sesji nie dostaje schematu. Sprawdź, czy nagłówek CORS API nie jest otwarty dla dowolnego źródła; na to patrzy zbyt liberalny CORS.