Skip to content
KitploitKITPLOIT
أدواتعمليات الاستغلالالمدونة
Log in
إرسال
أدواتعمليات الاستغلالالمدونة
إرسال

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
ZigRaceExploit — إثبات المفهوم لـ CVE-2021-25741 في Zig | Kitploit
أدوات/GitHubGitHub/glutenfree69/zigraceexploit
أمن الحاوياتتحليل الثغرات الأمنيةالاستغلالأمن السحابةالتعلم والتعليماستغلال الملفات الثنائية
GitHubglutenfree69/zigraceexploit

ZigRaceExploit

إثبات المفهوم لـ CVE-2021-25741 في Zig

عرض المستودع
11منذ 6 أشهرلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

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

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

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

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

CVE-2021-25741 — استغلال سباق TOCTOU للروابط الرمزية في Zig

استغلال تعليمي لشرط السباق TOCTOU (Time Of Check, Time Of Use) الذي يقع في أصل CVE-2021-25741، وهو ثغرة في kubelet الخاص بـ Kubernetes.

يبيّن المشروع محليًا (بدون عنقود K8s) كيف يمكن لتبديل متزامن للروابط الرمزية تجاوز فحص المسار بين lstat() وopen()، ويثبت أن openat2() مع أعلام RESOLVE_* هو الحل.

جدول المحتويات

  • المشكلة
  • كيف يعمل الاستغلال
  • بنية الكود
  • المتطلبات الأساسية
  • البناء
  • الاستخدام
    • الاختبار محليًا باستخدام Docker
    • مقارنة openat مقابل openat2
    • اللعب بالتأخير الزمني TOCTOU
    • الاختبار على عقدة Kubernetes حقيقية
  • النتائج المتوقعة
  • شرح الكود
  • استدعاءات نظام Linux المستخدمة
  • التصحيح باستخدام strace
  • المراجع

المشكلة

تحليل المسارات في Linux

عندما يقوم النواة بتحليل مسار مثل /a/b/c/file، فإنه يفعل ذلك مكوّنًا مكوّنًا. في كل خطوة، إذا كان المكوّن رابطًا رمزيًا، فإن النواة تتبعه تلقائيًا. هذا التحليل ليس ذريًا — يمكن لنظام الملفات أن يتغير بين خطوتين.

TOCTOU في kubelet

كان kubelet الخاص بـ Kubernetes يتبع هذا النمط الضعيف تمامًا:

1. CHECK : lstat(subPath) → "c'est un répertoire, c'est safe"
     ↕ FENÊTRE DE RACE — un process dans le container swap le répertoire pour un symlink
2. USE   : mount(subPath) → suit le symlink, monte le filesystem host

بين الفحص والتركيب، كان بإمكان عملية خبيثة داخل الحاوية استبدال subPath برابط رمزي يؤدي إلى / الخاص بالمضيف، وبالتالي الحصول على وصول كامل إلى نظام ملفات المضيف.

الإصلاح: openat2(2)

استدعاء النظام openat2 (نواة 5.6+) يحل المسار و يفتح الملف بشكل ذري، مع قيود:

Flagالتأثير
RESOLVE_NO_SYMLINKSيرفض اتباع أي رابط رمزي → يعيد ELOOP
RESOLVE_BENEATHيرفض الخروج من المجلد الأساسي → يعيد EXDEV
RESOLVE_IN_ROOTيتعامل مع dirfd كجذر لنظام الملفات
RESOLVE_NO_XDEVيرفض عبور نقاط التركيب

مع openat2، لا توجد نافذة TOCTOU: إذا ظهر رابط رمزي أثناء التحليل، يفشل استدعاء النظام فورًا.


كيف يعمل الاستغلال

يتعاون خيطان لاستغلال نافذة TOCTOU:

workdir/
├── legit_dir/
│   └── secret.txt  → contient "LEGIT"
├── symlink_target/
│   └── secret.txt  → contient "PWNED"
└── target/          → swappé entre vrai dir et symlink

خيط Racer

يعمل في حلقة فائقة السرعة ويبدّل target/ ذريًا بين حالتين عبر renameat2(RENAME_EXCHANGE):

  • الحالة A: target/ هو مجلد حقيقي (يحتوي على secret.txt = "LEGIT")
  • الحالة B: target/ هو رابط رمزي إلى symlink_target/ (يحتوي على secret.txt = "PWNED")

استدعاء نظام واحد فقط لكل تبديل = أقصى نافذة سباق.

خيط Victim (يحاكي kubelet)

يعيد إنتاج النمط الضعيف الخاص بـ kubelet:

  1. fstatat("target", AT_SYMLINK_NOFOLLOW) — يتحقق من أنه مجلد
  2. إيقاف اختياري (يحاكي كمون kubelet بين الفحص والاستخدام)
  3. openat(dirfd, "target/secret.txt", O_RDONLY) — يفتح الملف
  4. read() — يقرأ المحتوى
  5. إذا كان المحتوى == "PWNED" → فوز بالسباق (تم اتباع الرابط الرمزي)
  6. إذا كان المحتوى == "LEGIT" → خسارة السباق (كان بالفعل المجلد الحقيقي)

في الوضع المحمي (--use-openat2)، تستخدم الخطوة 3 openat2 مع RESOLVE_NO_SYMLINKS | RESOLVE_BENEATH. إذا وُجد رابط رمزي، يعيد النواة ELOOP بدلاً من اتباعه.


بنية الكود

src/
├── main.zig       # Point d'entrée : parse CLI, crée le shared state, spawn les
│                  # threads, mesure le temps, affiche les résultats
│
├── racer.zig      # Thread racer : prépare l'état initial (target → symlink),
│                  # puis boucle sur renameat2(RENAME_EXCHANGE) pour swapper
│                  # target/ et legit_dir/ en continu
│
├── victim.zig     # Thread victim : boucle N itérations de fstatat → delay →
│                  # openat/openat2 → read → compare "LEGIT" vs "PWNED"
│
├── setup.zig      # Crée l'arborescence de test : workdir/, legit_dir/,
│                  # symlink_target/, target/ avec les fichiers sentinel
│
├── syscalls.zig   # Constantes et wrappers pour les syscalls raw :
│                  # - open_how struct (kernel UAPI, 3×u64)
│                  # - RESOLVE_* flags
│                  # - RENAME_EXCHANGE (= 2)
│                  # - openat2() via linux.syscall4(.openat2, ...)
│                  # - rename_exchange() via linux.renameat2()
│                  # - Helpers : is_err(), to_errno(), to_fd()
│
└── stats.zig      # Compteurs atomiques lock-free (std.atomic.Value(u64))
                   # pour wins, losses, errors, eloop + affichage formaté

تُستدعى جميع استدعاءات النظام عبر std.os.linux.* مباشرة (بدون مغلفات std.fs أو std.posix). استدعاء النظام الوحيد بدون مغلف في مكتبة Zig 0.15 المعيارية هو openat2، ونستدعيه عبر linux.syscall4(.openat2, ...) مع بنية open_how معرّفة يدويًا من ترويسات UAPI الخاصة بالنواة.


المتطلبات الأساسية

الأداةالإصدارالسبب
Zig0.15.xالمترجم + الترجمة المتقاطعة
Dockerأي إصدارلتنفيذ ثنائي Linux على Mac
colimaأي إصداربيئة تشغيل Docker على macOS (أو Docker Desktop)

تُجمَّع الثنائي بشكل ثابت (مكتبة musl) ويعمل على أي Linux دون تبعيات.

Kernel minimum:

  • 3.15+ من أجل renameat2(RENAME_EXCHANGE)
  • 5.6+ من أجل openat2 مع RESOLVE_* (ضروري فقط لـ --use-openat2)

يستخدم Docker Desktop و colima على Mac نواة 6.x — كل شيء مدعوم.


البناء

الترجمة المتقاطعة من Mac إلى Linux

# ARM64 (Mac M1/M2/M3 → Docker colima / EC2 ARM)
zig build -Dtarget=aarch64-linux-musl -Doptimize=ReleaseSafe

# x86_64 (pour des nodes x86)
zig build -Dtarget=x86_64-linux-musl -Doptimize=ReleaseSafe

الثنائي موجود في zig-out/bin/race-exploit.

$ file zig-out/bin/race-exploit
ELF 64-bit LSB executable, ARM aarch64, statically linked

الاستخدام

الاختبار محليًا باستخدام Docker

# Démarrer le runtime Docker (si macOS)
colima start

# Lancer l'exploit (mode vulnérable par défaut)
docker run --rm -v $(pwd)/zig-out/bin:/app alpine /app/race-exploit --iterations 10000

مقارنة openat مقابل openat2

# Mode vulnérable (openat) — la race fonctionne
docker run --rm -v $(pwd)/zig-out/bin:/app alpine \
  /app/race-exploit --iterations 10000

# Mode protégé (openat2) — la race est bloquée
docker run --rm -v $(pwd)/zig-out/bin:/app alpine \
  /app/race-exploit --iterations 10000 --use-openat2

أو مع السكربت الذي يشغّل كليهما:

./scripts/run_in_docker.sh --iterations 10000

اللعب بالتأخير الزمني TOCTOU

تضيف المعلمة --delay-us تأخيرًا بين lstat (الفحص) وopenat (الاستخدام). كلما زاد التأخير، اتسعت نافذة TOCTOU، وزاد معدل الفوز:

# Sans délai — win rate ~25%
docker run --rm -v $(pwd)/zig-out/bin:/app alpine \
  /app/race-exploit --iterations 50000

# 10µs — win rate ~35%
docker run --rm -v $(pwd)/zig-out/bin:/app alpine \
  /app/race-exploit --iterations 50000 --delay-us 10

# 100µs — win rate ~50%
docker run --rm -v $(pwd)/zig-out/bin:/app alpine \
  /app/race-exploit --iterations 50000 --delay-us 100

# 1000µs (1ms) — win rate ~50% (plafonné, le racer swap bien plus vite)
docker run --rm -v $(pwd)/zig-out/bin:/app alpine \
  /app/race-exploit --iterations 10000 --delay-us 1000

في kubelet حقيقي، يكون الكمون بين التحقق من subPath والتركيب bind mount في حدود عدة ميلي ثانية (استدعاءات API، تحضير مساحة أسماء mount، وما إلى ذلك)، مما يجعل السباق موثوقًا جدًا في الظروف الحقيقية.

خيارات سطر الأوامر الكاملة

تنزيل الأداة