إدارة الأسرار والبنية التحتية للمفاتيح

مشكلة الأسرار

18 دقيقة الدرس 1 من 28

مشكلة الأسرار

كل نظام في بيئة الإنتاج يحتوي على أسرار: كلمات مرور قواعد البيانات، مفاتيح API، مفاتيح TLS الخاصة، بيانات اعتماد OAuth، مفاتيح SSH، رموز وصول موفري الخدمات السحابية. السؤال ليس أبداً ما إذا كان نظامك يحتوي على أسرار — فهو يحتوي حتماً — بل هو ما إذا كانت تلك الأسرار مُدارة بشكل مقصود أم مبعثرة بشكل عرضي عبر كل سطح لمسه مهندسوك يوماً ما.

غالبية الاختراقات الحقيقية لا تبدأ باستغلال ثغرة يوم الصفر أو هجوم متطور. تبدأ بسر مُودَع في مستودع Git، مدمج في صورة Docker، ملصوق في متغير بيئة CI بصلاحيات واسعة للغاية، أو متروك في ملف سجل الأوامر على مضيف بروكسي مشترك. يرسم هذا الدرس سطح الهجوم الكامل لتفهم تماماً ما تدافع عنه قبل تصميم أي حل.

ما هو الانتشار العشوائي للأسرار؟

الانتشار العشوائي للأسرار هو الحالة التي توجد فيها بيانات الاعتماد في أماكن كثيرة في آن واحد، غالباً بدون جرد مركزي أو جدول زمني للتدوير أو مسار تدقيق للوصول. يحدث هذا بشكل عضوي: يُرمّز مطور كلمة مرور قاعدة البيانات بشكل ثابت لإتمام شيء ما، ينسخها إلى متغير بيئة CI، يلصقها في رسالة Slack لزميله، ثم ينسى كل مكان هبطت فيه.

على نطاق واسع، يبدو الانتشار هكذا: شركة من 50 مهندساً تجري فحصاً على سجل GitHub الخاص بها وتجد 3,400 سر عبر 120 مستودعاً، كثير منها بيانات اعتماد نشطة لأنظمة إنتاج. هذا ليس افتراضياً — إنه النتيجة الوسطية لتشغيل أداة مثل trufflehog أو git-secrets على قاعدة بيانات غير مُدارة للمرة الأولى. كل مؤسسة لم تشغّل أحد هذه الفحوصات يجب أن تفترض أنها في هذه الحالة.

لماذا الانتشار خطير وليس مجرد فوضوي: سر في مكان واحد هو سر يمكنك تدويره. سر في اثني عشر مكاناً هو سر لا يمكنك تدويره بأمان — لا تعرف جميع المستهلكين، لا يمكنك تحديثهم بشكل ذري، وستكسر شيئاً حتماً، لذا تتأخر. التأخير يعني بقاء بيانات الاعتماد نشطة لأشهر أو سنوات بعد الاشتباه في اختراقها.

مسارات التسرب الستة

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

1. إيداعات الكود المصدري

المتجه الأكثر شيوعاً والأكثر خطورة. يقوم مطور بتسجيل ملف .env، أو ترميز مفتاح بشكل ثابت في إعداد، أو دفع ملف اختبار يحتوي على بيانات اعتماد إنتاج حقيقية. Git يتذكر كل شيء: حتى بعد git rm وإيداع جديد، يعيش السر في التاريخ الكامل، قابل للاستنساخ من قبل أي شخص لديه وصول للمستودع — وإذا أُتيح المستودع للعامة ولو لحظياً، يُفهرسه فحص أسرار GitHub وأدوات الكشط الخارجية في غضون دقائق.

# خطأ — لا تفعل هذا أبداً # config/database.py DB_PASSWORD = "hunter2_prod_2024!" AWS_SECRET_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" # التحقق من وجود سر في سجل Git (شغّل هذا على أي مستودع ترثه) git log --all --full-history -- "**/*.env" "**/*.pem" "**/credentials*" # فحص الأسرار في السجل الكامل باستخدام trufflehog trufflehog git file://. --only-verified

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

2. متغيرات بيئة CI/CD

متغيرات البيئة في أنظمة CI (أسرار GitHub Actions، متغيرات GitLab CI، مخزن بيانات اعتماد Jenkins) تبدو آمنة لأنها مُقنَّعة في السجلات. إنها ليست كذلك. التقنيع مجرد مظهر: يستبدل السلسلة الحرفية في مخرج السجل، لكن المتغير لا يزال متاحاً لكل خطوة في الـ pipeline، بما في ذلك الإجراءات أو الإضافات التابعة لجهات خارجية التي أضفتها دون تدقيق. يمكن لإجراء GitHub Actions ضار أو مخترق تهريب كل سر في بيئتك بطلب HTTP صادر واحد.

# GitHub Actions — إجراء خارجي مخترق يمكنه قراءة كل الأسرار # حتى الأسرار "المقنعة" هي متغيرات بيئة متاحة لكل الخطوات name: CI on: push jobs: build: runs-on: ubuntu-latest steps: # هذا الإجراء الخارجي لديه وصول لكل الأسرار أدناه - uses: some-vendor/action@v1 # مثبّت؟ مدقق؟ محتفظ به؟ - name: Build env: DB_PASS: ${{ secrets.DB_PASSWORD }} # مرئي لكل الخطوات أعلاه AWS_KEY: ${{ secrets.AWS_SECRET_KEY }} # نفس عملية الـ runner # الأفضل: حدّد نطاق الأسرار للخطوة الدنيا التي تحتاجها # الأفضل: ثبّت الإجراءات الخارجية على SHA كامل، لا على علامة قابلة للتغيير # الأفضل: استخدم OIDC federation للتخلص من بيانات الاعتماد طويلة الأمد كلياً

3. صور الحاويات

عمليات بناء Docker هي بالوعة كلاسيكية لبيانات الاعتماد. يضيف مطور وسيطة ARG أو ENV لسحب حزمة خاصة، تشغيل ترحيل قاعدة بيانات، أو المصادقة مع API أثناء وقت البناء. تُدمج تلك القيمة بعد ذلك في طبقة صورة أو أكثر وتصبح قابلة للاستخراج بسهولة من قبل أي شخص يمكنه سحب الصورة:

# خطأ — بيانات الاعتماد مدمجة في طبقة FROM node:20-alpine ARG NPM_TOKEN ENV NPM_TOKEN=$NPM_TOKEN RUN echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc RUN npm install # حتى إذا حذفت .npmrc في الطبقة التالية، الرمز موجود في طبقة ARG/ENV # استخرجه بـ: docker history --no-trunc my-image:latest # أو: docker save my-image:latest | tar xv # صواب — استخدم أسرار BuildKit (لا تلمس طبقة أبداً) # syntax=docker/dockerfile:1 FROM node:20-alpine RUN --mount=type=secret,id=npm_token \ NPM_TOKEN=$(cat /run/secrets/npm_token) && \ echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc && \ npm install && \ rm ~/.npmrc # البناء بـ: docker build --secret id=npm_token,env=NPM_TOKEN .

4. السجلات وأنظمة المراقبة

سجلات التطبيق هي ثالث أكثر نقاط التسرب شيوعاً. سجلات الطلبات التي تتضمن عناوين URL كاملة تلتقط مفاتيح API الممررة كمعاملات استعلام (?api_key=abc123). تقارير الأخطاء تتضمن آثار المكدس التي تتفريغ متغيرات البيئة. رؤوس التتبع الموزعة يمكنها حمل رموز المصادقة. كل هذا يصل إلى Elasticsearch وDatadog وSplunk وCloudWatch — أنظمة بضوابط وصول أضعف بكثير من مخزن أسرارك في الإنتاج.

5. ملفات حالة البنية التحتية

ملفات حالة Terraform (terraform.tfstate) تحتوي على المخرج الكامل بنص واضح لكل مورد تم إنشاؤه — بما في ذلك كلمات المرور المولّدة والمفاتيح الخاصة وسلاسل اتصال قواعد البيانات. ملف حالة مخزّن في حاوية S3 بدون تشفير أو سياسات IAM مناسبة هو تفريغ كامل لبيانات اعتماد بنيتك التحتية. ينطبق الأمر نفسه على ملفات Ansible vault المخزّنة بعبارات مرور ضعيفة، ومخرجات CloudFormation المكتوبة إلى Parameter Store بدون تشفير، وملفات قيم Helm المُودَعة في Git.

6. مشاركة الأسرار بين الأشخاص

Slack والبريد الإلكتروني وNotion والخزائن المشتركة في 1Password وحسابات مضيف الوصول المشتركة كلها تمثل المتجه البشري: الأسرار المنقولة بين الأشخاص تترك نسخة في كل نظام عبرته. لا توجد طريقة موثوقة لتدوير سر تمت مشاركته عبر Slack — لا تعرف من يمتلكه، أو من صدّر المحادثة، أو ما إذا كان وصل إلى تخزين تطبيق Slack تابع لجهة خارجية.

Secrets leak paths and attack surface SECRET DB password / API key Source Code Git history (forever) committed CI/CD Pipeline env vars / logs env injection Container Image baked into layers ARG/ENV Logs & Traces URL params / stack traces leaked IaC State Files tfstate / CF outputs plaintext output Human Sharing Slack / email / notes copy-paste Attacker Access DB / AWS / Prod System
مسارات التسرب الستة التي تنتقل من خلالها الأسرار إلى أيدي المهاجمين.

التكلفة الحقيقية: ثلاث حوادث نموذجية

هذه ليست افتراضات. إنها نمط الاختراقات الحقيقية:

  • Uber (2022): حصل المهاجم على بيانات اعتماد متعاقد عبر تصيد SMS، ثم وجد مفاتيح AWS مُرمَّزة بشكل ثابت في سكريبت PowerShell داخلي على مشاركة شبكية. وصول كامل لبيئة AWS في الإنتاج، تعرّض 57 مليون سجل.
  • Toyota (2023): أُتيح مستودع GitHub عرضاً للعموم لمدة خمس سنوات يحتوي على بيانات اعتماد تمنح وصولاً لخادم إدارة بيانات. تعرّض 215,000 سجل عملاء. لم تُدوَّر بيانات الاعتماد لأن أحداً لم يعلم بوجودها في المستودع.
  • Codecov (2021): هجوم على سلسلة التوريد عدّل سكريبت Bash الخاص بـ Codecov لتهريب جميع متغيرات البيئة من أي pipeline CI شغّله — مما أدى إلى الاستيلاء على أسرار آلاف الشركات المنبثقة بما فيها HashiCorp وTwilio وRapid7.
سجل Git دائم حتى تعيد كتابته — وإعادة الكتابة خطرة. عندما يُودَع سر في مستودع عام أو مستودع به أكثر من متعاون واحد، افترض أنه مخترق وقم بتدويره فوراً. تشغيل git filter-repo أو BFG لإزالة السر من السجل هو إعادة كتابة مدمرة تُبطل كل نسخة واستنساخ. التكلفة التشغيلية لإعادة كتابة السجل عادةً تتجاوز تكلفة تدوير بيانات الاعتماد. دوّر أولاً، أعد الكتابة أبداً (أو فقط إذا كانت بيانات الاعتماد لا يمكن تدويرها).

قياس سطح الهجوم: الكشف أولاً

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

# 1. فحص سجل Git بحثاً عن الأسرار (جميع الفروع، كل التاريخ) pip install trufflehog trufflehog git file://. --only-verified --json | jq '.SourceMetadata.Data.Git' # 2. فحص الأسرار الخاص بـ GitHub (فعّله في إعدادات المستودع > الأمان) # يغطي 200+ نوع رمز؛ ينبّه فوراً عند الدفع # 3. كشف الأسرار في صورة Docker (جميع الطبقات) pip install detect-secrets # أو: docker save myimage:latest | tar xO | strings | grep -E 'AKIA[0-9A-Z]{16}' # 4. فحص ملفات IaC / Terraform pip install checkov checkov -d . --check CKV_SECRET_6 # يتحقق من الأسرار المُرمَّزة في TF # 5. خطاف ما قبل الإيداع لمنع الإيداعات المستقبلية (ثبّته مرة على كل جهاز مطور) pip install detect-secrets detect-secrets scan > .secrets.baseline cat > .pre-commit-config.yaml <<'EOF' repos: - repo: https://github.com/Yelp/detect-secrets rev: v1.4.0 hooks: - id: detect-secrets args: ['--baseline', '.secrets.baseline'] EOF pre-commit install
فعّل فحص أسرار GitHub Advanced Security على كل مستودع خاص. يعمل على كل دفع ويفحص 200+ نوع من الأسرار (AWS وGCP وAzure وStripe وTwilio وغيرها) بنسبة إيجابيات كاذبة قريبة من الصفر. للمؤسسات غير المشتركة في GitHub Enterprise، يحقق trufflehog في CI نفس التغطية. في كلتا الحالتين، يجب أن يعمل هذا الفحص على كل PR — ليس كفكرة لاحقة بل كفحص إلزامي. يجب أن يفشل CI لأي PR يُدخل سراً قبل أن يُدمج.

لماذا مجموعة أدوات DevOps القياسية ليست كافية

الخطأ الشائع هو الاعتقاد بأن متغيرات البيئة "آمنة بما يكفي." إنها ليست كذلك — إنها فقط أقل ملاءمة للقراءة من ملف نص واضح. كل عملية تعمل كنفس مستخدم نظام التشغيل يمكنها قراءة كل متغير بيئة. في الحاويات، يتفريغ docker inspect <container> تلك المتغيرات. موارد Kubernetes Secret المخزّنة في etcd مُشفّرة بـ base64، وليست مُشفَّرة افتراضياً، ويمكن لأي شخص لديه صلاحية get secrets في RBAC عبر الكلاستر قراءتها. base64 ليس تشفيراً.

الدرس التالي يرسّخ مبادئ نظام إدارة الأسرار المناسب: المركزية، وبيانات الاعتماد الديناميكية، والوصول بأقل الصلاحيات، وتسجيل التدقيق الكامل، والتدوير التلقائي. كل مبدأ من هذه المبادئ هو إجابة مباشرة على أحد مسارات التسرب المُرسَمة في هذا الدرس.