מבוא:
integer overflow הינו אחד מהbuffer overflows הפחות נפוצים.
למעשה, הניצול של int overflow הוא למעשה "עזר" לניצול של heap overflow או stack overflow.
הנזק שint overflow יכול לגרום בכוחות עצמו הינו אפסי.
ובדיוק מהסיבה הזו, לא נ יתן למצוא מידע רב על הנושא ברחבי האינטרנט.
int overflow הרבה יותר קשה לגילוי מאשר שאר הbuffer overflows.
כמו כן, הנזק שלהם לא גדול, וקשה לנצלם.
כיצד נגרם int overflow:
הגורם ל int overflow הוא שלכל טיפוס,ואני מדגיש-לכל טיפוס, יש הגבלה בערך אותו הוא יכול להכיל.
כאשר אנחנו עוברים את הערך הזה, נוצר מצב משונה למדי, שעלול לגרום לבעיות שאותם ציינתי במבוא.
להלן תוכנית דוגמא על מנת להמחיש את העניין:
הערה: הגודל המאקסימאלי של חלק מהטיפוסים, למשל int תלוי במערכת, במסגרת מאמר זה אשתמש רק בטיפוסים אשר הערך המאקסימאלי שלהם גלובאלי לכל מערכות ההפעלה.
#include <iostream>
using namespace::std;
int main()
{
unsigned long n = 4294967295;
n++;
cout<<n<<endl;
return 0;
}
הערך המאקסימאלי של unsigned long הוא 4,294,967,295, כמו שאתם רואים, התוכנית מוסיפה לערך הזה אחד.
הפלט של התוכנית הוא 0.
הפלט הלא צפוי הזה נשלח אל המשתמש כיוון שההקצאה של המספר בתוך המשתנה מתבצעת בעזרת החישוב הבא:
(4294967295 + 1) % 4294967295, כאשר המשתנה אמור להכיל את השארית, שכרגע היא 0.
ניצול int overflow:
אז כמו שציינתי מקודם, הניצול של int overflow משמש בעצם לניצול של stack overflow או heap overflow,אפשרות לניצולם של פגיעויות אלו
מתרחשת כאשר מבוצע וידוי קלט בעזרת האינטיג'ר.
אני אדגים כיצד לנצל stack overflow בעזרת int overflow.
להלן תוכנית דוגמא, ומיד אחריה הסבר קצר:
#include <iostream>
using namespace::std;
int main(int argc, char *argv[])
{
char buffer[10];
unsigned short n;
int i=0;
if(argc<2)
{
cout<<"Usage: <buffer>"<<endl;
return 0;
}
n = strlen(argv[1]);
if(n > 10)
{
cout<<"Error, buffer size is too big"<<endl;
}
else
{
strcpy(buffer, argv[1]);
}
return 0;
}
כמו שאתם רואים, השתמשתי הפעם בunsigned short, שהערך המאקסימאלי שלו הוא 65535.
ממבט ראשון ניראה שבלתי אפשרי לגרום בקוד לstack overflow, כיוון שיש בדיקה שהbuffer בגודל המתאים.
בשביל לגרום לstack overflow, משתמשי לינוקס יכולים להשתמש בפקודה
perl -e 'print "A"x65537.
משתמשי ווינדאוס יכולים להוסיף לולאה קטנה בתוך התוכנית.
הסיבה שהstack overflow נגרם היא עקב העובדה שהאם נכניס 65536 תווים הערך של n, שמכיל את האורך המזוייף של הbuffer יהיה 1.
התגוננות:
ישנם דרכים מגוונות להתגוננות מפני ההתקפה הזו.
הדרך הפשוטה ביותר היא להשתמש בפונקציות הבטוחות יותר של libc.
(במקרה הזה בstrncpy).
int underflows:
סוגייה הקשורה לint overflow, היא הint underflow.
פגיעות זאת נדירה עוד יותר מהint overflow, אך עלולה לגרום ללא מעט צרות.
להלן קוד דוגמא, ומיד אחריו הסברים:
#include <iostream>
using namespace::std;
void allocbuffer(unsigned int size)
{
char *buffer;
size--;
buffer=new char[size];
}
ניראה תמים לחלוטין.
אבל, אם נריץ אות הפונקצייה עם פרמטר 0 בצורה הזו:
int main()
{
allocbuffer(0);
}
יווצר מצב בו הsize יהיה שווה ל-1,ומכאן השם של ההתקפה, underflow-הערך מתחת ל0.
אצל רובנו ההקצאה תיכשל, כי לא יהיה מספיק זיכרון ונקבל הודעת שגיאה.
ואצל מחשבים חזקים מספיק ההקצאה תיקח המון זיכרון.
מצב זה נגרם עקב העובדה ש-1 במקרה של unsigned integer ,שיכול להכיל רק מספרים חיוביים,שווה למספר גדול מאד.
סיום:
כמו שראיתם, int overflow זוהי התקפה נדירה, שבעד עצה לא יכולה לגרום להרבה נזק.
אם זאת, הינה קשה לגילוי וניתן לגרום בעזרתה להתקפות אחרות שיגרמו לא מעט נזק.
לינק לספר מעניין בנושא אבטחת מידע, שאללקוד, פגיעות אבטחה ועוד המון דברים תוכלו למצוא כאן.
ויקיפדיה על הצפת אינטג'ר.