برنامهنویسی امن، تمرین توسعه نرمافزارهای کامپیوتری است تا از ایجاد آسیبپذیریهای امنیتی بهطور تصادفی جلوگیری شود. نقصها، اشکالات و خطاهای منطقی بهطور مداوم علت اصلی آسیبپذیریهای نرمافزاری است. از طریق تجزیه و تحلیل هزاران آسیبپذیری گزارش شده، متخصصان امنیتی کشف کردهاند که بیشتر آسیبپذیریها به دلیل خطاهای برنامهنویسی رایج هستند. با شناسایی شیوههای نادرست برنامهنویسی که منجر به خطا میشوند و آموزش توسعه دهندگان، سازمانها میتوانند اقدامات پیشگیرانه ای را جهت کاهش یا حذف آسیبپذیریهای نرمافزاری قبل از استقرار در محیطهای عملیاتی آنها را از بین ببرند.
سرریز بافر، یک آسیبپذیری امنیتی نرمافزاری رایج میباشد، زمانی اتفاق میافتد که یک فرایند تلاش میکند دادههای بیشتری نسبت به ظرفیت بافر ذخیره کند. برای مثال، در صورتی که (۸ بخش) فضا برای ذخیرهسازی داشته باشیم، اگر تلاش کنیم یک فضای بیشتر (یعنی ۹ بخش) را مورد استفاده قرار دهیم خطا وجود خواهد داشت. در حافظه کامپیوتر دادههای سرریز شده ممکن است دادهها را در مکان بعدی بازنویسی کنند که میتواند یک آسیبپذیری امنیتی (انفجار پشته) یا خاتمه برنامه (segmentation fault) رخ دهد.
نمونه یک برنامه نوشته شده به زبان C که مستعد سرریز بافر است
int vulnerable_function(char * large_user_input) {
char dst[SMALL];
strcpy(dst, large_user_input);
}
اگر ورودی کاربر بزرگتر از بافر مقصد باشد، سرریز بافر رخ خواهد داد. برای رفع خطای این برنامه ناامن از سرریز بافر احتمالی از strncpy استفاده کنید.
int secure_function(char * user_input) {
char dst[BUF_SIZE];
//copy a maximum of BUF_SIZE bytes
strncpy(dst, user_input,BUF_SIZE);
}
یک جایگزین امن دیگر این است که به صورت پویا حافظه را با استفاده از malloc بگذارید .
char * secure_copy(char * src) {
size_t len = strlen(src);
char * dst = (char *) malloc(len + 1);
if(dst != NULL){
strncpy(dst, src, len);
//append null terminator
dst[len] = '\0';
}
return dst;
}
در قطعه کد بالا، برنامه تلاش میکند تا محتویات src را به dst کپی کند ، در حالی که همچنین مقدار بازگشتی malloc را بررسی میکند تا اطمینان حاصل شود که حافظه کافی برای مقصد buffer اختصاص داده میشود.
حمله رشته فرمت زمانی رخ میدهد که مهاجم ورودیهای خاصی را فراهم میکند که در نهایت به عنوان یک استدلال برای یک تابع که قالب بندی را انجام میدهد، مانند printf () وارد میشود. این حمله شامل خواندن دشمن یا نوشتن آن به پشته میشود.
عملکرد C printf خروجی را به stdout مینویسد. اگر پارامتر عملکرد printf به درستی فرمت نشده باشد، میتوان چندین اشکال امنیتی را به وجود آورد. برنامه زیر نمونه حمله رشته فرمت است.
int vulnerable_print(char * malicious_input) {
printf(malicious_input);
}
پارامترهای مخرب برای این برنامه میتواند شامل "٪ s٪ s٪ s٪ s٪ s٪ s٪ s" باشد، که سبب بروز خطا برنامه هنگام خواندن از بخش نامناسب حافظه میشود.
سرریز عدد صحیح زمانی اتفاق میافتد که عملیات محاسباتی یک عدد صحیح که در فضای موجود نمایش داده میشود بسیار بزرگ باشد. برنامه ای که به درستی برای سرریز عدد صحیح بررسی نمیشود، اشکالات و سوء استفادههای نرمافزاری بالقوه را به همراه دارد.
کد زیر تابعی در C ++ است که تلاش میکند تا تأیید کند که مجموع x و y کمتر یا برابر مقدار تعریف شده MAX است:
bool sumIsValid_flawed(unsigned int x, unsigned int y) {
unsigned int sum = x + y;
return sum <= MAX;
}
مشکل کد این است که سرریز عدد صحیح را چک نمیکند. اگر مجموع x و y بزرگتر از حداکثر مقدار احتمالی یک unsigned int
، عملیات اضافه شدن سرریز خواهد شد و احتمالاً در نتیجه یک مقدار کمتر یا برابر MAX خواهد بود، حتی اگر مجموع x و y بزرگتر از MAX باشد.
تابع زیر سرریز با تأیید مقدار بزرگتر یا برابر با x و y است. اگر مجموع سرریز شود، مجموع آن کمتر از x یا کمتر از y خواهد بود.
bool sumIsValid_secure(unsigned int x, unsigned int y) {
unsigned int sum = x + y;
return sum>= x && sum>= y && sum <= MAX;
}