“זה GraphQL, זה Typed, זה סגור” – שאילתת introspection אחת אחר כך
עושים בדיקת אבטחה למערכת SaaS מוכרת, עם API מסוג GraphQL. הצוות שם אומר: “אנחנו בטוחים – GraphQL זה Typed, הכל סגור.” אני מחייך – שמעתי את זה לא פעם.
שלב ראשון: מיפוי. ב-REST מחפשים Swagger, וב-GraphQL משתמשים ב-introspection:
{ __schema { types { name fields { name } } } }
השרת עונה יפה, ועכשיו יש לי blueprint מלא – כל הטייפים, כל המיוטיישנים.
שלב שני: חיפוש נקודה מעניינת. בין כל המיוטיישנים מופיע משהו בשם updateUser עם השדות: id, isAdmin, email, name. ה-UI הרגיל מאפשר לשנות רק שם ומייל. אני שואל את עצמי: “מה קורה אם אשלח mutation עם isAdmin=true?”
אני מריץ:
mutation { updateUser(id: 6, isAdmin: true) { id isAdmin } }
והתגובה:
{ "data": { "updateUser": { "id": 6, "isAdmin": true } } }
בום – המשתמש שלי עכשיו אדמין.
לא צריך לפרוץ את האפליקציה או לנחש סיסמאות. המערכת עצמה, עם הרשאות משתמש רגיל, מאפשרת עדכון של שדה קריטי שלא נבדק ברמת הרשאות. ה-UI מסתיר את זה, אבל ה-API עצמו לא חסום.
ההמלצות
- לחסום introspection ב-Production.
- להגדיר בדיקות הרשאות ברמת שדה, לא רק “משתמש משנה את עצמו”.
- להריץ בדיקות אוטומטיות על כל mutation חדש – במיוחד כאלה שמשנים הרשאות.
מוסר השכל: שאילתת introspection אחת ושורת mutation אחת – זה כל מה שנדרש כדי לפתוח דלת לאדמין. לא כי GraphQL בעייתי, אלא כי הנחת האבטחה הייתה “אם זה לא ב-UI, זה בטוח”.
פוסט זה פורסם לראשונה בלינקדאין בתאריך 2025-07-28. — ארז מטולה
