לדלג לתוכן

אבטחת GraphQL - הבסיס

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

אז מה זה בעצם GraphQL, ולמה זה שונה

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

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

חשיפת הסכימה - כשמכניסים לתוקף מפת דרכים מלאה

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

בעולם ה-REST, תוקף צריך לגלות endpoints בעצמו, בניחוש, בכלים אוטומטיים, או בבדיקת קוד הצד לקוח. ב-GraphQL עם introspection פעיל, כל הרשימה פשוט מוגשת לו על מגש.

אכיפת הרשאות ברמת שדה - הבעיה שרוב הצוותים מפספסים

זו אולי הנקודה הכי מהותית להבין. ב-REST, בקרת הרשאות בדרך כלל קורית ברמת ה-endpoint - "האם למשתמש הזה מותר לגשת לנתיב הזה בכלל". ב-GraphQL, שאילתה אחת יכולה למשוך נתונים ממספר טיפוסים ושדות שונים בבת אחת, ולכן בקרת הרשאה ברמת ה-endpoint פשוט לא מספיקה.

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

ריבוי שאילתות ואליאסים - וקטור לניחוש ולעומס

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

אבל אותה תכונה בדיוק הופכת לכלי רב עוצמה עבור תוקף שמנסה לנחש סיסמאות, לבדוק תוקף של קודי אימות, או פשוט להעמיס על השרת. במקום לשלוח אלף בקשות נפרדות שקל לזהות ולחסום לפי קצב (rate limiting) רגיל, אפשר לארוז מאות ניסיונות בתוך בקשת HTTP אחת בודדת, עם מאות אליאסים שונים. אם המערכת מגבילה קצב לפי מספר הבקשות ולא לפי מספר הפעולות שבתוכן, ההגנה הזאת בפועל לא שווה הרבה.

שאילתות מקוננות - כשעומק השאילתה הופך לנשק

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

הבעיה היא ששאילתה עם עומק גדול מספיק, במיוחד אם היא כוללת גם ריבוי אליאסים כמו שדיברנו עליו קודם, יכולה לגרום לשרת לבצע כמות עצומה של עבודה בשביל בקשה יחסית קטנה מבחינת התוקף. זה וקטור מובהק למניעת שירות - Denial of Service - שלא קיים באותה צורה כלל ב-API מבוסס REST רגיל, כי שם כל בקשה מוגבלת מראש למה שהמפתח החליט להחזיר.

למה אינטואיציית REST פשוט לא מספיקה

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

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

יש לכם שאלה על GraphQL באמצע הלמידה? יש קהילה שלמה שאפשר להתייעץ איתה.

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

לסיכום

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