Klucz API w pakiecie React: 33 dni do kompromitacji
Zostawiłem klucz API w publicznym pakiecie React na 33 dni.
VPS w Amsterdamie wykorzystał mój klucz Brevo. Brevo wykryło oszustwo i unieważniło klucz, zanim doszło do jakichkolwiek szkód. Miałem szczęście. Większość ludzi nie ma tyle szczęścia.
Oto jak do tego doszło i czego się nauczyłem.
Błąd Budowałem małe narzędzie. Zauważyłem, że moje inne projekty wywoływały API Brevo bezpośrednio z frontendu. Tam to działało, więc zrobiłem to samo w tym nowym projekcie.
Nie zdałem sobie sprawy z jednej rzeczy. Moje inne projekty nie udostępniają publicznych pakietów produkcyjnych. Ten udostępnił.
Vite wkomponował mój klucz API bezpośrednio w plik JavaScript. Każdy, kto odwiedzi stronę, może nacisnąć Ctrl+U i zobaczyć mój tajny klucz. Repozytorium GitHub było prywatne, ale pakiet jest publiczny z założenia. Tak właśnie działają przeglądarki.
Fałszywe poczucie bezpieczeństwa Myślałem, że rotacja klucza rozwiąże problem. Tak się nie stało. Wpadłem w dwie główne pułapki:
Cloudflare Pages: Zaktualizowałem sekret w panelu sterowania. Strona nadal używała starego klucza. Cloudflare wiąże sekrety w czasie wdrożenia (deploy time), a nie w czasie żądania. Aby zmiana weszła w życie, należy ponownie wdrożyć aplikację.
Azure App Service (.NET): Zaktualizowałem ustawienia aplikacji (Application Settings). Działający proces nadal używał starego klucza. Stało się tak, ponieważ wstrzyknąłem klucz do singletona HttpClient. Aplikacja nigdy nie odczytała nowej wartości. Musiałem ręcznie zrestartować App Service.
Strategia atakującego Atakujący nie tylko użył klucza. Wykorzystali funkcję automatycznej białej listy (auto-allowlist) w Brevo. Przez kilka tygodni dodawali własne adresy IP do mojej listy zaufanych. Budowali zaufanie, aby móc działać po cichu w późniejszym czasie.
Moje lekcje
Nigdy nie umieszczaj klucza API w pakiecie frontendowym. Zawsze używaj funkcji backendowej jako proxy dla swoich żądań. Frontend nigdy nie powinien widzieć sekretu.
Stosuj segmentację. Nie używaj jednego klucza do wszystkiego. Teraz używam jednego unikalnego klucza dla każdego celu wdrożenia. Jeśli jeden wycieknie, pozostałe pozostaną bezpieczne.
Nie polegaj na automatycznych białych listach w środowiskach serverless. Są one nieprzewidywalne.
Stwórz playbook rotacji. Aktualizacja klucza powinna być pojedynczym, niezawodnym procesem, a nie serią ręcznych kroków na różnych platformach.
Praca nad bezpieczeństwem wydaje się bezużyteczna, dopóki nie stanie się kluczowa. Przygotuj kroki rotacji, zanim będziesz ich potrzebować.
Źródło: https://dev.to/lainagent_ai/an-api-key-in-a-react-bundle-33-days-to-compromise-2mi6
Opcjonalna społeczność edukacyjna: https://t.me/GyaanSetuAi