DevSecOps وأمن سلسلة التوريد

الفحص الديناميكي واختبار وقت التشغيل

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

الفحص الديناميكي واختبار وقت التشغيل

يقرأ الفحص الاستاتيكي (SAST) الكود المصدري دون تنفيذه. أما اختبار أمان التطبيقات الديناميكي (DAST) فيفعل العكس تماماً: يهاجم تطبيقاً يعمل فعلاً بالطريقة ذاتها التي يستخدمها المهاجم الحقيقي — إرسال مدخلات مشوهة، واستطلاع نقاط النهاية، وتتبع عمليات إعادة التوجيه، وفحص الردود. تتناول هذه الدرس كيفية دمج DAST في خط أنابيب قائم على بيئة التدريج، وكيفية فحص واجهات برمجة التطبيقات (APIs) على نطاق واسع، وكيفية تفسير النتائج دون إغراق فريقك بالإيجابيات الكاذبة.

لماذا DAST إلى جانب SAST؟

يفوّت SAST فئة كاملة من الثغرات التي لا تظهر إلا في وقت التشغيل: سلاسل أدوات إلغاء التسلسل، وتزوير الطلبات من جهة الخادم الذي تُطلقه مكتبة تجلب عناوين URL المقدمة من المستخدم، والتحايل على المصادقة عبر منطق التحقق من الرمز المميز، وحالات السباق في معالجات الطلبات المتزامنة. يكتشف DAST هذه الثغرات لأنه يتفاعل مع العملية الفعلية وحالة الذاكرة ومكدس الشبكة. على مستوى الشركات الكبرى، كلاهما إلزامي — إذ يكتشفان فئات معيبة متقاطعة، ومجموع نتائجهما أكبر بكثير من نتائج أي منهما على حدة.

المبدأ الأساسي: يتطلب DAST هدفاً يعمل. يجب أن يكون ذلك الهدف مكافئاً لبيئة الإنتاج في بيئة التدريج — نفس إعداد المصادقة، ونفس محرك قاعدة البيانات، ونفس أعلام الميزات — وإلا فإن نتائج الفحص لن تعكس المخاطر الحقيقية.

أدوات DAST الأساسية في خط الأنابيب الحديث

الأداتان اللتان ستصادفهما أكثر من غيرهما في خطوط أنابيب CI/CD هما OWASP ZAP (Zed Attack Proxy) وNuclei. ZAP هو بروكسي اعتراضي كامل مع محرك فحص نشط وإطار أتمتة غني. أما Nuclei فهو ماسح قائم على القوالب مُصمَّم للسرعة وسير العمل الصديق لـ GitOps — تعيش القوالب في مستودع إلى جانب كود التطبيق، تُعامَل كأي تبعية أخرى وتخضع للمراجعة.

بالنسبة للخدمات القائمة على واجهة برمجة التطبيقات، يتولى RESTler من Microsoft Research الفحص العشوائي الحالاتي (stateful fuzzing) المبني على مواصفة OpenAPI — إذ يقرأ ملف openapi.yaml الخاص بك ويولّد تسلسلات من الاستدعاءات تستكشف آلات الحالة متعددة الخطوات. أما ffuf فيُستخدم للفحص الدقيق للمعلمات والمسارات عند الحاجة إلى دقة جراحية ضد نقطة نهاية محددة.

التكامل في خط أنابيب قائم على بيئة التدريج

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

# .github/workflows/dast.yml — فحص ZAP النشط بعد نشر بيئة التدريج dast-scan: needs: deploy-staging runs-on: ubuntu-latest steps: - name: Checkout (لملف قواعد ZAP) uses: actions/checkout@v4 - name: ZAP Full Scan uses: zaproxy/action-full-scan@v0.10.0 with: target: 'https://staging.example.com' rules_file_name: '.zap/rules.tsv' # إسكات معرّفات التنبيه الآمنة cmd_options: '-a -j -l WARN' fail_action: true # خروج غير صفري عند نتائج HIGH - name: رفع تقرير ZAP uses: actions/upload-artifact@v4 if: always() with: name: zap-report path: report_json.json

ملف rules.tsv هو الطريقة التي تتجنب بها إرهاق التنبيهات. كل سطر هو معرّف تنبيه وإجراء: IGNORE أو WARN أو FAIL. على خدمة جديدة، شغّل ZAP في وضع الفحص السلبي أولاً، راجع كل نتيجة، ثم رقّ النتائج الحقيقية إلى FAIL وأسكت الضوضاء بـIGNORE.

# .zap/rules.tsv — قاعدة واحدة لكل سطر: <alertId> TAB <action> TAB <تعليق> 10020 IGNORE X-Frame-Options تتولاه طبقة CDN وليس التطبيق 10038 IGNORE CSP يُقدَّم عبر عكس البروكسي 10096 WARN الكشف عن الطوابع الزمنية — مخاطر منخفضة، راقب فقط 40018 FAIL حقن SQL — تسامح صفري 40012 FAIL XSS المنعكس — تسامح صفري 90022 WARN الكشف عن خطأ التطبيق — تحقق لكن لا توقف النشر

أساسيات الفحص العشوائي لواجهات برمجة التطبيقات

الخلفيات الحديثة هي في معظمها واجهات برمجة تطبيقات وليست صفحات HTML. برنامج الزحف في ZAP مُصمَّم لـHTML — لواجهات REST وGraphQL تحتاج إلى فحص عشوائي مبني على المواصفة. سير العمل: صدّر مواصفة OpenAPI من CI (كثير من الأطر تولّدها تلقائياً)، أطعِمها للماسح، ودعه يولّد مدخلات قيم الحدود لكل معلمة.

DAST pipeline: spec-driven API fuzzing flow OpenAPI Spec Export Fuzzer (RESTler / ZAP) Boundary Value Payloads Malformed Auth Sequences Staging API Target Response analysis & finding triage
الفحص العشوائي المبني على المواصفة: عقد OpenAPI تقود توليد الحمولات؛ النتائج تعود للفرز.

استدعاء Nuclei عملي ضد واجهة برمجة تطبيقات في بيئة التدريج — بتشغيل قوالب HTTP واكتشاف التقنيات فقط، بخطورة متوسطة وما فوق — يبدو هكذا:

# تثبيت Nuclei (ثنائي Go) go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest # التشغيل ضد بيئة التدريج — قوالب HTTP فقط، خطورة متوسطة+ nuclei \ -target https://staging.example.com \ -tags http,tech \ -severity medium,high,critical \ -rate-limit 50 \ -bulk-size 10 \ -concurrency 5 \ -o nuclei-report.json \ -json # تحديث مكتبة القوالب (ثبّتها في CI بإيداعها في مستودعك) nuclei -update-templates
ثبّت إصدار القوالب في CI. تشغيل nuclei -update-templates بشكل غير مشروط في خط الأنابيب يعني أن قالباً جديداً بإيجابية كاذبة قد يكسر بنيتك بشكل غير متوقع. أودع دليل nuclei-templates/ (أو علامة محددة) في مستودعك وحدّثه كترقية تبعية مقصودة.

الفحص المصادق عليه

يجد DAST غير المصادق عليه المشكلات المعرضة للعموم لكنه يفوّت سطح الهجوم المصادق عليه بالكامل — وهو عادةً المكان الذي تعيش فيه البيانات الحساسة. يدعم ZAP نصوص معالجة الجلسة وإعداد المصادقة بتنسيق JSON. تحقن بيانات اعتماد بيئة تدريج قصيرة العمر (ليس سراً من الإنتاج أبداً) عبر سر CI، ويعيد ZAP تشغيله على كل طلب.

لتدفقات OAuth2/OIDC، النمط هو: الحصول على رمز مميز بمنح بيانات اعتماد العميل أو كلمة المرور ضد موفر الهوية في التدريج ← كتابته في ملف سياق ZAP ← استخدام إضافة replacer في ZAP لحقن ترويسة Authorization: Bearer على كل طلب فحص.

فئات نتائج DAST الشائعة

  • XSS المنعكس والمخزّن — المدخلات التي تُعاد بدون ترميز. يحقن ZAP متعددات XSS المعروفة في كل معلمة.
  • حقن SQL — كلا من ZAP وSQLMap يختبران هذا؛ ZAP صديق لخط الأنابيب، وSQLMap أشمل للتحقيق الموجّه.
  • IDOR (المرجع المباشر للكائن غير الآمن) — استبدال معرف مورد مستخدم بمعرف آخر. تغطية الماسحات الآلية محدودة هنا؛ تكمل بالاختبار اليدوي أو البرامج النصية المخصصة.
  • الأخطاء في الإعداد الأمني — غياب HSTS، CORS المتساهل، الكشف عن إصدار الخادم، بيانات الاعتماد الافتراضية على واجهات الإدارة.
  • عيوب المصادقة — غياب تحديد المعدل على نقاط نهاية تسجيل الدخول، وضعف إنتروبيا رمز الجلسة، وJWT بـalg:none.
مشكلة إنتاجية — الفحص ضد قاعدة بيانات مباشرة: سيحاول الفحص النشط حقن SQL مما يُطلق استعلامات DB حقيقية. إذا كانت قاعدة بيانات التدريج تحتوي قيوداً على مفاتيح خارجية تشير إلى بنية تحتية مشتركة، أو إذا كانت بيئة التدريج تشارك قائمة انتظار رسائل مع الإنتاج، فقد تنتشر حمولة فحص إلى المصب. عزل بيئة التدريج على مستوى الشبكة والبيانات قبل تفعيل الفحص النشط.

تفسير النتائج وتقليل الضوضاء

أول فحص ZAP لتطبيق ويب نموذجي يُرجع عشرات إلى مئات النتائج بخطورة INFORMATIONAL أو LOW — معظمها كشوفات معلوماتية عن الترويسات أو ترويسات اختيارية مفقودة تتولاها شبكة توصيل المحتوى (CDN) بالفعل. سير العمل لاستخراج الإشارة من الضوضاء:

  1. شغّل ZAP في الوضع السلبي أولاً (بدون حمولات نشطة) لبناء خط أساس بدون مخاطر.
  2. افرز كل نتيجة وفقاً لمعمارتيك الفعلية — كثير من النتائج المنخفضة تُخفَّف على مستوى موازن التحميل أو CDN.
  3. ضمّن قرارات الفرز في rules.tsv حتى تُطبَّق تلقائياً في كل تشغيل لاحق.
  4. اضبط بوابة خط الأنابيب على HIGH أو CRITICAL فقط — نتائج MEDIUM تذهب إلى الأعمال المتراكمة باتفاقية مستوى خدمة للسبرنت بدلاً من حجب النشر.
  5. تتبع عدد النتائج بمرور الوقت في نظام SIEM أو ملف CSV بسيط؛ ارتفاع مفاجئ في النتائج الجديدة بعد نشر هو إشارة ذات معنى حتى لو كانت النتائج الفردية مُسكَّتة.

DAST في حلقة DevSecOps الأشمل

تُغذّي نتائج DAST قواعد SAST. عندما يجد ZAP XSS منعكساً في دالة تصيير قالب، تضيف قاعدة SAST (نمط Semgrep أو استعلام CodeQL) تُشير إلى كل استدعاء لتلك الدالة بدون غلاف التطهير — لاصطياد الانتكاسات المستقبلية قبل وصولها إلى التدريج. هذه الحلقة التغذية الراجعة هي المكان الذي يحصل فيه "الإزاحة لليسار" على رافعة حقيقية: النتائج في وقت التشغيل تُصلب القواعد الاستاتيكية.

DevSecOps feedback loop: DAST findings harden SAST rules Developer Commits Code CI — SAST Semgrep / CodeQL Staging DAST / ZAP Production Deploy Gate نتيجة DAST ← قاعدة SAST جديدة (تغلق الحلقة)
نتائج DAST من بيئة التدريج تُغذّي قواعد SAST جديدة، تصطاد نفس فئة الخطأ في وقت الإيداع مستقبلاً.

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