כשה-JWT סומך על הקליינט: איך קיצור דרך אחד הפך למשתמש אדמין
לא מזמן נתקלתי בבדיקת חדירה במערכת שבה השתמשו ב JWT כדי לנהל סשנים. לכאורה הכל היה סטנדרטי, טוקן עם exp חתימה ו payload בסיסי. אבל המפתח החליט לחסוך בשורות קוד והסתמך על client side בלבד כדי לוודא הרשאות. בתוך ה payload הופיע שדה role שהוחזר ללקוח וכל הבדיקות הקריטיות בצד השרת התבססו על הערך הזה. התוצאה ברורה לכל מי שמתעסק קצת באבטחה – אם אני לוקח טוקן קיים ומשנה את ה payload ל role admin, מצפין מחדש עם אותו אלגוריתם ובמקרה הזה אפילו בלי חתימה אמיתית (alg none היה מותר בשרת), אני מקבל גישה מלאה למודולים שלא היו אמורים להיות פתוחים עבורי.
הדבר הכי בעייתי הוא שמהצד של המשתמש הכל נראה לגיטימי. בקשה פשוטה ל endpoint רגיש יכולה להיראות כך:
GET /api/admin/reports HTTP/1.1
Host: VULNERABLE_SITE
Authorization: Bearer eyJhbGciOiJub25lIn0.eyJ1c2VySWQiOiIxMjMiLCJyb2xlIjoiYWRtaW4ifQ.
והשרת יחזיר לי מידע עסקי סופר רגיש כאילו הייתי אדמין אמיתי.
מה שזה מדגים בצורה הכי חדה שיש הוא שלא משנה כמה ה client נראה מתוחכם, האבטחה חייבת להיות enforced בצד השרת. אין לסמוך על מידע שמגיע מהלקוח גם אם הוא ארוז יפה בתוך JWT.
איך פותרים את זה בצורה נכונה
לא לאפשר alg none ולא לאפשר מעבר חופשי של אלגוריתמים שונים – להגדיר בצד השרת אלגוריתם חתימה אחד בלבד ולוודא שהספרייה בודקת אותו.
לא להחזיק הרשאות קריטיות בתוך ה payload של ה JWT אלא לשמור אותן בצד השרת במסד נתונים או ב session store אמין. ה JWT צריך להיות מזהה ולא מקור אמת להרשאות.
להחיל ולידציה מלאה על כל בקשה רגישת הרשאות – לא משנה מה מופיע ב payload, השרת חייב לבדוק בעצמו למול מקור האמת.
לבצע ניטור ולוגים על שימושים חריגים כמו ניסיון לגשת לנתיבים אדמיניסטרטיביים עם משתמשים רגילים.
מקרה כזה אולי נראה שולי אבל בפועל הוא מאפשר לתוקף לעקוף את כל שכבות ההגנה ולשלוט על האפליקציה. זו תזכורת מצוינת שכל חיסכון קטן באבטחה בצד השרת הופך מהר מאוד לבעיה עסקית חמורה.
פוסט זה פורסם לראשונה בלינקדאין בתאריך 2025-10-01. — ארז מטולה
