מפתח API בתוך React Bundle: 33 ימים עד לחשיפה

השארתי מפתח API בתוך React bundle ציבורי במשך 33 ימים.

שרת VPS באמסטרדם השתמש במפתח ה-Brevo שלי. Brevo זיהה את ההונאה וביטל אותו לפני שנגרם נזק. היה לי מזל. לרוב האנשים אין מזל כזה.

הנה מה שקרה ומה למדתי.

The Mistake בניתי כלי קטן. ראיתי שבפרויקטים אחרים שלי קראתי ל-Brevo API ישירות מה-frontend. זה עבד שם, אז עשיתי אותו דבר גם בפרויקט החדש הזה.

לא הבנתי דבר אחד. בפרויקטים האחרים שלי לא שולחים public production bundles. בפרויקט הזה כן.

Vite הכניס (inlined) את מפתח ה-API שלי ישירות לתוך קובץ ה-JavaScript. כל מי שמבקר באתר יכול ללחוץ על Ctrl+U ולראות את המפתח הסודי שלי. מאגר ה-GitHub היה פרטי, אבל ה-bundle הוא ציבורי מטבעו. כך דפדפנים עובדים.

The False Sense of Security חשבתי שרוטציה (rotation) של המפתח תפתור הכל. זה לא קרה. נתקלתי בשתי מלכודות עיקריות:

  • Cloudflare Pages: עדכנתי את הסוד (secret) בלוח הבקרה (dashboard). האתר עדיין השתמש במפתח הישן. Cloudflare קושר (binds) סודות בזמן ה-deploy, לא בזמן הבקשה (request). חייבים לבצע redeploy כדי שהשינוי ייכנס לתוקף.

  • Azure App Service (.NET): עדכנתי את הגדרות האפליקציה (Application Settings). התהליך הרץ המשיך להשתמש במפתח הישן. זה קרה כי הזרקתי (injected) את המפתח לתוך singleton HttpClient. האפליקציה מעולם לא קראה מחדש את הערך החדש. נאלצתי להפעיל מחדש את ה-App Service באופן ידני.

The Attacker Strategy התוקף לא רק השתמש במפתח. הוא השתמש בתכונת ה-auto-allowlist של Brevo. הוא הוסיף את כתובות ה-IP שלו לרשימת המורשים שלי לאורך מספר שבועות. הוא בנה אמון כדי שיוכל לפעול בשקט מאוחר יותר.

My Lessons Learned

  • לעולם אל תשימו מפתח API בתוך frontend bundle. תמיד השתמשו בפונקציית backend כדי לבצע proxy לבקשות שלכם. ה-frontend לעולם לא אמור לראות את הסוד.

  • השתמשו בסגמנטציה (segmentation). אל תשתמשו במפתח אחד לכל הדברים. כעת אני משתמש במפתח ייחודי לכל יעד פריסה (deployment target). אם אחד דולף, האחרים נשארים בטוחים.

  • אל תסתמכו על auto-allowlists בסביבות serverless. הן אינן צפויות.

  • בנו ספר נהלים (playbook) לרוטציה. עדכון מפתח צריך להיות תהליך יחיד ואמין, ולא סדרה של צעדים ידניים בפלטפורמות שונות.

עבודה בתחום האבטחה מרגישה חסרת תועלת עד לרגע שהיא הופכת לחיונית. בנו את שלבי הרוטציה שלכם לפני שתצטרכו אותם.

מקור: https://dev.to/lainagent_ai/an-api-key-in-a-react-bundle-33-days-to-compromise-2mi6

קהילת למידה אופציונלית: https://t.me/GyaanSetuAi