
התקפות דה-סריאליזציה - מניפולציה בלתי מורשית של נתונים מסודרים לצורך ביצוע קוד זדוני - עלולות לגרום נזק חמור לארגונים. מפתחים וצוותי אבטחה חייבים לזהות באופן יזום פגיעויות מרכזיות שחושפות כיצד, מתי והיכן התרחשה ההתקפה.
דוגמה עדכנית לאיום זה היא CVE-2023-34040, וקטור מתקפת דה-סריאליזציה ב-Spring עבור Apache Kafka שיכול להוביל ל-RCE (ביצוע קוד מרחוק). למעשה, שכיחותן של פגיעויות דה-סריאליזציה מודגשת על ידי רשימת 10 המובילים של OWASP, הכוללת את "דה-סריאליזציה של נתונים לא מהימנים" כאחד מעשרת סיכוני האבטחה הקריטיים ביותר של יישומי אינטרנט.
כלים כמו OPSWAT MetaDefender Core™ עם SBOM שלו ( Software מנוע (Bill of Materials) חיוניים בזיהוי ומניעת התקפות ביטול סריאליזציה. אלה מאפשרים למפתחים לסרוק ולנתח ביעילות את הקוד שלהם, תוך הבטחה שלא יתעלמו מנקודות תורפה.
בבלוג זה, עמיתינו הבוגרים ידונו בפרטי CVE-2023-34040 ובניצולו, וכיצד לאבטח רכיבים בקוד פתוח מפני איומים דומים.
אודות CVE-2023-34040
CVE-2023-34040 חושף וקטור תקיפה של ביטול סידור ב-Spring עבור Apache Kafka, אשר ניתן לנצל כאשר מוחלת תצורה יוצאת דופן. פגיעות זו מאפשרת לתוקף לבנות אובייקט סידורי זדוני באחת מכותרות רשומת חריגות הביטול סידור, מה שעלול לגרום ל-RCE. הפגיעות משפיעה על Spring עבור Apache Kafka גרסאות 2.8.1 עד 2.9.10 ו-3.0.0 עד 3.0.9.

באופן ספציפי, יישום/צרכן פגיע תחת התצורות והתנאים הספציפיים הבאים:
- המחלקה ErrorHandlingDeserializer אינה מוגדרת עבור המפתח ו/או הערך של הרשומה.
- המאפיינים checkDeserExWhenKeyNull ו/או checkDeserExWhenValueNull של הצרכן מוגדרים כ-true.
- מקורות לא מהימנים מורשים לפרסם בנושא קפקא.
אפאצ'י קפקא
אפאצ'י קפקא, שפותח על ידי האפאצ'י Software Foundation, היא פלטפורמת הזרמת אירועים מבוזרת שנועדה ללכוד, לעבד, להגיב ולנתב זרמי נתונים בזמן אמת ממקורות שונים, כולל מסדי נתונים, חיישנים ו... mobile מכשירים.
לדוגמה, הוא יכול להזרים התראות לשירותים שמגיבים לפעילויות של לקוחות, כגון השלמת ביצוע רכישה של מוצר או ביצוע תשלום.

ב-Apache Kafka, אירוע - המכונה גם רשומה או הודעה - משמש כיחידת נתונים המייצגת אירוע ביישום בכל פעם שקוראים או כותבים נתונים. כל אירוע כולל מפתח, ערך, חותמת זמן וכותרות מטא-נתונים אופציונליות.
| מפתח-בינארי (יכול להיות ריק) | ערך בינארי (יכול להיות ריק) | ||||
| סוג דחיסה [אין, gzip, snappy, lz4, zstd] | |||||
כותרות (אופציונלי)
| |||||
| מחיצה + קיזוז | |||||
| חותמת זמן (מוגדרת על ידי המערכת או המשתמש) | |||||
אירועים מאוחסנים באופן עמיד ומאורגנים לפי נושאים. יישומי לקוח ששולחים (כותבים) אירועים לנושאי קפקא נקראים יצרנים, בעוד שאלו שנרשמים לאירועים (קוראים ומעבדים אותם) ידועים כצרכנים.

אביב לאפאצ'י קפקא
כדי לחבר את Apache Kafka עם המערכת האקולוגית של Spring, מפתחים יכולים להשתמש ב-Spring for Apache Kafka, מה שמפשט את האינטגרציה ביישומי Java.
ספרינג עבור אפאצ'י קאפקה מציעה כלים ו-APIs חזקים המפשטים את תהליך השליחה והקבלה של אירועים עם קאפקה, ומאפשרים למפתחים לבצע משימות אלו ללא קידוד נרחב ומורכב.

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

מכיוון שביטול סריאליזציה מאפשר המרה של זרם בתים או מחרוזת לאובייקט, טיפול לא נכון או חוסר אימות נאות של נתוני קלט עלולים לגרום לפגיעות אבטחה משמעותית, שעלולה להוביל להתקפת RCE.
ניתוח פגיעויות
לפי תיאור ה-CVE, OPSWAT העמיתים הגדירו את checkDeserExWhenKeyNull ואת checkDeserExWhenValueNull ל-true כדי להפעיל את פגיעות האבטחה. על ידי שליחת רשומה עם מפתח/ערך ריק וביצוע ניתוח מפורט על ידי ניפוי באגים בצרכן בזמן שקיבל רשומת Kafka מהיצרן, העמיתים הבוגרים שלנו חשפו את תהליך העבודה הבא במהלך עיבוד הרשומה:
שלב 1: קבלת רשומות (הודעות)
עם קבלת רשומות, הצרכן מפעיל את המתודה invokeIfHaveRecords() , אשר לאחר מכן קוראת למתודה invokeListener() כדי להפעיל מאזין רשומות רשום (מחלקה המצוידת בביאור @KafkaListener ) לצורך עיבוד הרשומות בפועל.

לאחר מכן, הפונקציה invokeListener() מפעילה את המתודה invokeOnMessage() .
שלב 2: בדיקת רשומות
בתוך המתודה invokeOnMessage() , מספר תנאים מוערכים מול ערך הרשומה ומאפייני התצורה, אשר קובעים לאחר מכן את השלב הבא שיש לבצע.

אם לרשומה יש מפתח או ערך ריק והמאפיינים checkDeserExWhenKeyNull ו/או checkDeserExWhenValueNull מוגדרים במפורש כ- true , תיקרא שיטת checkDeser() כדי לבחון את הרשומה.
שלב 3: בדיקת חריגה מכותרות
בפונקציה checkDesr() , הצרכן מפעיל באופן רציף את הפונקציה getExceptionFromHeader() כדי לאחזר חריגים מהמטא-דאטה של הרשומה, אם קיימים, ומאחסן את התוצאה במשתנה בשם exception .

שלב 4: חילוץ חריג מכותרות
המתודה getExceptionFromHeader() נועדה לחלץ ולהחזיר חריג מהכותרת של רשומת קפקא. תחילה היא מאחזרת את הכותרת של הרשומה ולאחר מכן מקבלת את ערך הכותרת, המאוחסן במערך בתים.

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

עם זאת, המחלקה DeserializationException מרחיבה את המחלקה הסטנדרטית Exception וכוללת בנאי עם ארבעה פרמטרים. הפרמטר האחרון, cause , מייצג את החריג המקורי שהפעיל את ה- DeserializationException , כגון IOException או ClassNotFoundException .

המחלקה Throwable משמשת כמחלקת-על עבור כל האובייקטים שניתן לזרוק כחריגים או שגיאות ב-Java. בשפת התכנות Java, מחלקות טיפול בחריגים כמו Throwable , Exception ו- Error ניתנות לביטול סידורי בבטחה. כאשר חריג עובר ביטול סידורי, Java מאפשרת לטעון ולהפעיל את האב Throwable של המחלקות עם בדיקות פחות תובעניות מאלה המוחלות על מחלקות רגילות.
בהתבסס על זרימת העבודה והניתוח המקיף, אם הנתונים המסודרים תואמים למחלקה זדונית שיורשת ממחלקת האב Throwable , היא עשויה לעקוף בדיקות תנאים. זה מאפשר ביטול סידור של אובייקט זדוני, אשר יכול לבצע קוד מזיק ולגרום באופן פוטנציאלי למתקפת RCE.
ניצול

כפי שצוין בניתוח, ניצול פגיעות זו דורש יצירת נתונים זדוניים הנשלחים לצרכן דרך רשומת הכותרת של Kafka. בתחילה, התוקף חייב ליצור מחלקה זדונית המרחיבה את המחלקה Throwable ולאחר מכן להשתמש בשרשרת גאדג'טים כדי להשיג ביצוע קוד מרחוק. גאדג'טים הם קטעי קוד הניתנים לניצול בתוך האפליקציה, ועל ידי שרשורם יחד, התוקף יכול להגיע ל"גאדג'ט שקיעה" שמפעיל פעולות מזיקות.
להלן מחלקה זדונית שניתן להשתמש בה כדי לנצל פגיעות זו ב-Spring עבור Apache Kafka:

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


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

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

הפחתת CVE-2023-34040 באמצעות SBOM ב- MetaDefender Core
כדי למתן ביעילות את הסיכונים הקשורים ל-CVE-2023-34040, ארגונים זקוקים לפתרון מקיף המספק נראות ושליטה על רכיבי הקוד הפתוח שלהם.
SBOM, טכנולוגיה בסיסית בתוך MetaDefender Core , מספק תשובה עוצמתית. על ידי שימוש כמלאי מקיף של כל רכיבי התוכנה, הספריות והתלויות הנמצאות בשימוש, SBOM מאפשר לארגונים לעקוב, לאבטח ולעדכן את רכיבי הקוד הפתוח שלהם בצורה פרואקטיבית ויעילה.

בעזרת SBOM, צוותי אבטחה יכולים:
- איתור מהיר של רכיבים פגיעים: זהה מיד את רכיבי הקוד הפתוח שנפגעו מהתקפות ביטול סריאליזציה. זה מבטיח פעולה מהירה בתיקון או החלפת ספריות פגיעות.
- ודא עדכון ותיקון יזום: ניטור רציף של רכיבי קוד פתוח באמצעות SBOM כדי להקדים את תשומת ליבם של פגיעויות ביטול סריאליזציה. SBOM יכול לזהות רכיבים מיושנים או לא מאובטחים, מה שמאפשר עדכונים בזמן והפחתת החשיפה להתקפות.
- שמירה על תאימות ודיווח: SBOM מסייע לארגונים לעמוד בדרישות התאימות, שכן מסגרות רגולטוריות מחייבות יותר ויותר שקיפות בשרשראות אספקה של תוכנה.
מחשבות סיכום
פגיעויות ביטול סריאליזציה הן איום אבטחה משמעותי שניתן להשתמש בו כדי לנצל מגוון רחב של יישומים. פגיעויות אלו מתרחשות כאשר יישום מבצע ביטול סריאליזציה של נתונים זדוניים, מה שמאפשר לתוקפים לבצע קוד שרירותי או לגשת למידע רגיש. הפגיעות CVE-2023-34040 ב-Spring עבור Apache Kafka משמשת תזכורת חדה לסכנות של התקפות ביטול סריאליזציה.
כדי למנוע התקפות דה-סריאליזציה, חיוני ליישם כלים מתקדמים כגון OPSWAT MetaDefender Core וטכנולוגיית SBOM שלה. ארגונים יכולים לקבל נראות עמוקה על שרשרת האספקה של התוכנה שלהם, להבטיח תיקון בזמן של פגיעויות ולהגן על עצמם מפני נוף האיומים המתפתח ללא הרף. אבטחה יזומה של רכיבי קוד פתוח אינה רק שיטת עבודה מומלצת - זוהי הכרח להגנה על מערכות מודרניות מפני ניצול אפשרי.
