
Forgejo 16.0.5 - عالي - عن بُعد - IDOR - GET /api/v1/user/keys/{id} يعيد مفاتيح SSH ومفاتيح النشر الخاصة بمستخدمين آخرين
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · forgejo-keys-idor
الفئة: IDOR الوصول: عن بُعد
Forgejo 16.0.5 (8d24b7d) - Forgejo
GET /api/v1/user/keys/{id} يقع في مجموعة المستخدم الحالي (reqToken، نطاق المستخدم). لا يزال المعالج يحمّل public_key بواسطة المعرّف الرقمي دون أي تحقق من المالك. يحتوي الجدول نفسه على مفاتيح المستخدمين، ومفاتيح النشر (deploy keys)، والهويات (principals). أما GPG في هذا الإصدار فيفعلها بشكل صحيح: GetGPGKeyForUserByID(ctx, ctx.Doer().ID, id). الحقول الإضافية الخاصة محجوبة. أما مادة المفتاح العام والعنوان والبصمة فليست محجوبة. المعرّفات متسلسلة.
رمز read:user يتنقل عبر 1 و2 و3 ويحصي مفاتيح SSH ومفاتيح النشر الخاصة بالآخرين.
| المعرّف | لا يوجد CVE بعد |
| الفئة | IDOR |
| الوصول | عن بُعد (مصادَق عليه عبر read:user / جلسة) |
| CWE | CWE-639 |
| CVSS | مرتفع: 7.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| المنتج | Forgejo |
| المتأثر | حتى v16.0.5 (8d24b7d) |
| المصادقة | مصادَق عليه (رمز read:user أو جلسة) |
| الترخيص | GNU Affero GPL v3.0 |
| المختبر | 127.0.0.1 فقط |
سجّل أو استخدم أي حساب، وأنشئ رمز read:user (أو استخدم ملف تعريف ارتباط الجلسة)، وتنقّل عبر /api/v1/user/keys/{id}. يحصل على العناوين والبصمات ومادة المفتاح العام لمفاتيح لا يملكها. لا يحصل على المفتاح الخاص. لا يحصل على shell. يحصي من لديه صلاحية الوصول إلى ماذا.
| الصلاحية | الطريقة / الهدف | الاستطلاع / السلامة / التوافر | مُثبت مختبريًا أم مُستنتج |
|---|---|---|---|
| قراءة عنوان مفتاح SSH العام لبصمة مستخدم آخر ومادة المفتاح | GET /api/v1/user/keys/{id} بصفة مالك أجنبي | استطلاع (سرية جرد المفتاح العام) | مُثبت مختبريًا. شاهد العنوان FORGEJO-KEYS-IDOR-WITNESS على المعرّف 1؛ قائمة المهاجم تحتوي فقط على المعرّف 2 |
| جرد مفاتيح النشر بالطريقة نفسها | المعالج نفسه، صفوف KeyTypeDeploy في public_key (OwnerID 0) | استطلاع | مُستنتج من الجدول. المختبر زرع مفتاح SSH لمستخدم، وليس مفتاح نشر |
| قراءة هويات شهادات SSH | المعالج نفسه، صفوف KeyTypePrincipal. يستثني ListPublicKeys هذا النوع | استطلاع | مُستنتج من الجدول |
| رؤية المفاتيح التي تنتمي إلى مستخدمين محدودين أو خاصين | لا يوجد تحقق من الرؤية في هذا البحث | استطلاع | مُستنتج من المعالج |
JSON إضافي (user، key_type، read_only) | appendPrivateInformation فقط إذا كان مديرًا أو المالك | استطلاع | مُثبت مختبريًا مغلق: استجابة غير المالك لم تحتوِ على حقل user |
مغلق على هذا المسار: مادة المفتاح الخاص، وshell، وGET /users/{username}/keys (قائمة عامة بنطاق اسم المستخدم)، وGPG GET /api/v1/user/gpg_keys/{id} (404 على معرّف أجنبي)، وDeletePublicKey (403 للمالك/المدير). GET /repos/{owner}/{repo}/keys/{id} عبر المستودعات يعيد 404 عندما لا يتطابق RepoID.
تصحيحات الأمان في v16.0.5 (#14370) كانت RCE عبر git-apply وCSRF في OpenID. لم تغلق هذا البحث. من الفئة نفسها مثل gitea-user-keys-idor، ولا يزال مفتوحًا هنا بشكل مستقل.
ثبّتّ Forgejo v16.0.5 بعد موجة 2026-09. كان Gitea 1.27.3 لا يزال يحتوي على هذا البحث. لقد تباعد Forgejo، لذا أعدت قراءة معالج مفاتيح المستخدم الحالي بجانب GPG بدلًا من نسخ حزمة Gitea. GPG يعيد 404 على معرّف أجنبي. أما SSH فلا.
المنعطفات الخاطئة المسجلة مسبقًا: اعتبار قائمة المهاجم نفسه هي التسريب (وهي ليست كذلك - القائمة محدودة النطاق، أما GET-by-id فليس كذلك)؛ واعتبار DISABLE_REGISTRATION=true على المثبّت إغلاقًا (أي حساب موجود يكفي)؛ وreverse shell. مسرحيات.
python3 forgejo-keys-idor-Abraxas-Labs.py
أو:
cd lab
./run.sh
استهدف فقط http://127.0.0.1:19310. الصورة codeberg.org/forgejo/forgejo:16.0.5. حسابان. الشاهد FORGEJO-KEYS-IDOR-WITNESS.
IOC planted victim-id=1 attacker-id=2
IOC attacker-list status=200 ... title=attacker-own-key
IOC get id=1 status=200 ... FORGEJO-KEYS-IDOR-WITNESS
IOC gpg-neg id=1 status=404
SUCCESS forgejo-keys-idor victim-id=1 get-http=200 list-has-id=no gpg-http=404 FORGEJO-KEYS-IDOR-WITNESS
404 إلا إذا كان key.OwnerID == ctx.Doer().ID (أو مدير الموقع). ارفض KeyTypeDeploy / KeyTypePrincipal على هذا المسار. طابِق GetGPGKeyForUserByID.
GetPublicKeyGNU Affero GPL v3.0. انظر LICENSE. مختبر loopback فقط. لا ضمان.