
POC لـ CVE-2026-30950 والذي يسمح باختطاف الجلسة في AutoGpt
إثبات مفهوم لـ CVE-2026-30950، وهو IDOR مصادق (نقص التفويض) في منصة AutoGPT يتيح لأي مستخدم مسجل إعادة تعيين — وبالتالي اختطاف — جلسة الدردشة لأي مستخدم آخر عبر طلب PATCH واحد، دون الحاجة إلى وصول مسبق إلى الجلسة.
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:L)autogpt-platform-backend >= 0.6.36تعرّض واجهة برمجة تطبيقات جلسات الدردشة مسارًا يتيح للمستخدم إرفاق حسابه الخاص بسجل الجلسة. المسار محمي بمصادقة JWT لكنه لا يجري أي فحص بأن المتصل يملك حاليًا الجلسة التي يتم تعديلها — بل يتحقق فقط من أن المتصل مستخدم مصادق عليه. استدعاء مباشر باستخدام session_id الخاص بالضحية وJWT الخاص بالمهاجم ينقل ملكية الجلسة إلى المهاجم.
الثغرة لها ثلاث طبقات ويتم تجاوزها في كل طبقة:
# autogpt_platform/backend/backend/api/features/chat/routes.py:753-776
@router.patch(
"/sessions/{session_id}/assign-user",
dependencies=[Security(auth.requires_user)],
status_code=200,
)
async def session_assign_user(
session_id: str,
user_id: Annotated[str, Security(auth.get_user_id)],
) -> dict:
await chat_service.assign_user_to_session(session_id, user_id)
return {"status": "ok"}
يقبل المسار أي متصل مصادق عليه. ثم يفوّض المهمة إلى الخدمة:
# autogpt_platform/backend/backend/copilot/service.py:291-303
async def assign_user_to_session(session_id: str, user_id: str) -> ChatSessionInfo:
session = await get_chat_session(session_id, None) # ← user_id=None
if not session:
raise NotFoundError(f"Session {session_id} not found")
session.user_id = user_id
session = await upsert_chat_session(session)
return session
يمرر الخدمة عمدًا user_id=None إلى موصل البيانات، بدلاً من تمرير معرف المستخدم الخاص بالمتصل. ثم يعامل موصل البيانات القيمة None كوضع مسؤول ويتخطى مرشح الملكية:
# autogpt_platform/backend/backend/copilot/model.py:355-366
session = await _get_session_from_cache(session_id)
if session:
if user_id is not None and session.user_id != user_id:
logger.warning(f"Session {session_id} user id mismatch")
return None
return session
عندما تكون user_id is None، تقصر العبارة الشرطية ولا يتم إجراء فحص عدم التطابق أبدًا — يتم إرجاع أي جلسة لأي متصل. ثم تقوم الخدمة بكتابة session.user_id بمعرف المتصل وتخزين النتيجة في Redis، بحيث يتم رفض عمليات البحث اللاحقة من قبل المالك الأصلي بواسطة نفس فحص عدم التطابق الذي تم تجاوزه للتو.
أي مثيل من منصة AutoGPT يعمل بإصدار autogpt-platform-backend >= 0.6.36 و < 0.6.51 مع تمكين ميزة الدردشة (copilot) يمكن استغلاله. يتطلب الاستغلال:
تأثير لكل جلسة، يتصاعد مع كل جلسة مختطفة:
تعكس درجة CVSS (C:H / I:N / A:L) النطاق لكل جلسة: تأثير عالٍ على السرية للجلسات المختطفة، لا ضرر على سلامة محتوى الرسائل الموجودة مسبقًا، وتأثير على التوفر (إغلاق) للمالك الشرعي.
يأتي هذا المستودع مع إثبات واحد يغطي المحفز المباشر: طلب PATCH واحد من JWT الخاص بالمهاجم ضد session_id معروف. يقوم سكريبت الإعداد بإنشاء مستخدمين (مهاجم + ضحية) في بيئة AutoGPT مهيأة حديثًا ويتحقق من الشروط المسبقة قبل الإعلان عن الجاهزية.
setup/ — بيئة Docker Compose.
setup.sh يستنسخ AutoGPT عند آخر علامة ضعيفة (autogpt-platform-beta-v0.6.50) إلى setup/AutoGPT-src/، ويُشغّل الخدمات الدنيا من ملف docker-compose.yml الأصلي (rest_server, copilot_executor, database_manager, migrate، بالإضافة إلى تبعياتها غير المباشرة: Postgres، Redis، RabbitMQ، Supabase Kong + GoTrue)، وينشئ مستخدمين اختباريين، ويتحقق من توجيه نقطة النهاية الضعيفة.teardown.sh يُوقِف البيئة ويمسح وحدات التخزين.pocs/session_hijack.py — استغلال ذاتي الاكتفاء. يسجل الدخول كضحية ومهاجم، وينشئ جلسة كضحية، ويتأكد من أن المهاجم ليس لديه حق قراءة قبل الاستغلال، ثم يُطلِق طلب PATCH الواحد، ثم يُثبت أن الملكية قد انتقلت وأن الضحية مغلقة.
المتطلبات: Docker، Git، Python 3.10+، و uv.
cd setup
./setup.sh
يقوم التشغيل الأول باستنساخ AutoGPT عند العلامة الضعيفة وبناء صورة الخلفية (~3-5 دقائق). التشغيلات اللاحقة سريعة. عند اكتمال الإعداد، يطبع الأمر الجاهز لنسخ ولصق استدعاء الإثبات.
تشغيل الإثبات:
uv run --no-project --with requests \
pocs/session_hijack.py \
--api-url http://localhost:58006 \
--auth-url http://localhost:58000 \
--attacker-email [email protected] \
--attacker-password 'Attacker123!' \
--victim-email [email protected] \
--victim-password 'Victim123!'
لماذا المنافذ العالية؟ يقوم ملف compose الأصلي بتثبيت أسماء الحاويات (
supabase-db،rabbitmq، ...) ونشر المنافذ الافتراضية (5432، 8000، ...). للتعايش مع أي بيئات Supabase / Postgres / RabbitMQ أخرى قد يقوم المستخدم بتشغيلها، يقومsetup/docker-compose.override.ymlبإعادة تسمية الحاويات، وعزل الشبكات تحت اسم مشروع فريد (autogpt-cve-2026-30950)، ورفع المنفذين المكشوفين خارجيًا إلى نطاق 58000. الخدمات الداخلية الأخرى ترتبط فقط بشبكة docker للمشروع.
يتوقع أن ينتهي الإخراج بـ:
[PASS] AUTHENTICATED SESSION HIJACK CONFIRMED
إيقاف البيئة:
cd setup
./teardown.sh
يتم الاحتفاظ بالشفرة المصدرية المستنسخة لـ AutoGPT في setup/AutoGPT-src/ عبر عمليات الإيقاف حتى لا تعيد عمليات التشغيل التنزيل. لمسحها بالكامل، احذف setup/AutoGPT-src/.