
إثبات مفهوم ومختبر لثغرة SSRF مُصادَق عليها في نقطة نهاية ترحيل المستودع في Gitea، حيث يتبع git عمليات إعادة توجيه HTTP إلى git HTTP على الواجهة المحلية ويسرّب الكائنات الداخلية.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · gitea-git-redir-ssrf
Gitea 1.27.3 - Gitea
IsMigrateURLAllowed هو استدعاء لمرة واحدة لـ net.LookupIP على الرابط الذي كتبته. ثم تمر البايتات عبر git clone --mirror. من المفترض أن يمنع HandleGitCmdHTTPRedirection git من اتباع تلك القفزة. لكنه لا يفعل شيئًا. التعليق هو الاكتشاف بحد ذاته: لقد تركوا http.followRedirects=false معطّلًا لأن GitLab يعيد 301 بدون .git. استدعاء جلب النسخة المتطابقة (pull-mirror fetch) يستدعي نفس الدالة عديمة الأثر.
يمكن لمستخدم مسجّل الدخول أن يهاجر من مضيف طُعم مُدرج في القائمة المسموحة، فيتبع git إعادة التوجيه 302 إلى git HTTP على loopback. الكائنات الداخلية تصل إلى مستودع يملكه.
| ID | لا يوجد CVE بعد |
| CWE | CWE-918 |
| CVSS | High: 7.7 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N |
| Product | Gitea |
| Affected | حتى v1.27.3 (146cc3e) |
| Auth | مصادَق عليه (التسجيل المفتوح افتراضيًا) |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 فقط |
سجّل، ثم هاجر من رابط يبدو خارجيًا يعيد 302 إلى http://127.0.0.1:.../internal.git. الهجرة المباشرة إلى loopback مرفوضة. أما النسخ المتطابق الذي يتبع إعادة التوجيه فليس مرفوضًا. ملف الإثبات (witness) يصل إلى مستودع الخاص به.
ليس قراءة قرص عبر file://. وليس X-Gitea-Internal-Auth على /api/internal (لن يضبط git ذلك الترويسة). وليس RCE بدون مصادقة. وليس RCE عبر metadata إلا إذا أثبت بشكل منفصل أن git خزّن المحتوى.
من نفس الإصدار: keys IDOR، hostmatcher 0.0.0.0/8.
أغلقت v1.27.3 موجة GHSA لعام 2026: CVE-2026-60004 (RCE عبر خطاف diffpatch، CISA KEV)، CVE-2026-59774 (Org-mode #+INCLUDE بدون مصادقة)، بوابات fork-PR Actions، وافتراضي X-WEBAUTH-USER في reverse-proxy. ابقَ على 1.27.3+ لأجل تلك. ومع ذلك بقيت على ذلك الإصدار.
أصلح CVE-2026-59765 دالة Go uri.Open. وأصلح CVE-2026-22874 دالة Go reservedIPNets. أما مُعيد توجيه git فلا يزال FIXME. سطر سجل التغييرات "disable HTTP redirects on pull mirror sync" لا يخص هذه الدالة.
يضع المختبر Gitea على 8.8.4.2 بحيث يبدو مضيف الطُعم على 8.8.4.10 خارجيًا بالنسبة إلى hostmatcher. يرتبط git HTTP الداخلي على loopback فقط داخل netns الخاص بـ Gitea (network_mode: service:gitea، المنفذ 9418). يجب أن تفشل الهجرة المباشرة إلى 127.0.0.1. ويجب أن ينجح النسخ المتطابق الذي يتبع إعادة التوجيه. يعيد redir.py توجيه 302 من /bait.git إلى http://127.0.0.1:9418/internal.git. ملف الإثبات WITNESS يحتوي على GHSA-GITEA-GIT-REDIR-SSRF.
مسارات خاطئة مسجّلة مسبقًا: ALLOW_LOCALNETWORKS true (عندها تختفي القائمة المسموحة)؛ file://؛ X-Gitea-Internal-Auth؛ reverse shell. مسرحية. الضابط هو رفض الهجرة المباشرة إلى loopback.
أخطاء العميل تبدو كأخطاء المنتج. مساعد يحجب http.client لا يرسل أي حزمة. .recv() على HTTPResponse ليست .read(). أذكر ذلك مرة واحدة لأنه كلّفني وقتًا وبدا، لدقيقة، كأن 1.27.3 قد أنهى المهمة.
cd lab
./run.sh
استهدف فقط http://127.0.0.1:18103. مع ALLOW_LOCALNETWORKS=false.
negative-loopback status=422 You can not import from disallowed hosts
migrate-bait status=201 clone_addr=http://8.8.4.10/bait.git
fetch raw/WITNESS status=200 GHSA-GITEA-GIT-REDIR-SSRF
SUCCESS Gitea #2 git HTTP redirect SSRF
لا تعامل DNS وقت الإرسال كحدود. افرض http.followRedirects=false (وطبّع روابط النسخ إلى .git حتى يظل GitLab يعمل)، أو مرّر git HTTP عبر dialer يعيد تشغيل hostmatcher عند كل قفزة.
HandleGitCmdHTTPRedirection · IsMigrateURLAllowedGNU Affero GPL v3.0. انظر LICENSE. مختبر loopback فقط. دون أي ضمان.