Tržiště fungovalo osm měsíců. Dva spoluzakladatelé, ani jeden s bezpečnostním zázemím, ho postavili na platformě Bubble.io s využitím Stripe Connect pro platby. Zpracovalo transakce v hodnotě přes 40 000 USD, mělo 1 500 registrovaných uživatelů a stabilně rostlo díky ústnímu doporučení.
Dvanáct minut po zahájení skenování Penetrify se objevilo kritické zjištění: tajný API klíč Stripe byl vložen do souboru JavaScriptu na straně klienta, který byl doručován do prohlížeče každého návštěvníka. Byl tam od spuštění. Čtyři měsíce plného přístupu pro čtení/zápis k celému jejich účtu Stripe, dostupné pro každého, kdo otevřel DevTools.
Toto je příběh o tom, jak se podnik v hodnotě 40 000 USD málem stal varovným příkladem.
API klíč Stripe, který byste nikdy neměli vystavit
Stripe vydává dva typy API klíčů: publikovatelné klíče a tajné klíče.
Publikovatelný klíč (pk_live_...) je navržen pro použití ve frontendovém kódu. Může provádět pouze omezené operace — vytváření tokenů platebních metod, potvrzování plateb — a nemůže přistupovat k citlivým datům účtu. Je bezpečné ho vystavit v JavaScriptu na straně klienta.
Tajný klíč (sk_live_...) je zcela jiná záležitost. S tajným klíčem Stripe můžete:
- Vypsat všechny zákazníky, platební metody a předplatná
- Přečíst kompletní otisky karet a fakturační adresy všech zákazníků
- Vydat libovolné refundace u jakékoli transakce
- Vytvářet platby proti jakékoli uložené platební metodě
- Upravit nebo smazat plány výplat a bankovní údaje
- Přistupovat ke všem Connected Accounts (v tomto případě ke všem platebním účtům prodejců na tržišti)
- Získat bankovní údaje pro každého prodejce, který se připojil přes Stripe Connect
Tajný klíč Stripe je hlavním klíčem k celé vaší platební infrastruktuře. Patří pouze do kódu na straně serveru, do proměnných prostředí, které se nikdy neposílají do prohlížeče.
Jak se dostal do balíčku
Bubble.io je no-code platforma, která vám umožňuje vytvářet full-stack webové aplikace bez psaní kódu. Má vestavěný systém pracovních postupů pro logiku na straně serveru a API konektor pro externí služby. Pro tým dvou lidí bez inženýrského zázemí je to legitimní způsob, jak rychle uvést na trh skutečný produkt.
Tajný klíč Stripe se dostal do frontendu z důvodu, který bude známý každému, kdo stavěl na no-code platformě pod časovým tlakem: fungovalo to.
Během vývoje tým potřeboval provádět volání Stripe API z pracovních postupů Bubble. Tajný klíč přidali do konfigurace API konektoru. V určitém okamžiku konfigurace — ať už kvůli nepochopení rozdílu mezi prováděním na straně klienta a na straně serveru, nebo kvůli nejasnému detailu konfigurace Bubble — se klíč nakonec ocitl v JavaScriptovém balíčku odeslaném do prohlížeče. Platební toky fungovaly. Transakce byly zpracovány správně. Nebyla žádná chyba, žádné varování, žádný zjevný symptom.
Platforma Bubble ve výchozím nastavení správně zpracovává mnoho provádění na straně serveru, ale hranice mezi tím, co běží v prohlížeči a co běží na serverech Bubble, není v no-code builderu vždy vizuálně zřejmá. Jedná se o dobře zdokumentované riziko v komunitě vývojářů Bubble, ale je snadné ho přehlédnout, když se soustředíte na to, aby produkt fungoval, spíše než na auditování toho, jaká data vaše aplikace odesílá klientovi.
Co skutečně znamenalo vystavení
Pojďme si upřesnit, co bylo během těch čtyř měsíců v ohrožení.
Kdokoli, kdo navštívil tržiště, mohl otevřít Chrome DevTools, přejít na záložku Sources nebo Network, prohledat soubory JavaScriptu pro sk_live_ a najít klíč. To nevyžaduje žádné hackerské nástroje, žádné speciální znalosti a žádnou zranitelnost nad rámec schopnosti kliknout pravým tlačítkem a zkontrolovat webovou stránku.
S tímto klíčem mohli:
- Vyčerpat zůstatek Stripe účtu firmy vydáváním refundací u dokončených transakcí, čímž by zvrátili již získané příjmy
- Vypsat všechny záznamy zákazníků včetně jmen, e-mailových adres, částečných údajů o kartách a fakturačních adres – což je ohlašitelné narušení dat podle GDPR a různých zákonů o ochraně soukromí států USA
- Získat přístup k bankovním údajům prodejců pro každého prodejce, který si připojil svůj výplatní účet přes Stripe Connect – jména, čísla účtů, směrovací kódy
- Upravit výplatní plány a přesměrovat výplaty prodejcům na účty ovládané útočníkem
- Vytvořit podvodné platby proti jakékoli uložené platební metodě zákazníka, až do limitů Stripe pro daný účet
Jakýkoli z těchto výsledků by znamenal konec podnikání. Dohromady představují typ katastrofického narušení, které se dostává do přednášek na bezpečnostních konferencích.
Klíč Stripe byl vystaven po dobu 4 měsíců. Během této doby navštívilo tržiště přibližně 8 000 lidí. Kterýkoli z nich ho mohl najít.
Další zjištění
Klíč Stripe byl nejzávažnějším zjištěním, ale sken odhalil čtyři další problémy:
MEDIUM — Nesprávně nakonfigurovaná pravidla ochrany soukromí Bubble
Pravidla ochrany soukromí Bubble řídí, která databázová pole jsou viditelná pro různé uživatelské role. Záznamy profilů prodejců – které zahrnovaly bankovní údaje zadané během onboardingu Stripe Connect – byly viditelné pro každého ověřeného uživatele prostřednictvím datového API Bubble. I bez klíče Stripe mohl jakýkoli přihlášený kupující dotazovat finanční informace prodejce.
MEDIUM — Enumerace účtů prostřednictvím resetování hesla
Proces resetování hesla vracel různé odpovědi pro registrované a neregistrované e-mailové adresy. Požadavek na registrovaný e-mail vrátil „Zkontrolujte svou schránku“; požadavek na neregistrovaný e-mail vrátil „Účet nenalezen.“ To umožňuje útočníkovi sestavit seznam e-mailových adres, které mají účty na platformě – což je užitečné pro cílený phishing nebo credential stuffing.
MEDIUM — Žádná Content Security Policy
Aplikace nevracela žádnou hlavičku Content-Security-Policy. Funkce vyhledávání odrážela uživatelský vstup bez kódování v některých kontextech, což umožňovalo reflektované XSS. Bez CSP by XSS payload mohl exfiltrovat session tokeny, provádět ověřené API volání jménem oběti nebo vkládat škodlivé skripty do stránky pro ostatní návštěvníky.
LOW — CORS wildcard
API vracelo Access-Control-Allow-Origin: *, což umožňovalo jakékoli webové stránce provádět cross-origin požadavky na API endpointy a číst odpovědi. Pro endpointy vracející citlivá data to umožňuje cross-site exfiltraci dat ze škodlivé stránky, kterou oběť navštíví.
Odpověď: Okamžitá a účinná
Zakladatelé jednali do hodiny od obdržení zprávy.
Prvním krokem bylo otočení kompromitovaného klíče Stripe. V panelu Stripe, pod Developers → API Keys, lze živý tajný klíč „otočit“ – vygenerovat nový klíč a okamžitě zneplatnit starý. To trvalo přibližně dvě minuty. Od té chvíle ho již nikdo, kdo získal vystavený klíč, nemohl použít.
Druhým krokem bylo auditování protokolů událostí Stripe na neoprávněnou aktivitu. Dashboard Stripe poskytuje úplný protokol každého API volání provedeného s vašimi klíči, včetně IP adresy a časového razítka každého požadavku. Zakladatelé zkontrolovali protokol událostí za předchozí čtyři měsíce a hledali anomální volání – refundace, které nevydali, zákazníky, které nevytvořili, změny výplat, které neprovedli. Žádné nenašli. Klíč byl vystaven, ale – pokud bylo možné určit – nebyl aktivně zneužit.
Třetím krokem bylo opravit konfiguraci Bubble. Ve spolupráci s vývojářem Bubble, kterého si najali na několik hodin, přesunuli všechna volání Stripe API do serverových backendových workflow Bubble, kde se API klíče nepřenášejí do prohlížeče. Pravidla ochrany soukromí Bubble byla také opravena tak, aby omezovala finanční údaje prodejců pouze na příslušný účet prodejce.
Jak to najít ve vlastní aplikaci
Pokud používáte Bubble, Webflow nebo jakoukoli jinou no-code aplikaci, která se integruje se Stripe, zde je návod, jak zkontrolovat, zda máte tento problém:
- Otevřete svou aplikaci v anonymním okně.
- Otevřete Chrome DevTools (F12) → záložku Síť.
- Znovu načtěte stránku.
- Na záložce Síť vyhledejte soubory JavaScriptu. U každého z nich klikněte a vyhledejte (Ctrl+F)
sk_live_. - Zkontrolujte také záložku Zdroje. Použijte Ctrl+Shift+F k prohledání všech načtených skriptů pro
sk_live_.
Pokud najdete svůj tajný klíč Stripe v některém z těchto souborů, okamžitě jej otočte, než uděláte cokoli jiného, a poté prozkoumejte, jak se tam dostal.
Stejná kontrola platí pro jakýkoli jiný citlivý API klíč: OpenAI, Twilio, SendGrid, AWS, Mailchimp. Jakýkoli klíč s přístupem pro zápis nebo přístupem k citlivým datům, který najdete v JavaScriptu na straně klienta, by měl být považován za kompromitovaný a okamžitě otočen.
Proč tento vzor přetrvává
Odhalení tajného klíče ve frontendových balíčcích není nová třída zranitelností. Je to známé, dobře zdokumentované riziko po celou dobu, co webové aplikace používají API třetích stran. Proč se to tedy stále děje?
Odpověď je, že vývojářská zkušenost to usnadňuje. No-code platformy a moderní JavaScriptové frameworky stírají hranici mezi klientem a serverem způsoby, které nebyly přítomny v dřívějších modelech vývoje webu. Proměnné prostředí s předponou NEXT_PUBLIC_ jsou záměrně odesílány do prohlížeče; ty bez předpony nejsou. Kontext spuštění Bubble závisí na typu workflow, který používáte. Konfigurace balíčků Vite a webpack určují, co se dostane do prohlížeče.
Tyto hranice jsou zdokumentovány, ale nejsou vynucovány na úrovni nástrojů. Neexistuje žádná chyba při sestavení, když náhodně odhalíte tajný klíč. Aplikace funguje správně. Odhalení je tiché, neomezené a roste každý den, kdy klíč zůstává platný.
Jedinou spolehlivou obranou je explicitně ho vyhledávat – a rychle ho otočit, když ho najdete.
