أمان تطبيقات C++: أهم 10 ثغرات أمنية للمبتدئين

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة
```html

مقدمة: لماذا تعتبر أمان كود C++ أمرًا بالغ الأهمية؟

C++ هي واحدة من أقوى اللغات وأكثرها أداءً، لكن مرونتها تتطلب مسؤولية عالية من المطور. على عكس العديد من اللغات الحديثة التي تدير الذاكرة تلقائيًا (Java, Python)، يوفر C++ وصولًا مباشرًا إلى الذاكرة وموارد النظام. وهذا يفتح مجالًا واسعًا للهجمات: من تجاوز سعة المخزن المؤقت إلى تسرب البيانات.

بالنسبة لمطوري C++ المبتدئين، فإن فهم نقاط الضعف النموذجية ليس مجرد نظرية، بل ضرورة. خطأ بضعة أسطر يمكن أن يؤدي إلى انهيار الخادم، أو تسرب كلمات المرور، أو تنفيذ كود عشوائي من قبل المهاجم. في هذه المقالة، سنستعرض أهم 10 نقاط ضعف شائعة في C++ مع أمثلة وطرق الحماية.

أهم 10 نقاط ضعف في C++ مع أمثلة وحماية

1. تجاوز سعة المخزن المؤقت (Buffer Overflow)

المشكلة: كتابة بيانات تتجاوز حدود المصفوفة المخصصة. هذا كلاسيكي في C/C++، ويسمح بإعادة كتابة المتغيرات المجاورة، أو عنوان عودة الدالة، أو البيانات في الكومة.

// مثال على الثغرة
#include <cstring>
#include <iostream>

void vulnerable() {
    char buffer[10];
    std::cout << "أدخل السلسلة: ";
    std::cin >> buffer; // خطر! لا يوجد فحص للطول
}

int main() {
    vulnerable();
    return 0;
}

النتائج: تنفيذ كود عشوائي (RCE)، انهيار البرنامج.

الحماية: استخدم std::string، std::vector، والدوال الآمنة (مثل strncpy مع تحديد الحجم).

// الخيار الآمن
#include <string>
#include <iostream>

void safe() {
    std::string input;
    std::getline(std::cin, input);
    std::cout << "لقد أدخلت: " << input << std::endl;
}

2. تسرب الذاكرة (Memory Leak)

المشكلة: يتم تخصيص الذاكرة عبر new/malloc، ولكن لا يتم تحريرها عبر delete/free. بمرور الوقت، يستهلك التطبيق كل ذاكرة الوصول العشوائي.

void leaky() {
    int* data = new int[1000];
    // نسينا delete[] data;
}

النتائج: رفض الخدمة (DoS)، إبطاء النظام.

الحماية: استخدم المؤشرات الذكية (std::unique_ptr، std::shared_ptr)، وRAII (اكتساب الموارد هو التهيئة).

#include <memory>
void safe() {
    std::unique_ptr<int[]> data = std::make_unique<int[]>(1000);
    // سيتم تحرير الذاكرة تلقائيًا عند الخروج من الدالة
}

3. إلغاء الإشارة إلى مؤشر فارغ (Null Pointer Dereference)

المشكلة: محاولة الوصول إلى الذاكرة عبر عنوان nullptr.

void process(int* ptr) {
    *ptr = 42; // إذا كان ptr == nullptr، سيتعطل البرنامج
}

النتائج: انهيار فوري (segmentation fault)، DoS.

الحماية: تحقق دائمًا من المؤشرات قبل الاستخدام أو استخدم المراجع.

void safe(int* ptr) {
    if (ptr) {
        *ptr = 42;
    } else {
        // معالجة الخطأ
    }
}

4. تجاوز سعة الأعداد الصحيحة (Integer Overflow)

المشكلة: نتيجة عملية حسابية تتجاوز نطاق نوع البيانات. يمكن أن يؤدي هذا إلى سلوك غير متوقع، خاصة عند العمل مع فهارس المصفوفات.

#include <cstdint>
void vulnerable() {
    uint16_t a = 65535;
    uint16_t b = 1;
    uint16_t sum = a + b; // تجاوز: 65536 -> 0
}

النتائج: أخطاء منطقية، تجاوز سعة المخزن المؤقت (إذا تم استخدامه لحساب الحجم).

الحماية: استخدم أنواعًا ذات حجم ثابت (int32_t، int64_t)، وتحقق من العمليات الحسابية.

```

المدونات

توصيات الكتب