Przejdź do treści
INDEKS ANALIZ BREACHROAD / NOTA TECHNICZNA

Izolacja tenantów SaaS: techniczny pentest

Jak testować izolację tenantów SaaS w API, bazie, cache, kolejkach, storage i panelu administracyjnym. Metodyka pentestu bez ryzyka wycieku danych.

MATERIAŁ PUBLICZNY
AUTOR
/ CEO Breachroad · OSCP · PNPT
PUBLIKACJA
8 kwietnia 2026
CZAS CZYTANIA
18 min czytania
TEMAT
Pentest i AppSec
Izolacja tenantów SaaS: techniczny pentest

Pentest izolacji tenantów SaaS odpowiada na jedno krytyczne pytanie: czy użytkownik, integracja albo proces działający dla organizacji A może odczytać, zmienić lub pośrednio wpłynąć na dane organizacji B? Odpowiedź wymaga znacznie więcej niż podmiany identyfikatora w jednym żądaniu API. Granica tenanta przebiega przez tokeny, warstwę autoryzacji, zapytania do bazy, cache, kolejki, wyszukiwarkę, pliki, eksporty, analitykę, zadania asynchroniczne i narzędzia wsparcia.

Najbezpieczniejszy test wykorzystuje dwa lub więcej kontrolowanych tenantów, syntetyczne dane i macierz dozwolonych relacji. Tester sprawdza każdą granicę negatywnie, ale nie pobiera danych prawdziwych klientów i nie próbuje obciążać współdzielonej infrastruktury. Wynikiem powinien być dowód naruszenia izolacji oparty na znacznikach testowych, opis warunku technicznego oraz poprawka możliwa do wdrożenia na właściwej warstwie.

Co naprawdę oznacza izolacja tenantów?

Tenant jest domeną administracyjną klienta SaaS: organizacją, workspace’em, kontem biznesowym lub projektem. Użytkownik może należeć do kilku tenantów i mieć w każdym inną rolę. Sam fakt poprawnego uwierzytelnienia nie daje prawa do zasobu. Decyzja autoryzacyjna musi uwzględniać co najmniej tożsamość podmiotu, aktywny tenant, akcję, zasób i relację zasobu z tenantem.

Praktyczna reguła brzmi: kontekst tenanta powinien pochodzić z zaufanej, zweryfikowanej relacji, a nie z dowolnego nagłówka, parametru URL lub pola JSON przesłanego przez klienta. Identyfikator tenanta w żądaniu jest wskazówką routingu, nie dowodem uprawnienia. Aplikacja musi powiązać go z sesją albo zweryfikowanym tokenem i sprawdzić członkostwo oraz rolę po stronie serwera.

OWASP opisuje izolację wielodostępną jako problem obejmujący kontekst tożsamości, warstwę danych, cache, storage, kolejki i limity zasobów. Microsoft podobnie traktuje izolację jako spektrum: od wspólnej aplikacji i tabel po osobne instancje oraz bazy. Architektura współdzielona nie jest automatycznie niebezpieczna, ale wymaga konsekwentnego egzekwowania granicy na każdej ścieżce dostępu.

Model techniczny: gdzie znika kontekst tenanta

W typowym przepływie użytkownik uwierzytelnia się u dostawcy tożsamości, aplikacja ustala aktywną organizację, a gateway przekazuje żądanie do usług. Usługa pobiera rekord, zapisuje zdarzenie, publikuje zadanie i zwraca odpowiedź z cache. Naruszenie może wystąpić w każdym przejściu:

  1. token nie jest związany z właściwym issuerem, audience lub tenantem;
  2. gateway ufa nagłówkowi tenant-id nadpisywalnemu przez klienta;
  3. endpoint sprawdza rolę admin, lecz nie sprawdza, w którym tenancie rola obowiązuje;
  4. repozytorium pobiera obiekt wyłącznie po globalnym resource_id;
  5. klucz cache nie zawiera identyfikatora tenanta;
  6. komunikat kolejki zawiera tenant z danych wejściowych, a worker nie weryfikuje zleceniodawcy;
  7. indeks wyszukiwarki albo link eksportu miesza dokumenty różnych klientów;
  8. operator wsparcia może przełączyć tenant bez osobnego uprawnienia i śladu audytowego.

Dlatego test powinien śledzić „linię pochodzenia” kontekstu: gdzie powstaje, kto może go zmienić, jak jest propagowany i na której warstwie jest egzekwowany. Jeżeli bezpieczeństwo zależy wyłącznie od filtra w interfejsie lub jednego middleware, pojedyncze obejście może otworzyć wszystkie niższe warstwy.

Macierz testowa zamiast przypadkowego fuzzingu

Przed testem tworzymy co najmniej dwa izolowane tenanty: A i B. W każdym umieszczamy unikalne, nieszkodliwe znaczniki w nazwach rekordów, treści dokumentów, metadanych plików i zdarzeniach. Przydatny jest także użytkownik należący do obu organizacji, konto wyłączone, zaproszony gość, integracja machine-to-machine oraz administrator platformy — jeśli zakres je obejmuje.

Macierz łączy podmioty, role, tenanty, typy zasobów i akcje. Dla każdej dozwolonej operacji tworzymy odpowiadającą jej próbę negatywną. Przykładowo członek A może odczytać fakturę A, ale nie fakturę B; administrator A może zaprosić osobę do A, ale nie nadać jej roli w B; integracja A może wysłać webhook A, ale nie odtworzyć sekretu webhooka B.

To podejście ujawnia błędy poziome, pionowe i międzytenantowe bez masowego skanowania identyfikatorów. Losowe UUID nie stanowią kontroli dostępu — jedynie zmniejszają przewidywalność. Test musi potwierdzić decyzję autoryzacyjną nawet wtedy, gdy identyfikator zasobu został pozyskany legalnie z logu, webhooka, odsyłacza lub współdzielonego procesu biznesowego.

Uwierzytelnianie, tokeny i przełączanie organizacji

W tokenach JWT weryfikujemy podpis, dozwolony algorytm, issuer, audience, czas ważności oraz semantykę claimów związanych z organizacją. Szczególnie ważne jest rozróżnienie identyfikatora katalogu dostawcy tożsamości od wewnętrznego identyfikatora klienta SaaS. Zbieżna nazwa domeny lub adres e-mail nie powinny automatycznie tworzyć członkostwa.

Przełączenie aktywnego tenanta musi powodować nową, jednoznaczną decyzję. Jeżeli aplikacja aktualizuje tylko stan frontendu, stary token lub endpoint może zachować wcześniejszy kontekst. Sprawdzamy równoległe karty, odświeżanie tokenu, wylogowanie, zmianę roli, usunięcie członkostwa i unieważnienie sesji. Krytyczny jest czas między odebraniem uprawnienia a faktycznym zablokowaniem API oraz zadań asynchronicznych.

W federacji B2B testujemy mapowanie issuer–subject–tenant, reguły JIT provisioning i przejęcie niezweryfikowanej domeny. W OAuth rozdzielamy uprawnienia delegowane od aplikacyjnych i weryfikujemy, czy consent dla jednego klienta nie daje integracji szerszego zasięgu. Szerszy model zagrożeń opisujemy w przewodniku bezpieczeństwa OAuth 2.0 zgodnym z RFC 9700, a ochronę logowania w artykule o wdrażaniu MFA w firmie.

API i autoryzacja obiektowa

Każdy odczyt, zapis, usunięcie, eksport i akcja niestandardowa powinny wiązać obiekt z aktywnym tenantem. Bezpieczny wzorzec repozytorium wyszukuje po parze tenant_id + resource_id, zamiast pobrać rekord globalnie i dopiero później porównać właściciela. Ogranicza to ryzyko pominięcia kontroli w nowym endpointcie.

Test obejmuje nie tylko ścieżki REST GET i PUT. Sprawdzamy batch API, GraphQL, filtry, sortowanie, liczniki, autocomplete, endpointy mobilne, stare wersje API, import CSV, generowanie PDF, podglądy, kopie, przywracanie i akcje masowe. Częsty błąd polega na tym, że odpowiedź nie zwraca pełnego obiektu, lecz ujawnia jego istnienie, nazwę, status albo fragment danych w komunikacie błędu.

Zwracamy uwagę na funkcje „share”, „clone”, „move” i „transfer ownership”. Przeniesienie zasobu pomiędzy organizacjami jest procesem biznesowym, który powinien mieć jawne preconditions, zgodę obu stron, reautoryzację i audyt. Nie może być ukrytą konsekwencją zmiany tenant_id w żądaniu.

Baza danych: filtr aplikacji nie wystarcza

Wspólne tabele mogą być bezpieczne, jeśli każdy rekord posiada obowiązkowy tenant i wszystkie zapytania są ograniczone. W praktyce ryzyko tworzą zapytania administracyjne, raporty, migracje i nowe relacje ORM. Testujemy odczyt, aktualizację, usunięcie oraz agregacje; COUNT, średnia lub unikalna lista również mogą ujawniać dane innego klienta.

Row-Level Security w bazie może dać drugą warstwę, ale musi otrzymywać kontekst z zaufanego połączenia. Pula połączeń wymaga wyczyszczenia zmiennych sesyjnych po każdym żądaniu. Konto migracyjne albo właściciel tabeli może omijać RLS, dlatego aplikacja czasu wykonania nie powinna używać tej samej uprzywilejowanej tożsamości. W modelu schema-per-tenant lub database-per-tenant testujemy resolver połączenia, backupy, migracje i panel operacyjny — błędny wybór bazy nadal może złamać izolację.

Istotne są klucze obce i unikalność. Relacja powinna uniemożliwiać przypięcie obiektu A do rodzica B, a ograniczenie unikalne zwykle uwzględnia tenant, jeśli nazwa ma być unikalna tylko wewnątrz organizacji. To nie tylko jakość danych: błędna relacja może później przejść przez poprawnie wyglądające zapytanie i ujawnić rekord.

Cache, wyszukiwarka, kolejki i zadania w tle

Klucz cache powinien zawierać tenant, wersję polityki i — gdy wynik zależy od uprawnień — odpowiedni kontekst użytkownika. Testujemy rozgrzanie cache rekordem A i identyczne zapytanie z B. Dotyczy to CDN, cache aplikacyjnego, GraphQL DataLoader, fragmentów HTML i cache odpowiedzi. Nagłówki HTTP nie naprawią klucza, który zderza się wewnątrz aplikacji.

W indeksie wyszukiwarki filtr tenantowy musi być wymuszony po stronie usługi, nie dodawany opcjonalnie przez frontend. Sprawdzamy sugestie, facety, snippet, eksport wyników i indeksy pomocnicze. Dla systemów wektorowych test obejmuje namespace embeddingów, metadane retrievera i cytowane fragmenty; model językowy nie powinien dostać dokumentu spoza granicy, nawet jeśli finalna odpowiedź go nie zacytuje.

Komunikat asynchroniczny powinien nieść niezmienny identyfikator zleceniodawcy i tenanta, a worker ponownie autoryzować wrażliwe działanie. Testujemy retry, dead-letter queue, opóźnione zadania oraz zmianę członkostwa pomiędzy zleceniem i wykonaniem. „Zlecono przed odebraniem roli” nie zawsze oznacza, że operacja nadal powinna zostać wykonana.

Pliki, obiekty storage, CDN i eksporty

Separacja bucketów nie jest jedynym modelem, ale ścieżka obiektu, polityka dostępu i podpisany URL muszą odzwierciedlać tenant. Testujemy możliwość użycia klucza pliku B w API A, przewidywalność nazw, zakres i czas życia linków, cache CDN, warianty miniatur oraz metadane. Link podpisany jest capability: każdy posiadacz może go użyć do wygaśnięcia, więc nie powinien trafiać do szerokich logów ani mieć nieuzasadnionego czasu życia.

Eksporty są częstym źródłem wycieku, bo powstają w tle i są pobierane z innego endpointu. Zapytanie generujące plik, lokalizacja wynikowa i kontrola pobrania muszą stosować ten sam tenant. Sprawdzamy także archiwa backupowe, załączniki wiadomości, linki w e-mailach i pliki pozostałe po offboardingu klienta.

Panel wsparcia i płaszczyzna administracyjna

Operatorzy platformy czasem muszą wejść w kontekst klienta. Taka funkcja powinna wymagać osobnego uprawnienia, uzasadnienia, krótkiej sesji, widocznego banneru, rejestru działań i — dla operacji krytycznych — zatwierdzenia. Konto „superadmin” współdzielone przez zespół uniemożliwia rozliczalność i rozszerza skutki przejęcia.

Weryfikujemy, czy wyszukiwanie klienta, podgląd metadanych, impersonacja, reset MFA, eksport i działania naprawcze mają różne poziomy. Dostęp wsparcia powinien być czasowy zgodnie z podejściem PAM i just-in-time. Dla infrastruktury chmurowej dochodzi separacja kont, subskrypcji i ról, opisana w przewodniku pentestu AWS, Azure i GCP.

Bezpieczna metodologia pentestu izolacji SaaS

Reguły zaangażowania powinny wymienić kontrolowane tenanty, typy kont, dozwolone środowiska, ograniczenia automatyzacji, dane syntetyczne, kontakty awaryjne i akcje zabronione. Test międzytenantowy na produkcji wykonujemy wyłącznie pomiędzy tenantami należącymi do klienta. Nie próbujemy enumerować prawdziwych identyfikatorów ani potwierdzać podatności danymi osoby trzeciej.

Bezpieczny dowód polega na odczytaniu znacznika B kontem A albo na kontrolowanej zmianie syntetycznego rekordu. Gdy odpowiedź wskazuje realny obiekt spoza zakresu, zatrzymujemy test, minimalizujemy ekspozycję i uruchamiamy ścieżkę incydentową. Nie pobieramy całej kolekcji „dla pewności”. W testach odporności na noisy neighbor używamy uzgodnionych limitów; nie wykonujemy DoS współdzielonego SaaS.

Metodykę warto połączyć z analizą architektury i code review. Black-box pokazuje skutek, ale biały lub szary dostęp szybciej odnajduje zapytania bez scope’u, brakujące policy checks i nieuwzględnione consumer-y kolejki. Różnicę między ograniczonym pentestem a pełną symulacją opisuje artykuł red team vs pentest.

Detekcja i telemetria międzytenantowa

Każde zdarzenie bezpieczeństwa powinno zawierać podmiot, aktywny tenant, tenant zasobu, decyzję polityki, akcję, identyfikator korelacyjny i źródło. Log nie może zawierać sekretów ani pełnych tokenów. Najbardziej wartościowy alert wykrywa rozbieżność actor_tenant != resource_tenant, odmowę po zmianie kontekstu, masowe błędy autoryzacji lub nietypowe użycie narzędzia wsparcia.

Monitorowanie musi obejmować warstwę synchroniczną i asynchroniczną. Ślad z gatewaya bez identyfikatora zadania nie połączy się z workerem. Dobrze zaprojektowany test zawiera uzgodnione scenariusze, które SOC ma wykryć; sam kod 403 nie dowodzi gotowości operacyjnej. Alerty powinny być agregowane z ostrożnością, by nie ukryć pojedynczej próby wobec zasobu wysokiej wartości.

Jak naprawiać błędy bez łatania jednego endpointu

Jeżeli podatność wynika z pobrania obiektu globalnie, poprawka tylko w kontrolerze pozostawi inne ścieżki. Najlepsza remediacja przenosi invariant do wspólnej warstwy: repozytorium tenant-scoped, centralnej polityki autoryzacji, RLS lub typów, które nie pozwalają utworzyć zapytania bez kontekstu. Następnie dodajemy test regresyjny z tenantem A i B dla wszystkich wariantów operacji.

Ważne jest rozróżnienie odpowiedzi 404 i 403. Ukrywanie istnienia obiektu może ograniczyć enumerację, lecz nie zastępuje autoryzacji. Sanitizacja odpowiedzi i jednakowy czas obsługi pomagają ograniczać side-channel, ale najpierw trzeba zapewnić prawidłową decyzję.

Checklista dla właściciela SaaS

  • Katalog zasobów wskazuje, do którego tenanta należy każdy obiekt i proces.
  • Kontekst tenanta wynika ze zweryfikowanej sesji lub relacji, nie z zaufania do nagłówka.
  • Każdy endpoint egzekwuje autoryzację obiektową dla odczytu i zapisu.
  • Zapytania, relacje i agregacje są tenant-scoped; RLS stanowi defense in depth.
  • Klucze cache, indeksy, kolejki, storage i eksporty zawierają właściwy scope.
  • Zmiana roli i usunięcie członkostwa unieważniają sesje oraz zadania zgodnie z polityką.
  • Panel wsparcia używa JIT, osobnych uprawnień, uzasadnienia i audytu.
  • Testy integracyjne zawierają negatywne przypadki A→B dla każdego typu zasobu.
  • Telemetria koreluje actor tenant z resource tenant i generuje alarmy.
  • Pentest korzysta wyłącznie z kontrolowanych tenantów i danych syntetycznych.

Co powinien zawierać raport?

Raport z pentestu izolacji tenantów powinien przedstawiać model architektury, macierz ról, dokładny warunek naruszenia, minimalny dowód na danych testowych, zasięg podobnych ścieżek i zalecenie systemowe. Ocena ryzyka uwzględnia nie tylko poufność, ale integralność, możliwość trwałej zmiany konfiguracji klienta i wpływ na dostępność współdzielonej platformy.

Najważniejsza konkluzja jest prosta: izolacja tenanta nie jest cechą bazy ani tokenu, lecz invariantem całego przepływu danych. Jeżeli firma chce wiarygodnie potwierdzić tę granicę przed wdrożeniem enterprise albo audytem klienta, skontaktuj się z Breachroad. Test zaprojektujemy tak, aby wykazać realne ryzyko bez dotykania danych osób trzecich.

Źródła pierwotne i techniczne

UDOSTĘPNIJ / KOPIUJ