דפוסי פריצה · 1 מתוך 5
הרשאה שבורה ברמת האובייקט: איך שינוי של מספר אחד ב-URL מספיק כדי לגנוב מידע
זה אחד הבאגים הנפוצים ביותר באפליקציות שנבנות מהר — וגם אחד הקלים ביותר להבין. זה הפוסט הראשון בסדרה על דפוסי הפריצה הנפוצים ביותר; נתחיל בפשוט שבהם, ולמרבה הצער גם בנפוץ שבהם.
מה זה בעצם "הרשאה שבורה ברמת האובייקט"?
לכל פיסת מידע באפליקציה יש בדרך כלל "מזהה" — מספר הזמנה, מספר חשבונית, מספר פרופיל. אפליקציה תקינה בודקת שני דברים לפני שהיא מציגה מידע: (1) האם המשתמש בכלל מחובר, ו-(2) האם הפריט הספציפי הזה שייך למשתמש הזה. הרשאה שבורה ברמת האובייקט (באנגלית: Broken Object-Level Authorization, בקיצור BOLA — לפעמים תשמעו גם את השם הישן, IDOR) קורה כשהבדיקה השנייה פשוט לא קיימת. האפליקציה בודקת "מי אתה", אבל שוכחת לבדוק "האם זה שלך".
תחשבו על זה כמו בניין דירות עם דלת כניסה נעולה בקוד. יש לכם קוד, אז אתם יכולים להיכנס לבניין — זו ה"התחברות". אבל ברגע שאתם בפנים, כל תיבת דואר בבניין פתוחה לכל מי שיודע את המספר שלה. זה בדיוק ההבדל בין מי אתה לבין מה מותר לך לראות.
איך זה קורה בפועל
נניח שיש לכם אפליקציה לניהול חשבוניות, ולכל חשבונית יש כתובת עם מספר:
myapp.com/invoice/1001. דני מתחבר, ורואה את החשבונית שלו בכתובת הזו. עכשיו דני
— מתוך סקרנות, או כי הוא תוקף — פשוט משנה את המספר בכתובת ל-myapp.com/invoice/1002
ולוחץ Enter.
אם האפליקציה בדקה רק "האם דני מחובר?" ולא בדקה "האם חשבונית 1002 שייכת לדני?" — התוצאה תהיה שדני יראה עכשיו את החשבונית המלאה של יעל, כולל הסכום, הפרטים העסקיים שלה, ואולי גם פרטי תשלום. החלק המפחיד: זה לא דורש שום ידע טכני מיוחד. זה כפתור "עריכת כתובת" בדפדפן שהפך לכלי פריצה.
דוגמה מהעיתונות
קראו את הכתבה ב-TechCrunch ←
איך פותרים את זה
התיקון היחיד שבאמת עובד הוא בדיקת בעלות בצד השרת, על כל בקשה שמחזירה או משנה פריט ספציפי: "האם הפריט הזה באמת שייך למשתמש המחובר?" לא מספיק לבדוק שהמשתמש מחובר. לא מספיק לבדוק שהמזהה תקין. צריך לבדוק במפורש שהבעלות תואמת — בכל endpoint שמחזיר או משנה מידע.
שימו לב: הפיכת המזהים למסובכים (למשל UUID ארוך במקום 1001, 1002) עוזרת קצת, אבל היא לא פתרון אמיתי — זו הסתרה, לא הרשאה. תוקף נחוש, או סורק אוטומטי, עדיין יכול למצוא מזהה תקף. ולפעמים זה אפילו לא דורש תחכום טכני בכלל: יעל יצאה לרגע למטבחון במשרד ושכחה לנעול את המסך, ודני פשוט העתיק פיזית את המזהה הסודי שהיה גלוי מול העיניים שלו. וברגע שמישהו כבר קיבל מזהה אחד — מקישור ששותף, מפניית תמיכה, ממסך לא נעול, מבאג אחר — מזהה מסובך לא יעצור אותו. הבדיקה עצמה היא הפתרון היחיד, וצריך אותה בכל endpoint שמחזיר או משנה מידע. מספיק לשכוח אותה במקום אחד כדי שכל המערכת תהיה חשופה.
איך בודקים אם האפליקציה שלכם חשופה לדפוס הזה
הבדיקה הזו לוקחת חמש דקות ולא דורשת שום ידע טכני:
- פתחו שני חשבונות משתמש שונים באפליקציה שלכם (או בקשו מחבר לפתוח חשבון שני).
- מהחשבון הראשון, אתרו פריט פרטי כלשהו — הזמנה, מסמך, פרופיל — והעתיקו את הכתובת (URL) שלו.
- התנתקו, והתחברו עם החשבון השני.
- הדביקו את אותה כתובת בדיוק בשורת הכתובות של הדפדפן, ולחצו Enter.
אם המידע של החשבון הראשון עולה על המסך — מצאתם את הדפוס הזה באפליקציה שלכם. עדיף שתמצאו את זה אתם, לפני שמישהו אחר ימצא.
איך secureFlows פותר את זה מלכתחילה
ב-secureFlows, הגישה למידע נקבעת לפי מי מבקש — לא לפי מזהה שהאפליקציה שלכם שולחת. כשמשתמש מתחבר, secureFlows מנפיקה לו טוקן הפעלה קצר מועד שמזהה אותו באופן מאובטח, וכל בקשה חוזרת עם הטוקן הזה. השרת מחזיר רק את מה שמותר לבעל הטוקן לראות, לא משנה איזה מספר מופיע בבקשה. במילים אחרות: אין דבר כזה "לשנות מספר בכתובת" ולקבל מידע של מישהו אחר — כי הגישה למידע אף פעם לא הייתה תלויה במספר הזה מלכתחילה.
תחשבו על זה כמו כרטיס מפתח במלון: כרטיס המפתח שקיבלתם פותח רק את החדר שלכם, כי הזיהוי מקודד בתוך הכרטיס עצמו. בדיוק כך פועל הטוקן: הבעלות לא נבדקת כל פעם מחדש על ידי מישהו שזוכר להוסיף שורת קוד — היא פשוט מובנית בתוך הכרטיס שכל בקשה נושאת איתה.
רוצים שהבדיקה הזו תהיה מובנית בתשתית, ולא תלויה בזיכרון של מפתח בשעה 2 בלילה? לחצו על הכפתור "התחילו לבנות בחינם" למטה, ונהלו משתמשים בקלות ובפרטיות עם secureFlows.
התחילו לבנות בחינם