מטושטשת חלק 1

מטושטש חלק 1: התיאוריה

מבולבל

קודם כל, מה זה מטושטש בדיוק? כאשר אנו בודקים תוכנית או פונקציה שמקבלת קלט (כל סוג של קלט), אנו מנסים שילובים שונים של קלט עד שנקבל ריסוק או תוצאה רצויה אחרת (לעיתים קרובות דליפות זיכרון). כאשר תוכנית לא מחטאת את הקלט שלה כראוי, קלט שגוי או לא תקין עלול להגיע מהמשתמש, מה שעלול לגרום לקריסות ולהתנהגות מוזרה או לא מוגדרת. דוגמה טובה ל-fuzzing שבטח שמעתם עליה בעבר היא משמימה, כאשר אנו מנסים כתובות אתרים שונות, ראשית מתחילים בכתובות אתרים נפוצות עד שאנו מוצאים ספריות לגיטימיות באתר. כלים כמו פוף לעשות בזה עבודה מצוינת.

Fuzzing שימושי במיוחד בתוכניות שנכתבו בשפות ברמה נמוכה או ישנות יותר, כמו Basic, Assembly, C/C++ וכו', שאינן מונעות מהמתכנת לכתוב טעויות כמו שגיאות כתיבה לא תקינות, שימוש לאחר פנוי [של מצביע], או הצפת זיכרון (מאגר, מחסנית, מספר שלם), שבדרך כלל לא בהכרח מובילות לקריסות בזמן ריצה או שגיאות בזמן הידור ויכול להיות מנוצל על ידי תוקף ממולח. בדרך כלל, כאשר מוזכר המונח 'פיוז', הוא מתייחס לסוג זה של מטוש.

סוגי טשטוש

ישנן שלוש גישות לטשטוש שעלינו למנות.

Whitebox Fuzzing

ב-whitebox fuzzing אנו מתייחסים לסוג של fuzzing שבו ה-fuzzer מנסה לנתח את המבנה הפנימי של התוכנית על מנת לעקוב ולמקסם את כיסוי הקוד. כיסוי קוד מתייחס לשיעור הסניפים אליהם הגענו בקוד שלנו; בכל פעם אמירה מותנית כמו if or בזמן מופעל, הקוד מתפצל לענף אחד שבו ההצהרה אמת, ואחר שבו הוא שקר. הרציונל הוא שאם מסתתרת שגיאה בסניף כלשהו, ​​ראשית עלינו לוודא שהגענו לסניף הזה מלכתחילה. כדי לבצע ניתוח מסוג זה, התוכנית חייבת להיות מוכשרת במהלך ההידור.

המכשור עובד על ידי קריאה לפונקציה מיוחדת בכל פעם שסניף מופעל, אשר רושם אותו כאילו הופעל, לפעמים אפילו ברזולוציה של איזה קו, כך שניתן יהיה לעקוב אחר הכיסוי. מכשור יכול גם לעזור למצוא באגים. לדוגמה, Address Sanitation (ASan) עוזר למצוא דליפות זיכרון שבדרך כלל אינן גורמות לקריסות. מכיוון שניתוח מבני מלא דורש משאבים רבים, ה-whitebox fuzzing הוא איטי, אבל הרבה יותר יעיל במציאת באגים ופגיעויות, במיוחד כאלה החבויות עמוק בתוכנית. כמובן שכדי לבצע מכשור נרחב צריך לקבל גישה לקוד המקור, שלא תמיד זמין, במיוחד בתור תוקף.

Blackbox Fuzzing

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

Graybox Fuzzing

גישה זו מנסה למצוא איזון בין היתרונות והחסרונות של הגישות הנ"ל; הוא משתמש במכשור קל במהלך זמן ההידור במקום בניתוח מלא על מנת לחשב כיסוי קוד ולעקוב אחר מצב התוכנית. ה-fuzzers הפופולריים ביותר כיום, כמו AFL, HongFuzz ו-LibFuzzer הם fuzzers Graybox. על מנת לבצע טשטוש כזה, בדרך כלל יש צורך בקוד המקור, אך יש דרכים לעקיפת הבעיה אם רק קובץ הפעלה זמין, אך הם פוגעים בביצועים. במאמר זה לא אגע בטכניקות אלו.

טכניקות של Fuzzing

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

Fuzzing מבוסס מוטציות

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

הכלי הידוע ביותר (וככל הנראה ה-fuzzer הידוע ביותר באופן כללי) הוא AFL, או אמריקן פאזי לופ.

AFL משתמש בשלושה סוגים של מוטציות בסיסיות:

  • מחיקה של סיביות אקראית.
  • הכנסת סיביות אקראית.
  • היפוך של סיביות אקראית (מ-0 ל-1 או להיפך)

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

טשטוש דקדוק

אתה בוודאי מודע לכך שתוכניות רבות אינן יכולות לקבל קלט לא מובנה, אך יש להן כללים ספציפיים כיצד ניתן ליצור קלט. כללים אלו נקראים תחביר הקלט, מכיוון שהם דומים לכללים תחביריים בשפות מדוברות. על מנת לבחון תוכניות מסוג זה באופן שיכסה את רוב האפשרויות התחביריות, ה-fuzzer חייב להיות מודע לתחביר, אחרת, קלט שנוצר באמצעות מוטציות פשוטות יסונן ויימחק. כלים כאלה כבר קיימים, ויכולים לטשטש JavaScript, WASM, URL ואחרים. אבל נכון לכתיבת המאמר הזה, רובם כולם ניסיוניים ואיטיים, ולמיטב ידיעתי, כולם כתובים ב-Python, שזה נהדר עבור אב טיפוס והדגמות, אבל לא כל כך עבור fuzzers בדרגת ייצור אופטימלית. לכן, הם משמשים לעתים רחוקות.

הבא - חלק 2

בפרק הבא"מסתבך עם AFL", אני מדגים כיצד לטשטש תוכנית פשוטה באמצעות AFL כדי למצוא קריסות שעלולות להיות מסוכנות בעולם האמיתי.

עבור לתוכן