Table of Contents
سرریزهای بافر یکی از مداوم ترین و خطرناک ترین آسیب پذیری های امنیتی در برنامه نویسی C هستند، علی رغم اینکه برای دهه ها به خوبی مستند شده اند، آنها همچنان به ایجاد مسائل جدی مانند فساد داده، سقوط سیستم و اجرای کد از راه دور ادامه می دهند. نوشتن کد C نیازمند درک عمیق از چگونگی وقوع سیل و یک رویکرد انضباطی برای جلوگیری از آنها است.
درک جریان های بافر Overflows
سرریز بافر زمانی اتفاق می افتد که یک برنامه داده های بیشتری را به یک بلوک پیوسته از حافظه (یک بافر) می نویسد تا بافر برای نگه داشتن اختصاص داده شود، از آنجایی که بافرها در حافظه پشته یا توده ای قرار دارند، بیش از مرزهای آنها بیش از حد از حد از حافظه مجاور بازنویسی می کند، این فساد می تواند حالت برنامه را تغییر دهد، رفتار غیر قابل پیش بینی را معرفی کند یا توسط یک مهاجم برای تزریق و اجرای کد خودسرانه مورد استفاده قرار گیرد.
عواقب آن بستگی به آنچه که بیش از حد نوشته شده است، بازنویسی آدرس بازگشت به پشته می تواند به کد کنترل شده مهاجم هدایت کند. بیش از حد اشاره کنندگان می توانند منجر به نوشتن حافظه خودسرانه شوند، حتی تصادف های ساده می توانند برای حملات انکار سرویس استفاده شوند.
جریان های Overflows
متغیرهای محلی، از جمله بافرهایی که در داخل توابع اعلام شده اند، در پشته ذخیره می شوند.این پشته همچنین آدرس بازگشتی، نقاط ذخیره شده و سایر داده های کنترل را در اختیار دارد.هنگامی که یک بافر خطی مانند بیش از حد ذخیره شده است، داده ها به آدرس بازگشت و فراتر از آن، بهره برداری های کلاسیک مانند کرم موریس (1988) از سرریز برای به دست آوردن دسترسی غیر مجاز استفاده می کردند.
جریان های Overflow
به طور پویا تخصیص داده شده بافر (از طریق ، ، و غیره) در توده قرار دارد، جریان های بیش از حد در اینجا می تواند متاداده های فاسد استفاده شده توسط تخصیص دهنده، منجر به تصادف و یا بهره برداری از طریق اسپری انبوه و یا حملات پس از استفاده از آن، سخت تر است.
توابع آسیب پذیر و جایگزین های امن آنها
کتابخانه استاندارد C چندین تابع را فراهم می کند که چک کردن مرزهای را انجام نمی دهند و استفاده از آنها رایج ترین علت سرریز بافر است. جایگزینی آنها با همتایان امن بهترین عمل اساسی است.
کپی رشته و Concatenation
- [[۱] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱] [۱۰] [۱] [۱] [۱] [۱] [۱]] [۱۰] [۱] [۱۰] [۱] [۱۰] [۱۰] [۱۰] [۱۰]] [۱۰] [۱۰]] [۱۰] [۳] [۳] [۱۰] [۳] [۱۰] [۳] [۱۰] [۳] [۳] [۳] [۱۰] [۳] [۳] [۱۰] [۳] [۳] [۳] [۱۰] [۱۰]] [۱۰] [۱۰]] [۳] [۳] [۱۰]]]]] [۳] [۳] [۳] [۱۰] [۳] [۳] [۳] [۳] [۱۰] [۱۰] [۱۰] [۳] [۱۰] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۱۰] [۱۰] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۱۰] [۱۰]
- بهتر است: - در دسترس در BSD و بسیاری از سیستم های لینوکس؛ همیشه خنثی و طول رشته منبع برای تشخیص توالی.
- [[[ویرایش] [۱] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰]] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰]] [۱۰]] [۱۰]] [۱۰]] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۱۰] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۱۰] [۳] [۳] [۳] [۳] [۱۰] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳]
خروجی و ورودی
- [[[ویرایش] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱]] [۱] [۱] [۱] [۱] [۱]] [۱] [۱] [۱۰] [۱]] [۱۰] [۱۰] [۱۰]] [۱۰]] [FLT: [۱۰] - [۱۰] [۱۰] [۱] [۱۰] [۱۰] [۳] [۳] [۱] [۱۰] [۳] [۳] [۳] [۳] [۱۰] [۱] [۱] [۳] [۱۰] [۳] [۱۰] [۳] [۳] [۳] [۳]] [۱۰]]]] [۳] [۳] [۳] [۱۰] [۳] [۳] [۳] [۳] [۱۰] [۱۰] [۱۰]]]]] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰]] [۱۰] [۱۰] [۳]] [۱۰] [۱۰] [۳] [۳] [۳] [۳] [۳] [۳]] [۳] [۳] [۳] [۱۰] [۱۰
- [[۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰]] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳
- - بسیار خطرناک؛ حذف شده از استاندارد C11 [FLT13] استفاده کنید.
- [[۱] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰]] [۱۰] [۱۰]] [۱۰]] [۱۰]] [۱۰]] [۱۰] [۳] [۱۰] [۳]] [۱۰] [۳] [۳]] [۳] [۳] [۳]] با مشخص کنندهٔ عرض، [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [۳] [
کپی حافظه و حرکت
- [در این باره] [[FLT] [FLT1] [FLT1]] [به جز [به]] [و [به جز]] [به اندازه امن نیست [و] [به اندازه [در برابر] و همیشه [در برابر [در برابر] اندازه [مشرکانت] مطمئن شوید.
- برخی از سیستم عامل ها (FLT 19) را از ضمیمه K (اختیاری در C11) ارائه می دهند، اما پذیرش محدود است.
اعتبار و مدیریت اندازه
حتی با عملکرد ایمن، شما باید طول ورودی را تأیید کنید، اندازه های بافر مناسب را تضمین کنید و به طور ماهرانه ای اندازه گیری بالقوه را کنترل کنید.
بررسی طول های ورودی
قبل از کپی یا پردازش ورودی خارجی ( ورودی کاربر، داده های شبکه، محتویات فایل)، حداکثر طول قابل قبول آن را تعیین کنید و داده های کوتاه یا کوتاه را که از آن فراتر می رود، رد کنید.
#define MAX_INPUT 255
char buffer[MAX_INPUT + 1]; // +1 for null
if (strlen(user_input) > MAX_INPUT) {
// Handle error: reject or truncate
fputs("Input too long", stderr);
return -1;
}
strncpy(buffer, user_input, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
استفاده از Buffer-Size با محدودیت های شناخته شده
هر زمان که امکان دارد، بافرها را با اندازه ثابت تعریف کنید و آن را در سراسر کد اجرا کنید.از آرایه های متغیر (VLAs) که می توانند باعث ایجاد سرریزی شوند اگر اندازه های بزرگ به جای آن عرضه شوند، به طور پویا با چک های اندازه واضح اختصاص دهید.
پرداخت هزینه های اضافی
توابع مانند و می توانند داده های کوتاه مدت را تنظیم کنند.با آگاهی از ارزش بازگشت برای تشخیص توالی و تصمیم گیری در مورد اینکه آیا داده های کوتاه قابل قبول است یا اگر یک خطا باید افزایش یابد.
پرچم های امنیتی Compiler و حفاظت از زمان
کامپایلرهای مدرن پرچم هایی را ارائه می دهند که تشخیص سر و صدا و کاهش بدون تغییرات کد را اضافه می کنند.
- [FLT3] / - قبل از بازگشت آدرس، کانکسان (معادلات غالب) را وارد کنید.
- [[۱] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱] [۱۰] [۱] [۱۰]] [۱۰] [۱۰] [۱] [۱۰] [۱۰]] [۱۰] [۳] [۳]] [۳]] و [FLT۲۷] با نسخه های چک شده که اگر بافرآیند، نیاز به کم است.
- [FLT 29] [FLT 1: 1] - جنگ در مورد آسیب پذیری های رشته فرمت که می تواند منجر به پرفرشته و یا نشت اطلاعات.
- - کد آدرس Sanitizerizer (ASan) برای تشخیص سر و صدا، استفاده پس از رایگان و دیگر خطاهای حافظه در زمان اجرا، کند اما برای تست ارزشمند است.
- [[۱] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰] [۱۰]] [۱۰] [۱۰] [۱]] [۱۰] [۱]] [۱۰] [۱]] [۱۰] [۱۰] [۱۰]] [۱۰] [۱]] [۱۰] [۱] [۱]] [۱۰] [۱] [۱] [۱] [۱] [۱۰] [۱] [۵] [۵] [۱] [۱] [۵] [بر [بر [بر [بر [بر [بر [بر [بر [بر [بر [بر [۵] [براى [براى [براى [براى [براى [براى [براى [براى [براى [براى [براى [براى [براى [براى [براى [براى [براى [براى [براى [براى [براى [براى [براى] [براى [براى [براى] [براى] [براى [براى [براى [براى [براى] [براى] [براى] [براى [براى] [براى [براى
سیستم حفاظت از سیستم عامل
کانaries Stack فقط یک لایه است. فن آوری های کاهش بهره وری در سیستم عامل های مدرن عبارتند از:
- پیشگیری از اعدام (DEP) / NX bit - مارک ها پشته و توده به عنوان غیر قابل اجرا، جلوگیری از اجرای کد پوسته.
- Address Space Configurationization (ASLR) - تصادفی آدرس های حافظه (stack، انبوه، کتابخانه های مشترک) را برای پیش بینی اهداف سخت تر می کند.
- [[۱] [۱۰] [۱] [۳] [۳] [۳] [۱]] - از [کتاب جهانی] فقط بخوانید.
ایمن کردن این حفاظت ها (معمولاً به طور پیش فرض) باعث افزایش بار برای بهره برداری می شود اما جایگزین برنامه نویسی امن نمی شود.
بررسی های کد و تحلیل استاتیک
بررسی انسانی همراه با تجزیه و تحلیل استاتیک خودکار می تواند مسائل سرریز بافر را زود بگیرد.این ها را در جریان کار توسعه خود ادغام کند.
- بررسی کد انسان ( - به دنبال استفاده از توابع ناامن، چک های اندازه از دست رفته و حلقه هایی که فراتر از مرزهای بافر می نویسند.
- ] [ ابزارهای تجزیه و تحلیل آماری - ابزارهایی مانند ، ] ، ] ، و سر و صدا بالقوه را تشخیص می دهند ، استفاده از توابع خطرناک و خطاهایی که می توانند در خط لوله CI اجرا شوند.
- - از libFuzzer، AFL یا دیگر فوززرها برای آزمایش خودکار ورودی با داده های غیر منتظره که ممکن است باعث پر شدن سیل شود، استفاده کنید.
نمونه های عملی از Secure Code
کپی های امن با Bounds Checking
#include <stdio.h>
#include <string.h>
int safe_string_copy(char *dest, size_t dest_size, const char *src) {
if (!dest || !src || dest_size == 0) {
return -1; // Invalid parameters
}
size_t src_len = strlen(src);
if (src_len >= dest_size) {
// Source too large; truncation or error
// Option: copy what fits and null-terminate
strncpy(dest, src, dest_size - 1);
dest[dest_size - 1] = '\0';
return 1; // Truncation occurred
}
strncpy(dest, src, dest_size);
// strncpy fills remaining with null, so dest_size fits; no need to null-terminate if src shorter
return 0; // Success, no truncation
}
ایمن Integerment for Buffer Sizes
سرریز بافر همچنین می تواند از سرریزهای صحیح در هنگام اندازه های محاسباتی ایجاد شود.همیشه قبل از تخصیص حساب را بررسی کنید.
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
void *safe_malloc_array(size_t nmemb, size_t size) {
if (nmemb == 0 || size == 0) {
return NULL; // Or handle zero-size allocation
}
if (nmemb > SIZE_MAX / size) {
// Integer overflow would occur
errno = ENOMEM;
return NULL;
}
return malloc(nmemb * size);
}
استفاده از snprintf برای رشته های فرمت شده
char log_message[256];
int ret = snprintf(log_message, sizeof(log_message),
"User %s logged in from %s", username, ip_address);
if (ret < 0) {
// Output error
} else if ((size_t)ret >= sizeof(log_message)) {
// Truncation occurred; handle if needed
}
بهترین تمرین های اضافی
- [[۱]:۰ [۱] [۱۰] [۱] [۱۰] [۱]] [۱۰] [۱]]- همیشه بافرهای صفر-initialize برای جلوگیری از نشت حافظه ی بی نظیر.
- [[۱] [۱۰] [۱] [۱۰] [۱] [۱]] [۱]] [۱]] [۱] [۱]] [۱]] [۱]] [۱] [۱]] [۱]] [۱]] [۱]] [۱]] [۱]] [۱]])) [برگشتهای عمیق [و از آن استفاده کنید یا عمق آن را محدود کنید.
- استفاده از [FLT 39] داور - کمک به کامپایلر بهینه سازی و ممکن است مسائل مربوط به بحث و گفتگو، هر چند به طور مستقیم جلوگیری از سرریز.
- [در این باره] پیش داوری اصلاح [[FLT1] - جلوگیری از اصلاح تصادفی رشته های ورودی و اجرای هدف.
- [در این باره] [در برابر [و] [از راه حق] خطا [از میان] [بر [و] [و [از این رو] [و [از این رو]] [و [از]]] [و [از]]] [و [به]] [و]] [و [به]] [و] [به] [و [و]] [و [و [و [و [و]]] [و [و [به [و [و [و [و [و [و [و]]]] [و [به [و [و [و [و [و [و [و [و [و [و]]]]]]]]]]] [و [و [به [و [و [به [و [و [و [و [و [و [و [و [و [و [و [و [از [از [از [از [به]]]]]]]]]]]]]]]]] [به [به [به [و [و [و [و [و [به [به [به [به [و [به [به]]]]]]]]
منابع برای یادگیری بیشتر
- I CERT Cding Standard [FLT 1] - قوانین جامع برای برنامه نویسی امن C.
- CWE-120: بافر کپی بدون بررسی اندازه ورودی - طبقه بندی MITRE از ضعف سر و صدا.
- جریان جریان [FLT 1] - راهنمایی عملی از پروژه امنیت وب باز.
- ]راهنمای کتابخانه GNU C: String and Array Utilities - مستندات برای توابع رشته امن.
- [[۱] [۱۰] [۱۰] [۱] [۱۰] [۱]] [۱]] [۱] [۱]] [۱] [۱]] [۱]] [۱] [۱] [۱]] [۱]] [۱] [۱] [۱]] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۳] [۱] [۳] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۳] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۳] [۱] [۱] [۳] [۱] [۱] [۱] [۱] [۱] [۱] [۳] [۱] [۱] [۳] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۱] [۳] [۳] [۱] [۱] [۳] [۱] [۱] [۱] [۱] [
نتیجه گیری
جلوگیری از سرریزهای بافر در C اختیاری نیست؛ مسئولیت اساسی هر توسعه دهنده ای است که با زبان کار می کند.با درک مکانیسم های سرریز، جایگزینی توابع خطرناک با گزینه های امن تر، به طور دقیق معتبر ورودی ها و اندازه ها، قادر به حفظ حفاظت از کامپایلر و استفاده از تجزیه و تحلیل استاتیک و آزمایش، شما می توانید به طور چشمگیری خطر این آسیب پذیری های مداوم را کاهش دهید.هیچ تکنیک منفرد کافی نیست؛ در ترکیب عمیق کد نویسی، و مطمئن است، و مطمئن ترین روش های کد نویسی، و کد نویسی دقیق، می تواند به طور مداوم با استفاده از طریق سیستم های کد نویسی دقیق و اصلاح دقیق، و کنترل دقیق، و سیستم های کد نویسی دقیق، و کنترل دقیق، و سیستم های کد نویسی دقیق، و کنترل دقیق، و کنترل دقیق، و کد نویسی دقیق، و اطمینان از طریق سیستم های کد نویسی دقیق، و اجرای دقیق، و اجرای کد های کد نویسی، و اجرای دقیق، و سیستم های کد نویسی دقیق، و کنترل سیستم های کد نویسی، به شما را فراهم کند: شما را فراهم کند: یک سیستم های کد های کد نویسی، و کنترل دقیق، و کنترل دقیق، و اجرای دقیق، و اجرای دقیق، و کنترل دقیق، به یاد ماندنی، به طور دقیق، و کنترل دقیق،