Trhovisko fungovalo osem mesiacov. Dvaja spoluzakladatelia, ani jeden s bezpečnostným pozadím, ho postavili na Bubble.io so Stripe Connect pre platby. Spracovalo transakcie v hodnote viac ako 40 000 USD, malo 1 500 registrovaných používateľov a neustále rástlo vďaka ústnemu podaniu.
Dvanásť minút po spustení skenovania Penetrify sa objavil kritický nález: tajný API kľúč Stripe bol vložený do klientskeho JavaScript súboru, ktorý sa doručoval do prehliadača každého návštevníka. Bol tam od spustenia. Štyri mesiace plného prístupu na čítanie/zápis k celému ich účtu Stripe, dostupné pre každého, kto otvoril DevTools.
Toto je príbeh o tom, ako sa podnikanie v hodnote 40 000 USD takmer stalo varovným príkladom.
API kľúč Stripe, ktorý by ste nikdy nemali vystaviť
Stripe vydáva dva typy API kľúčov: zverejniteľné kľúče a tajné kľúče.
Zverejniteľný kľúč (pk_live_...) je navrhnutý na použitie vo frontendovom kóde. Môže vykonávať len obmedzené operácie – vytváranie tokenov platobných metód, potvrdzovanie platieb – a nemôže pristupovať k citlivým údajom účtu. Je bezpečné ho vystaviť v klientskom JavaScript kóde.
Tajný kľúč (sk_live_...) je úplne iná záležitosť. S tajným kľúčom Stripe môžete:
- Zobraziť všetkých zákazníkov, platobné metódy a predplatné
- Prečítať úplné odtlačky kariet a fakturačné adresy pre všetkých zákazníkov
- Vydávať ľubovoľné refundácie pre akúkoľvek transakciu
- Vytvárať platby proti akejkoľvek uloženej platobnej metóde
- Upravovať alebo mazať plány výplat a bankové údaje
- Pristupovať ku všetkým Connected Accounts (v tomto prípade ku všetkým platobným účtom predajcov na trhovisku)
- Získať bankové údaje pre každého predajcu, ktorý sa pripojil cez Stripe Connect
Tajný kľúč Stripe je hlavným kľúčom k celej vašej platobnej infraštruktúre. Patrí len do server-side kódu, do premenných prostredia, ktoré sa nikdy neposielajú do prehliadača.
Ako sa dostal do balíka
Bubble.io je no-code platforma, ktorá vám umožňuje vytvárať full-stack webové aplikácie bez písania kódu. Má vstavaný systém pracovných postupov pre server-side logiku a API konektor pre externé služby. Pre dvojčlenný tím bez inžinierskeho pozadia je to legitímny spôsob, ako rýchlo uviesť na trh skutočný produkt.
Tajný kľúč Stripe sa dostal do frontendu z dôvodu, ktorý bude známy každému, kto staval na no-code platforme pod časovým tlakom: fungovalo to.
Počas vývoja tím potreboval vykonávať volania Stripe API z pracovných postupov Bubble. Tajný kľúč pridali do konfigurácie API konektora. V určitom bode konfigurácie – či už išlo o nepochopenie vykonávania na strane klienta vs. na strane servera, alebo o detail konfigurácie Bubble, ktorý nebol zrejmý – sa kľúč nakoniec dostal do JavaScript payloadu odoslaného do prehliadača. Platobné toky fungovali. Transakcie sa spracovali správne. Nebola tam žiadna chyba, žiadne varovanie, žiadny zrejmý symptóm.
Platforma Bubble predvolene správne spracováva veľa server-side vykonávania, ale hranica medzi tým, čo beží v prehliadači a čo beží na serveroch Bubble, nie je v no-code nástroji vždy vizuálne zrejmá. Toto je dobre zdokumentované riziko v komunite vývojárov Bubble, ale je ľahké ho prehliadnuť, keď sa sústredíte na to, aby produkt fungoval, namiesto auditovania toho, aké dáta vaša aplikácia posiela klientovi.
Čo skutočne znamenalo vystavenie
Buďme konkrétni v tom, čo bolo ohrozené počas týchto štyroch mesiacov.
Každý, kto navštívil trhovisko, mohol otvoriť Chrome DevTools, prejsť na kartu Sources alebo Network, prehľadať JavaScript súbory pre sk_live_ a nájsť kľúč. To si nevyžaduje žiadne hackerské nástroje, žiadne špeciálne znalosti a žiadnu zraniteľnosť okrem schopnosti kliknúť pravým tlačidlom myši a skontrolovať webovú stránku.
S týmto kľúčom mohli:
- Vyprázdniť zostatok Stripe účtu firmy vydávaním refundácií za dokončené transakcie, čím by zvrátili už získané príjmy
- Vymenovať všetky záznamy zákazníkov vrátane mien, e-mailových adries, čiastočných údajov o kartách a fakturačných adries — čo predstavuje hlásiteľné narušenie údajov podľa GDPR a rôznych zákonov o ochrane súkromia štátov USA
- Získať prístup k bankovým údajom predajcov pre každého predajcu, ktorý si pripojil svoj výplatný účet cez Stripe Connect — mená, čísla účtov, smerovacie čísla
- Upraviť výplatné plány s cieľom presmerovať výplaty predajcov na účty kontrolované útočníkom
- Vytvoriť podvodné poplatky proti akejkoľvek uloženej platobnej metóde zákazníka, až do limitov Stripe pre daný účet
Akýkoľvek z týchto výsledkov by ukončil podnikanie. Spolu predstavujú typ katastrofálneho narušenia, ktoré sa dostáva do prednášok na bezpečnostných konferenciách.
Kľúč Stripe bol vystavený po dobu 4 mesiacov. Počas tohto obdobia navštívilo trhovisko približne 8 000 ľudí. Ktorýkoľvek z nich ho mohol nájsť.
Ďalšie zistenia
Kľúč Stripe bol najzávažnejším zistením, ale sken odhalil štyri ďalšie problémy:
STREDNÉ — Nesprávne nakonfigurované pravidlá ochrany súkromia Bubble
Pravidlá ochrany súkromia Bubble kontrolujú, ktoré polia databázy sú viditeľné pre rôzne používateľské roly. Záznamy profilov predajcov — ktoré zahŕňali bankové údaje zadané počas onboarding procesu Stripe Connect — boli viditeľné pre každého autentifikovaného používateľa prostredníctvom dátového API Bubble. Aj bez kľúča Stripe mohol akýkoľvek prihlásený kupujúci vyhľadávať finančné informácie predajcu.
STREDNÉ — Enumerácia účtov prostredníctvom resetovania hesla
Proces resetovania hesla vracal rôzne odpovede pre registrované a neregistrované e-mailové adresy. Požiadavka na registrovaný e-mail vrátila "Skontrolujte si schránku"; požiadavka na neregistrovaný e-mail vrátila "Účet nenájdený." To umožňuje útočníkovi vytvoriť zoznam e-mailových adries, ktoré majú účty na platforme — užitočné pre cielený phishing alebo credential stuffing.
STREDNÉ — Žiadna Content Security Policy
Aplikácia nevracala hlavičku Content-Security-Policy. Funkcionalita vyhľadávania odrážala vstup dodaný používateľom bez kódovania v niektorých kontextoch, čo umožňovalo reflektované XSS. Bez CSP by XSS payload mohol exfiltrovať session tokeny, vykonávať autentifikované volania API v mene obete alebo vkladať škodlivé skripty do stránky pre iných návštevníkov.
NÍZKE — CORS wildcard
API vracalo Access-Control-Allow-Origin: *, čo umožňovalo akejkoľvek webovej stránke vykonávať cross-origin požiadavky na koncové body API a čítať odpovede. Pre koncové body vracajúce citlivé údaje to umožňuje cross-site exfiltráciu dát zo škodlivej stránky, ktorú obeť navštívi.
Odpoveď: Okamžitá a účinná
Zakladatelia konali do hodiny od prijatia správy.
Prvým krokom bolo otočenie kompromitovaného kľúča Stripe. Na paneli Stripe, v časti Developers → API Keys, je možné živý tajný kľúč "otočiť" — vygenerovať nový kľúč a okamžite zneplatniť starý. To trvalo približne dve minúty. Od tohto momentu ho už nikto, kto extrahoval vystavený kľúč, nemohol použiť.
Druhým krokom bolo auditovanie záznamov udalostí Stripe pre neoprávnenú aktivitu. Dashboard Stripe poskytuje kompletný záznam každého volania API vykonaného s vašimi kľúčmi, vrátane IP adresy a časovej pečiatky každej požiadavky. Zakladatelia preskúmali záznam udalostí za predchádzajúce štyri mesiace a hľadali anomálne volania — refundácie, ktoré nevydali, zákazníkov, ktorých nevytvorili, zmeny výplat, ktoré nevykonali. Nenašli žiadne. Kľúč bol vystavený, ale — pokiaľ sa dalo zistiť — nebol aktívne zneužitý.
Tretím krokom bolo opraviť konfiguráciu Bubble. V spolupráci s vývojárom Bubble, ktorého si najali na niekoľko hodín, presunuli všetky volania Stripe API do serverových backendových workflowov Bubble, kde sa kľúče API neprenášajú do prehliadača. Pravidlá ochrany súkromia Bubble boli tiež opravené tak, aby obmedzili finančné údaje predajcu len na príslušný účet predajcu.
Ako to nájsť vo vlastnej aplikácii
Ak používate Bubble, Webflow alebo akúkoľvek inú no-code aplikáciu, ktorá sa integruje so Stripe, tu je návod, ako skontrolovať, či máte tento problém:
- Otvorte svoju aplikáciu v anonymnom okne.
- Otvorte Chrome DevTools (F12) → záložku Network.
- Znova načítajte stránku.
- V záložke Network vyhľadajte súbory JavaScript. Pre každý z nich kliknite a vyhľadajte (Ctrl+F)
sk_live_. - Skontrolujte aj záložku Sources. Použite Ctrl+Shift+F na vyhľadávanie
sk_live_vo všetkých načítaných skriptoch.
Ak nájdete svoj tajný kľúč Stripe v ktoromkoľvek z týchto súborov, okamžite ho zmeňte, predtým než urobíte čokoľvek iné, a potom prešetrite, ako sa tam dostal.
Táto istá kontrola platí pre akýkoľvek iný citlivý API kľúč: OpenAI, Twilio, SendGrid, AWS, Mailchimp. Akýkoľvek kľúč s prístupom na zápis alebo prístupom k citlivým údajom, ktorý nájdete v client-side JavaScript, by mal byť považovaný za kompromitovaný a okamžite zmenený.
Prečo tento vzor pretrváva
Expozícia tajného kľúča vo frontendových balíkoch nie je nová trieda zraniteľnosti. Je to známe, dobre zdokumentované riziko už odvtedy, čo webové aplikácie používajú API tretích strán. Prečo sa to teda stále deje?
Odpoveďou je, že vývojárska skúsenosť to uľahčuje. No-code platformy a moderné JavaScript frameworky stierajú hranicu medzi klientom a serverom spôsobmi, ktoré neboli prítomné v skorších modeloch vývoja webu. Premenné prostredia s prefixom NEXT_PUBLIC_ sú zámerne odosielané do prehliadača; tie bez prefixu nie sú. Kontext vykonávania Bubble závisí od typu workflow, ktorý používate. Konfigurácie balíkov Vite a webpack určujú, čo sa dostane do prehliadača.
Tieto hranice sú zdokumentované, ale nie sú vynucované na úrovni nástrojov. Neexistuje žiadna build-time chyba, keď náhodne vystavíte tajný kľúč. Aplikácia funguje správne. Expozícia je tichá, neurčitá a rastie každý deň, kým kľúč zostáva platný.
Jedinou spoľahlivou obranou je explicitne ho skenovať — a rýchlo ho zmeniť, keď ho nájdete.
