פופולריות של שפת תכנות לא מבטיחה את את טיבה

חברת Digium (המפתחת העיקרית של Asterisk) שחררה בלילה (או באמצע יום העסקים האמריקאי) 4 דיווחים על פרצות אבטחת מידע:

  1. 2 גלישות חוצץ (Buffer Overflow) במימוש RTP.
  2. דילוג על מערכות זיהוי, ויכולת למשתמש פשוט להשתמש בשירותים שדורשים הזדהות (מדובר על פרוטוקול SIP).
  3. בעיית Format String, אשר איתה אפשר להגיע ממש כמו Buffer overflow למחוזות הזכרון ה"סגור" של מערכת ההפעלה, ואף להריץ קוד זדוני על השרת.
  4. מזהה צפוי מידי לבקשות Manager.

פרט ל2 ו 4, הבעיות הן בעיות של שפת C עצמה (בה Asterisk כתוב). למעשה אם Asterisk, היה נכתב למשל בפסקל (לא ברמת קוד בית ספר, אלא ברמה המקצועית שלו), יש סיכוי הרבה יותר נמוך, שהבעיות הללו לא היו מתרחשות, גם אם לא כולם באמת יודעים לתכנת בשפה עצמה.

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

למשל מאוד פשוט להימנע מ Format String:

פשוט לא עושים את הדבר הבא:

sprintf("%s" + s_var, string_content)

אלא עושים את הפעולה הבאה:

sprintf("%s%s", string_content, s_var)

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

טוב אני יודע שאתם עצלנים, אז הנה בגדול מאוד: יש החלפה של %s (לפי הוראות מסויימות שיכולות אף הן להופיע), עכשיו בגלל ש C עובד עם מצביעים בשביל בערך כמעט כל דבר אפשרי, ההחלפה של התווים נעשת ע"י לולאה על כתובות זכרון, ואני פשוט יכול לגרום לכתובת הזכרון לגלוש אל מחוץ לטווח שהוקצא, ואז אני יכול לעשות כל מה שאני רוצה במערכת, אם זה ללכת ולהביא מידע אחר שקיים בזכרון (מפרוסס אחר לגמרי שהמערכת הפעלה מריצה), ועד ליכולת להריץ קוד בצורות אלו ואחרות (אני לא אכנס מן הסתם איך עושים את זה).

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

snprintf, strncpy, strncat ואחרים, אשר כולם מקבלים גבול מסויים, ורצוי לתת לו את הגבול שלא עובר את גודל ההקצאה של אותו חוצץ, אחרת אם ניתן לו יותר מזה, תהיה גלישה, ואז נוכל להריץ קוד זדוני על המחשב, או גם לטייל בזכרון. העניין הוא שב C, יש פקודות אשר לא מכילות את זה, ובמקום לגרום להם להיות obsolete ויותר חשוב, אפילו לגרום להם להפסיק להתקיים, הן עדיין מתקיימות, ואם זה לא מספיק גרוע, אז בבתי ספר ואוניברסיטאות/מכללות, מלמדים להשתמש בהם, במקום במתן גבולות, דבר שיוצר מפתחים חסרי ידע והבנה אמיתי לגבי תכלואי השפה, והצורה להתמודד איתה.

אז למה בפסקל זה אולי לא יגרם ? ובכן בפסקל, יש לנו מצביעים, אנחנו יכולים לקבל Buffer overflow ואפילו Format string, אבל כאשר אני כותב קוד שלא אמור להתממשק עם C, בד"כ אני לא אשתמש במצביע ככה סתם, כי יש לי כלים וצורות עבודה הרבה יותר יעילות לנושא.

סתם חומר למחשבה.

4 מחשבות על “פופולריות של שפת תכנות לא מבטיחה את את טיבה

  1. צפריר כהן

    בעיית format string היא דווקא דוגמה לסוג הבעיות הטיפוסיות לשפות דינמיות. ב־C דבר כזה הוא באג. בשפות דינמיות היכולת הזו היא feature ולכן הקומפיילר לא מתריע עליו באופן כה חמור.

    הבעיה שם היתה יותר דבילית:

    http://svn.digium.com/view/asterisk?view=rev&revision=109488

    שים לב לשינוי אחר מהימים האחרונים:
    http://svn.digium.com/view/asterisk-addons?view=rev&revision=556

    פשוט התעלמו מאזהרות.

    אם תבדוק את הקוד של אסטריסק, תראה שלא משתמשים שם ב־strcpy וגם לא ב־sprintf . ב־snprintf כן משתמשים. אבל במקום strncpy הם משתמשים ב־ast_copy_string .

    ועכשיו נעבור להסתכל על השגיאה הראשונה:
    http://svn.digium.com/view/asterisk?view=rev&revision=109386

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

  2. ארתיום

    קודם כל: printf("%s" + s_var, string_content מי כותב ככה וגם מי מלמד ככה$%^#$%^#$% לא ראיתי שמישהו ילמד ככה. בנוסף להכל אי אפשר לחבר סטרינגים ככה ב-C.

    ואכן, *לא* משתמשים ב-sprintf אלא ב-snprintf ועוד ועוד. נושא של secure programming הוא נושא בפני עצמו.

    אגב (ל-sprintf יש עוד פרומטר 🙂 )

  3. ik_5 מאת

    העניין הוא שלא מלמדים איך עושים דברים נכון.

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

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

    בקשר לsprintf, יכול להיות, עבדתי מזכרון בלבד ולא בדקתי את עצמי.

להשאיר תגובה

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

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת /  לשנות )

תמונת גוגל

אתה מגיב באמצעות חשבון Google שלך. לצאת מהמערכת /  לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת /  לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת /  לשנות )

מתחבר ל-%s

אתר זו עושה שימוש ב-Akismet כדי לסנן תגובות זבל. פרטים נוספים אודות איך המידע מהתגובה שלך יעובד.