הם איגדו שמונה קריאות API לאחת. אני שרשרתי שלוש מהן מעבר להרשאות.
הסיפור הזה מתחיל באמצע ספרינט, בחדר ישיבות של סטארטאפ פיננסי קטן אבל עם קצב שחרור של חברת ענק. הייתי יועץ פיתוח מאובטח שהוזמן לחוות דעה על רעיון שעלה.
ראש הצוות נכנס ואומר: “יש יותר מדי קריאות API בין ה-frontend ל-backend. אנחנו מבזבזים שניות יקרות. אני רוצה לאגד את כל הקריאות ל-batch אחד – ב-endpoint חדש: /api/batchRun.”
המהלך נשמע מבריק. במקום 8 קריאות – אחת. ה-frontend שולח JSON של פקודות, ה-backend מריץ בלולאה, מחזיר תוצאות מסודרות.
בפועל, בקשה כזאת נראתה כך:
{
"commands": [
{"action": "getBalance", "userId": "23"},
{"action": "getTransactions", "userId": "23", "since": "2023-01-01"},
{"action": "transfer", "from": "23", "to": "999", "amount": "10"}
]
}
ראש הצוות טען בתוקף שאין עם זה שום בעיה, כי זה פשוט איגוד של בקשות שכל אחת מהן יכלה להתקבל ממילא בנפרד. כל אחת עוברת בדיקת הרשאות, קלטים וכו’.
בכל זאת, משהו הרגיש לי לא בסדר.
מה שהמערכת לא בדקה
המערכת טיפלה בכל פקודה על פי הסדר, אך לא בדקה את הקשרים הלוגיים בין הפעולות, וכל קומבינציה נשלחה כמו שהיא.
לאחר חשיבה, תכננתי איך אני שולח שילוב “מרושע”:
- קודם מעביר 10 ש”ח מעצמי לחשבון אחר.
- אחר כך מבקש לראות את ה-balance של אותו חשבון.
- אחר כך מנסה למשוך דוח PDF עם מזהה של action קודם – שלא הייתה לי הרשאה אליו.
כך, על ידי חיבור בין פקודות באותו batch, עקפתי בקרות שהיו קיימות בכל endpoint נפרד – כי הקוד רץ כולו על אותו אובייקט session, ולא בדק הרשאות מחדש על כל תוצאה.
מה יצא מזה
כשישבנו לניתוח, ראש הצוות הסביר: “לא חשבנו שפקודות תלויות. בנינו את זה לייעול בלבד.” אבל בפועל – attackers ייצרו “שרשראות” בקומבינציה, ויצרו התקפות שלא קיימות בשום API נפרד.
הלקח שצוות הפיתוח לקח: כל אופטימיזציה בממשק חייבת להיבחן מחדש גם ברמת אבטחה.
ובסוף התהליך, לא אשכח שראש הצוות אמר: “זה לא הבאג הכי חכם, זה הבאג הכי מתוחכם – כי בנינו אותו לבד מתוך רצון להשתפר.”
פוסט זה פורסם לראשונה בלינקדאין בתאריך 2025-07-21. — ארז מטולה
