الهندسة المدنية والهيكلية
كيفية كتابة مدونة تأمين C لمنع تدفق بوفر
Table of Contents
ولا تزال تدفقات الازدحام تشكل أحد أكثر مواطن الضعف الأمنية استمرارا وخطورة في البرمجة جيم، ورغم أنها موثقة توثيقا جيدا منذ عقود، فإنها لا تزال تتسبب في قضايا خطيرة مثل فساد البيانات، وهدمات النظام، وتنفيذ الرموز عن بعد، وتستلزم صياغة مدونة " جيم " فهما عميقا للكيفية التي تحدث بها التدفقات العازلة، ونهجا منضبطا لمنعها، وتوفر هذه المادة دليلا شاملا لكتابة وظائف قوية ومتجاوزة في مجال الحماية، تشمل المفاهيم الأساسية.
فهم تدفق بوفر
ويحدث تدفق احتياطي عند كتابة برنامج بيانات إلى مجموعة من الذاكرة (العازل) غير المُخصصة للاحتفاظ بها، حيث أن العازل تقيم في الذاكرة الخفيفة أو الخندقية، بما يتجاوز حدودها تُغشِّي مواقع الذاكرة المتاخمة، ويمكن أن يغير هذا الفساد حالة البرنامج، ويُحدث سلوكاً لا يمكن التنبؤ به، أو يستغله مهاجم ليحقن وينفذ شفرة تعسفية.
وتتوقف النتائج على ما يُخطى أكثر من اللازم، ويمكن أن يؤدي تخطي عنوان العودة على الحزمة إلى إعادة توجيه الإعدام إلى الرمز الذي يتحكم فيه المهاجمون، ويمكن أن يؤدي الكتابة المفرطة إلى كتابة الذاكرة التعسفية، بل يمكن أن تُستغل حوادث التصادم البسيطة في هجمات رفض الخدمة، علما بأن الميكانيكيين هم الخطوة الأولى في الوقاية.
تدفقات متداخلة
وتخزن المتغيرات المحلية، بما فيها العوازل المعلن عنها داخل الوظائف، على كومة المتغيرات، كما تحتفظ المجموعة بعنوان العودة، وأجهزة تحديد الإطار المنقذ، وغيرها من بيانات المراقبة، وعندما تُتجاوز الحدود، تُسرب البيانات إلى عنوان العودة وما بعده، وتستخدم المستغلات الكلاسيكية مثل دودة موريس (1988) تدفقات متداخلة للحصول على وصول غير مأذون به.
تدفقات مكثفة
وتقيم الحاجيات الموزعة صبغة دينامية (عن طريق ]، ، إلخ]، على السحب، ويمكن أن تؤدي التدفقات الزائدة إلى الفاسدة التي يستخدمها المشغل، مما يؤدي إلى تحطم أو استغلال عن طريق رذاذ الكعب أو شن هجمات خالية من الاستخدام، ويصعب استغلال تدفقات الحرارة، ولكنها أيضاً خطرة.
الوظائف العامة القابلة للتأثر وبدائلها الآمنة
وتوفر المكتبة الموحدة " جيم " عدة مهام لا تؤدي التحقق من الحدود، واستخدام هذه المهام هو أكثر الأسباب شيوعاً للتدفقات العازلة، واستردادها بنظراء أكثر أماناً هي أفضل الممارسات الأساسية.
الطباعة والتصنيف
- - Unsafe: copies until a null terminator, no length limit.
] Safe alternative: n] - copies at most n characters; note than it does not nullly-termin. - والأفضل من ذلك: - متاح على BSD والعديد من نظم لينكس؛ ويبطل دائماً مدة سلسلة المصادر لكشف التكتل ويعيدها.
- ] - Unsafe: concatenates without bounds.
]] Safe alternative: - appends at most n characters and always null-terminates.
النواتج المرسمة والمدخلات
- - Unsafe: writes formatted output to a buffer with no size check.
] Safe alternative:] - limits output to size-1 characters plus null terminator. - ] ] - مخاطر مماثلة؛ استخدام بدلاً من ذلك.
- ] - خطر للغاية؛ أزيل من معيار C11. Use بدلاً من ذلك.
- ] ] - لا يوجد فحص للقيدات، استخدام أو مع تحديد المواصفات الميدانية.
نسخة تذكارية وتحرك
- ] - آمنة فقط إذا تم التحقق من عدم تجاوز حجم المقصد العازل.
] ] Safer alternative: (handles overlapping) and always ensure n dest size. - Some platforms provide ] from Annex K (optional in C11), but adoption is limited.
التقييم وإدارة الحجم
حتى مع الوظائف الآمنة، يجب أن تتأكد من طول المدخلات، وتكفل الأحجام الحاجزة الصحيحة، وتعامل مع التهوية المحتملة بشكل جيد.
تحقق من المدخلات
وقبل نسخ المدخلات الخارجية أو تجهيزها (مدخلات المستعملين، وبيانات الشبكة، ومحتويات الملفات)، تحدد المدة القصوى المقبولة وترفض أو تُدير البيانات التي تتجاوزها.
#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';
استخدام بافيرز ذات الحجم الثابت مع حدود معرفة
(ب) تحديد العوازل ذات الحجم الثابت وإنفاذها في جميع أنحاء المدونة، مع تجنب السلاسل المتغيرة التي يمكن أن تسبب تدفقاً زائداً إذا تم توريد أحجام كبيرة، وبدلاً من ذلك، توزع دينامياً مع عمليات تفتيش واضحة للحجم.
ترسبة اليدين
ويمكن أن تُراجع البيانات من خلال مهام مثل و، ومعرفة قيمة العودة لكشف التكتل واتخاذ قرار بشأن ما إذا كانت البيانات المهددة مقبولة أو إذا كان ينبغي إثارة خطأ، ويمكن للتركة الشائكة أن تترك العوازل في حالة غير متوقعة.
كتلة من أجهزة الأمن والحماية في أوقات العمل
المجمّعين الحديثون يقدمون أعلاماً تضيف كشفاً للتدفقات العازلة والتخفيف من حدتها بدون تغيير رمزيّ، وتمكنهم من الوصول إلى نظام البناء الخاص بك
- ]/ - Inserts stack canaries (random values) before return address. وإذا كان التدفق العازل يُعدل الكناري قبل تعديل عنوان العودة، يلغي البرنامج قبل إتمام الاستغلال.
- ] - يستعاض عن المكالمات التي توجه إلى وظائف غير مأمونة مثل و] بنسخ مدققة تلغي إذا كانت حاجزة الوجهة صغيرة جداً.
- ] ] - Warns about format string vulnerabilities that can lead to buffer overflows or information leaks.
- ] - رمز صكوك شركة Sanitizer (ASan) لكشف التدفقات الاحتياطية، والإفراط في الاستخدام، وغير ذلك من أخطاء الذاكرة في الوقت الحاضر، ويبطئ التنفيذ، ولكنه لا يقدر على الاختبار.
- ] ] - تجنب إجراء عمليات تفتيش على التدفق الزائد (استخدام بحذر).
نظام التشغيل
إن قنوات السلاسل هي طبقة واحدة فقط، وتشمل تكنولوجيات التخفيف من آثار السلاسل في النظم الحديثة ما يلي:
- Data Execution Prevention (DEP) / NX bit] — Marks stack and heap as non-executable, preventing shellcode execution.
- Address Space Layout Randomization (ASLR)] - Randomizes memory addresses (stack, heap, shared Library) to make it hard to predict targets.
- Relocation Read-Only (RELRO)] - Protects GOT (Global Offset Table) from overwriting.
ويؤدي التمكين من الحصول على هذه الحماية (عادة ما يكون تقصيرا) إلى رفع الحانة من أجل الاستغلال، ولكنه لا يحل محل الترميز الآمن.
مراجعة الحسابات والتحليلات القانونية
ويمكن لاستعراض البشر، بالاقتران مع التحليلات الثابتة الآلية، أن يلحقوا قضايا التدفق العازل في وقت مبكر، وأن يدمجوا هذه المسائل في تدفق العمل الإنمائي.
- Manual code review] - look for uses of unsafe functions, missing size checks, and cycles that write beyond buffer boundaries.
- Static analysis tools] - Tools like , , ], and detect potential overflows, use of dangerous functions, and off-by-one errors. They can be run in CIs.
- Fuzzing] - Use libFuzzer, AFL, or other fuzzers to automatically test input handling with expected data that may trigger overflows.
أمثلة عملية على المدونة المضمونة
نسخة مأمونة من الـ"بيوند"
#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
}
معالجه مأمونه لحجم بافير
يمكن أن ينتج التدفق الزائد عن السائل المزود بالبخار عن ارتفاع حجمه عند حسابه، دائماً تفقد الحساب قبل التخصيص.
#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);
}
استخدام البصمات لـ "السترينات المُصمّمة"
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 buffers] - always zero-initialize buffers to avoid leaking uninitialized memory.
- تجنب تكرار بعمق غير مربوط - يمكن أن تحدث تدفقات زائدة من التكرار العميق؛ استخدام التكرار أو الحد من العمق.
- Usese ] qualifier] - helps the compilationr optimize and may catch aliasing issues, though not directly preventing overflows.
- Prefer -correctness] - Prevents accidental modification of input strings and enforces intent.
- Implement error handling] - لا تتجاهل قيم العودة من وظائف مثل ، ، ، الخ.
الموارد المخصصة لمواصلة التعلم
- SEI CERT C Coding Standard ] - comprehensive rules for secure C coding.
- CWE-120: Buffer copy without checking Size of Input] - MITRE’s classification of buffer overflow weaknesses.
- OWASP Buffer Overflow] - Practical guidance from the Open Web Application Security Project.
- GNU C Library Manual: String and Array Utilities] - Documentation for safe string functions.
- AddressSanitizer] - جهاز كشف سريع لخطأ الذاكرة.
خاتمة
إن منع تدفق الحاجات الاحتياطية إلى جيم ليس اختياريا؛ بل هو مسؤولية أساسية عن أي مطور يعمل مع اللغة، وبفهم آليات التدفقات الزائدة، وباستبدال الوظائف الخطرة ببدائل أكثر أمنا، والتحقق الصارم من المدخلات والأحجام، وتمكين المجمع من الحماية، واستخدام التحليل والاختبارات الثابتة، يمكن أن تؤدي بشكل كبير إلى الحد من خطر هذه الضعف، ولا توجد طريقة واحدة كافية، والدفاع عن كثب - وضع ضوابط للتخفيف من حدة الآثار.