לדלג לתוכן

איך OAuth נתקף - כשהפרוטוקול בטוח אבל המימוש שלו לא

כמעט כל אתר שאתם נכנסים אליו היום מציע לכם כפתור "התחברות עם גוגל" או "התחברות עם פייסבוק". מאחורי הכפתור הזה עומד פרוטוטול בשם OAuth 2.0, והאירוניה הגדולה היא שהפרוטוקול עצמו נחשב בטוח לגמרי, מתוכנן היטב, ועבר בדיקות אינספור. הבעיה כמעט אף פעם לא נמצאת בפרוטוקול. היא נמצאת באיך שכל אתר ואתר בוחר לממש אותו.

אז מה זה בעצם OAuth ולמה הוא כזה יעד פופולרי

OAuth הוא פרוטוקול שמאפשר לאתר אחד לקבל הרשאה מוגבלת לפעול בשם משתמש, בלי שהמשתמש ייתן לו את הסיסמה שלו. כשאתם לוחצים "התחברות עם גוגל", האתר שאתם נכנסים אליו לא רואה את הסיסמה של חשבון הגוגל שלכם בכלל. במקום זה, גוגל מאמתת אתכם בעצמה, ואז שולחת לאתר "אישור" שאתם באמת מי שאתם אומרים שאתם.

הסיבה שזה יעד כל כך אטרקטיבי לתוקפים היא שהוא נמצא ממש בלב תהליך האימות - אם אפשר לתקוף אותו בהצלחה, התוצאה כמעט תמיד היא השתלטות מלאה על חשבון של מישהו אחר, לפעמים בלי צורך בסיסמה בכלל.

למה כל כך קל לממש את OAuth לא נכון

הבעיה המרכזית היא שהפרוטוקול עצמו נותן למפתחים הרבה חופש - יש כמה זרימות (flows) שונות, הרבה פרמטרים אופציונליים, ולא תמיד ברור מה חובה לבדוק ומה אפשר לדלג עליו. מפתח שממש את הזרימה הבסיסית ורואה שהיא "עובדת" - כלומר המשתמש מצליח להתחבר - חושב שהוא סיים. אבל "עובד" ו"בטוח" הם שני דברים שונים לגמרי, וההבדל ביניהם הוא בדיוק המקומות שתוקפים מחפשים.

נקודות התורפה הנפוצות ביותר

הנה החולשות שחוזרות על עצמן שוב ושוב במימושי OAuth, גם באתרים גדולים ומוכרים:

  • אימות רופף של redirect_uri. אחרי שהמשתמש מאשר את ההתחברות, שרת האימות שולח אותו חזרה לאתר המקורי, לכתובת שנקראת redirect_uri, יחד עם קוד הרשאה או טוקן. אם השרת לא בודק בקפדנות שהכתובת הזאת היא בדיוק הכתובת הרשומה מראש - ומאפשר למשל תת-דומיינים או כתובות דומות בצורה חשודה - תוקף יכול לרשום את עצמו כ-redirect_uri ולגנוב את קוד ההרשאה או הטוקן ישירות.
  • פרמטר state חסר או לא נבדק. ה-state אמור להיות ערך אקראי שהאתר יוצר לפני שהוא שולח את המשתמש להתחבר, ובודק שוב כשהוא חוזר, כדי למנוע CSRF על תהליך ההתחברות עצמו. בלי state, תוקף יכול לגרום לקורבן להשלים התחברות עם חשבון של התוקף, ולמעשה "לקשור" את חשבון הקורבן לחשבון שהתוקף שולט בו.
  • הפניה פתוחה שמשורשרת לגניבת OAuth - Open Redirect. נקודת הפניה פתוחה באתר, גם כזו שנראית תמימה, יכולה לגרום ל-redirect_uri להיראות תקין בעיני שרת האימות אבל בפועל להוביל את הטוקן לשרת של התוקף.
  • דליפת טוקן בזרימת implicit. בזרימה הישנה יותר, implicit flow, הטוקן מוחזר ישירות בכתובת ה-URL עצמה. זה אומר שהוא נשמר בהיסטוריית הדפדפן, ולפעמים דולף דרך כותרת Referer לאתרי צד שלישי. זו אחת הסיבות שהתעשייה זזה בהדרגה משם.
  • קישור חשבונות רופף - Account Linking. כשאתר מקבל התחברות מספק חיצוני, הוא צריך להחליט לאיזה חשבון קיים לקשר אותה. אם ההחלטה מבוססת רק על שדה כמו כתובת אימייל בלי לבדוק שהוא אכן מאומת אצל הספק, תוקף שיוצר חשבון עם אימייל זהה לקורבן אצל ספק אחר יכול להשתלט על החשבון הקיים.

למה זה כל כך אפקטיבי כשזה עובד

מה שהופך את התקיפות האלה למסוכנות במיוחד הוא שהן קורות סביב תהליך ההתחברות עצמו, ולא אחריו. לא מדובר בהעלאת הרשאות בתוך חשבון קיים - מדובר בהשתלטות מלאה על הזהות של המשתמש, לפעמים בלי שהוא לוחץ על שום דבר חשוד יותר מלינק שנראה כמו כתובת רגילה של האתר. וכיוון שהתהליך כולו קורה בין כמה שרתים - האתר, ספק הזהות, והדפדפן - יש הרבה יותר נקודות שבהן הנחה שגויה יכולה ליצור פרצה.

איך בודקים ומגנים

הדרך הכי טובה למצוא בעיות כאלה, כחוקרי אבטחה, היא לעבור שיטתית על כל שלב בזרימה - מה קורה אם אני משנה את ה-redirect_uri במעט, מה קורה אם אני מדלג על שליחת state, מה קורה אם אני מנסה להירשם עם אימייל של מישהו אחר. כמפתחים, ההגנה מתחילה מלהתייחס לרשימה של הכתובות המותרות ב-redirect_uri כאילו היא רשימה סגורה לגמרי, לא לדלג אף פעם על בדיקת state, ולוודא שקישור חשבונות תלוי בזהות מאומתת ולא בשדה שאפשר לזייף.

זה בדיוק סוג הנושא שדורש הבנה של כמה חלקים נעים בו זמנית, וזו הסיבה שאנחנו מקדישים לו זמן משמעותי בקורס פריצת אתרים מתקדם - לא רק לזהות כל חולשה בנפרד, אלא להבין איך הן משתלבות זו בזו לתוך תרחיש תקיפה שלם.

אם אתם מתרגלים את זה בעצמכם ונתקעים באמצע, יש לנו קהילה בדיסקורד שמדברת בדיוק על הדברים האלה.

הצטרפו לקהילה בדיסקורד

לסיכום

OAuth הוא דוגמה מצוינת לכך שפרוטוקול בטוח על הנייר לא אומר מימוש בטוח בפועל. הפער בין השניים הוא בדיוק המקום שבו תוקפים טובים מוצאים את הדרך פנימה, ובדיוק המקום שבו מפתחים טובים צריכים להשקיע את תשומת הלב הכי גדולה.