מה זה סריאליזציה, ולמה כל תוכנה בעצם משתמשת בה¶
זה אחד המושגים ששומעים שוב ושוב בעולם התכנות, ובאבטחת מידע, ורוב האנשים משתמשים בו כל יום בלי לדעת שיש לו בכלל שם. סריאליזציה - Serialization - היא רעיון בסיסי ופשוט להבנה, וברגע שתבינו אותו, תגלו שהוא נמצא כמעט בכל מקום שבו תוכנה שולחת או שומרת מידע.
הבעיה שסריאליזציה פותרת¶
כשתוכנית רצה, היא מחזיקה מידע בזיכרון בצורת אובייקטים - מבנים מורכבים עם שדות, ערכים, וקשרים ביניהם. למשל, אובייקט "משתמש" יכול להכיל שם, גיל, ורשימה של הזמנות שהוא ביצע. הבעיה היא שהאובייקט הזה קיים רק בזיכרון של אותה תוכנית ספציפית, ברגע נתון. אי אפשר פשוט "לשלוח" אותו כמו שהוא ברשת לתוכנית אחרת, ואי אפשר גם לשמור אותו כמו שהוא בקובץ על הדיסק.
וכאן בדיוק נכנסת סריאליזציה. זה התהליך שבו לוקחים את האובייקט המורכב הזה, וממירים אותו לצורה פשוטה יותר - בדרך כלל טקסט או רצף בייטים - שאפשר לשלוח, לשמור, או להעביר בין מערכות שונות. דה-סריאליזציה - Deserialization - היא התהליך ההפוך - לוקחים את הטקסט או הבייטים האלה, וממנו בונים מחדש את האובייקט המקורי, עם כל השדות והערכים שלו.
דוגמה שכולם מכירים בלי לדעת¶
כל פעם שאתם משתמשים באתר שמדבר עם שרת דרך API, יש שם סריאליזציה בפעולה. הדפדפן שולח בקשה, השרת מעבד אותה בזיכרון בעזרת אובייקטים, ואז לפני ששולחים תשובה בחזרה, ממירים את האובייקט הזה לפורמט טקסטואלי כמו JSON:
זה בדיוק תהליך הסריאליזציה - אובייקט "משתמש" בזיכרון של השרת הפך למחרוזת טקסט שאפשר לשלוח ברשת. כשהדפדפן, או תוכנית אחרת, מקבל את הטקסט הזה, הוא מבצע דה-סריאליזציה - הופך אותו בחזרה לאובייקט שאפשר לעבוד איתו בקוד.
לא רק JSON - כמה פורמטים נפוצים¶
JSON הוא רק אחד מכמה פורמטים שמשמשים לסריאליזציה, וכל אחד מתאים למטרה קצת שונה:
- JSON. הפורמט הכי נפוץ כיום לתקשורת בין דפדפן לשרת ובין שירותים שונים, בזכות זה שהוא קריא לבני אדם וקל לעבוד איתו כמעט בכל שפת תכנות.
- XML. פורמט ותיק יותר, עדיין נפוץ במערכות ארגוניות ותיקות ובחלק מהתקשורת בין שירותים ברמת ארגון.
- פורמטים בינאריים. פורמטים כמו Protocol Buffers משמשים כשחשוב שהנתונים יהיו קטנים ומהירים לעיבוד, במחיר של קריאות פחות נוחה לבני אדם.
- פורמטים מובנים של שפת תכנות. שפות רבות, כמו Java, Python ו-PHP, מגיעות עם מנגנון סריאליזציה מובנה משלהן, שמאפשר לשמור כמעט כל אובייקט בשפה בלי המרה ידנית.
הבחירה בפורמט תלויה בצורך - אם צריך תקשורת פשוטה בין דפדפן לשרת, JSON כמעט תמיד המנצח. אם צריך ביצועים גבוהים בתקשורת פנימית בין שירותים, פורמט בינארי יכול להיות עדיף.
למה זה כל כך שימושי¶
בלי סריאליזציה, כל תקשורת בין מערכות שונות, ואפילו שמירה פשוטה של מידע לקובץ, הייתה הרבה יותר מסובכת. היא מאפשרת כמה דברים שהיום נראים מובנים מאליהם:
- לשמור מצב של תוכנית לקובץ, ולטעון אותו מחדש מאוחר יותר בדיוק כפי שהיה.
- לשלוח מידע מורכב בין שרת ולקוח, גם אם הם כתובים בשפות תכנות שונות לגמרי.
- לשמור עוגיית סשן שמכילה מידע על המשתמש, ולבנות אותה מחדש בבקשה הבאה.
- לתקשר בין מיקרו-שירותים שונים במערכת גדולה, כשכל שירות לא יודע (ולא צריך לדעת) איך השירות השני בנוי מבפנים.
מתי זה נהיה נושא אבטחתי¶
עד כאן דיברנו על סריאליזציה כרעיון תכנותי נייטרלי לגמרי, אבל שווה לדעת שהתהליך הזה, כשהוא לא מטופל בזהירות, יכול להפוך לנקודת תורפה רצינית. בכמה שפות תכנות, תהליך הדה-סריאליזציה לא רק "קורא נתונים" - הוא בפועל יכול להריץ קוד כחלק מבניית האובייקט מחדש. אם שרת מבצע דה-סריאליזציה על נתונים שהגיעו ממקור לא מהימן, בלי בדיקה מספקת, זה יכול לפתוח דלת לתוקף.
אם תרצו להעמיק בצד ההתקפי של הנושא הזה - איך תוקפים בפועל מנצלים דה-סריאליזציה לא מאובטחת - כתבנו על זה בהרחבה בפוסט נפרד שמתמקד ספציפית בחולשה הזאת.
אם אתם רוצים להעמיק בהבנת אתרים ואפליקציות ווב בצורה מסודרת ומעשית, כולל איך נתונים זורמים בין דפדפן לשרת, מוזמנים לעבור על קורס פריצת אתרים למתחילים.
ואם יש לכם שאלות בדרך, יש קהילה שמחה לעזור.
לסיכום¶
סריאליזציה היא אחד הרעיונות הכי בסיסיים ונפוצים בתכנות - הדרך שבה תוכנות הופכות אובייקטים מורכבים לצורה שאפשר לשלוח או לשמור, ובחזרה. היא נמצאת כמעט בכל מקום, מה-API הפשוט ביותר ועד למערכות הענק ביותר, וההבנה שלה היא בסיס טוב, גם לפני שמדברים בכלל על הסיכונים האבטחתיים שיכולים להתלוות אליה.