
تصحيح أمني وإثبات مفهوم لموازن التحميل GoBalance onion، يغطي استعادة المفتاح الرئيسي عبر blindedSign وقبول الوصف المزوّر، مع اختبارات الانحدار.
حزمة استشارية لـ gitlab.com/n0tr1v/gobalance - فرع master، الالتزام bb1b0f3 ("fix crash").
الحالة: حرجة - مساران مستقلان للاستيلاء الكامل. فرع patch1 upstream لا يصلح أياً منهما.
تحتوي هذه الحزمة على تصحيح أمني كامل، وإثبات مفهوم شامل من البداية إلى النهاية لكلا مساري الهجوم، واختبارات انحدار تُثبت نجاعة الإصلاحات. وهي مصاحبة لتقرير تحليل الثغرات الكامل ("Laporan Analisis Keamanan GoBalance") المُعدّ فيما يتعلق بحوادث الاستيلاء على نطاقات onion التي أثرت على منتدَيين مؤخراً. يوجد دليل بناء واختبار خطوة بخطوة في USAGE.md.
| # | الثغرة | الخطورة | التأثير | الحالة |
|---|---|---|---|---|
| 1 | تسرّب مفتاح الهوية الرئيسي عبر blindedSign (بادئة nonce ثابتة) | حرجة | استرداد كامل لهوية onion من واصف عام واحد | مُصلحة |
| 2 | يقبل RegisterDescriptor واصفات نسخ مزوّرة (بدون تحقق من التوقيع / الارتباط) | حرجة | اختطاف حركة المرور لأي واجهة GoBalance | مُصلحة |
| 3 | مسار RNG حتمي مبذور بالوقت في pkg/brand | عالية (خطر كامن) | مادة مفاتيح قابلة للتنبؤ لأي شيء يستخدمه | مُزال |
| 4 | خلط نقاط المقدمة يستخدم math/rand | منخفضة | عشوائية ضعيفة في كود مجاور للبروتوكول | مُستبدل بـ crypto/rand |
كان المُوزِّع blindedSign() في pkg/stem/descriptor/hidden_service.go يمرّر
identityKey.Seed() - السكالر الخام المكوّن من 32 بايت a - إلى
BlindedSignWithTorKey(). مفاتيح صيغة Tor هي مفاتيح ممتدة: 64 بايت
(a || h)، حيث h هو مفتاح PRF الذي يشتق بادئة nonce لكل توقيع. مع غياب h،
كان مُدخل اشتقاق nonce فارغاً وأصبح
kPrime = SHA512("Derive temporary signing key hash input" || <empty>)
ثابتاً عاماً. النتيجة: أي شخص يستطيع قراءة واصف منشور واحد يمكنه إعادة حساب
nonce r، وحل السكالر المُعمّى
s' = (S − r) · H(R‖PK‖M)⁻¹ mod L، وإلغاء تعميته بمُضاعِف عام -
مما يسترد المفتاح الرئيسي لهوية خدمة onion. لا وصول للخادم، لا MitM، لا قوة غاشمة.
هذا بدائي استيلاء صامت على النطاق ويتوافق مع الآلية الملاحظة في عمليات اختطاف المنتدى الأخيرة.
الإصلاح: يمرّر المُوزِّع الآن المفتاح الممتد الكامل
(gobpk.PrivateKey.PrivKey())؛ ويُطلق BlindedSignWithTorKey panic على أي مفتاح
لا يكون بالضبط 64 بايت؛ ويفرض blindedSignP2 بشكل مستقل طول ESK
كدفاع في العمق؛ ويرفض gobpk.New مفاتيح Tor المقتطعة عند وقت التحميل.
كان NewReceivedDescriptor() يحلّل ويثق بكل ما تعطيه إياه الشبكة.
ولأن الاعتمادات الفرعية تُشتق من المفتاح المُعمّى المحمول داخل الواصف نفسه،
كان بإمكان المهاجم سكّ واصفات متسقة ذاتياً تشفيرياً لعنوان onion الخاص بشخص آخر
باستخدام مفاتيحه الخاصة. ثم تعيد الواجهة الأمامية نشر نقاط مقدمة المهاجم
تحت هوية الضحية - اختطاف كامل لحركة المرور لا يتطلب أي استرداد للمفاتيح على الإطلاق.
الإصلاح: تحقق ثلاثي الطبقات في
VerifyHiddenServiceDescriptorV3() الجديد: (1) توقيع الشهادة تحت
المفتاح المُعمّى، (2) توقيع الواصف تحت مفتاح التوقيع المُصدّق، و
(3) الارتباط - يجب أن يساوي المفتاح المُعمّى القيمة التي تحسبها الواجهة الأمامية
بشكل مستقل من الإجماع (GetBlindingParam + الفترة الزمنية) وعنوان النسخة.
RegisterDescriptor يفشل مغلقاً: بدون إجماع حي يرفض التسجيل بدلاً من الثقة العمياء.
gobalance-patch/
├── README.md ← this file (English)
├── USAGE.md ← step-by-step build & test guide (English)
├── README_ID.md ← ringkasan patch (Bahasa Indonesia)
├── gobalance-security.patch ← unified diff against master@bb1b0f3 (7 files, +360/−94)
├── gobalance-patched/ ← full pre-patched source tree (drop-in)
│ ├── go.mod / go.sum / main.go
│ ├── pkg/… ← patched libraries, incl. regression tests
│ ├── poc/ ← end-to-end attack demo + vulnerable code snapshot
│ ├── cmd/gbdemo/ ← standalone recovery demo CLI (+ E2E tests) - USAGE #13
│ └── tools/ ← pem2tor.py (PEM→Tor key converter), get_desc.py (descriptor fetch)
└── gobalance-v1/ ← community fork "GoBalance Enhanced v1.0" (Dread), bundled
as distributed for testing - still VULNERABLE - USAGE #14
# Option A - patch a fresh upstream checkout
git clone https://gitlab.com/n0tr1v/gobalance && cd gobalance
git apply /path/to/gobalance-security.patch
go build ./... && go test ./...
# Option B - use the bundled pre-patched tree (fastest)
cd gobalance-patched
go build ./...
go test ./poc/ -v # attack demo: succeeds vs vulnerable snapshot, fails vs patch
go test ./... # full suite: 8 packages ok
راجع USAGE.md للشرح الكامل مع المخرجات المتوقعة.
Test01_Vulnerable_MasterKeyRecoveredFromSingleDescriptor.Test02_Patched_TruncatedTorKeyRejected.Test03_Patched_TorPathSignaturesVerifyAsStdEd25519.Test04_Patched_AttackMathYieldsGarbage.TestForgedSelfConsistentDescriptorIsDetected.TestNewReceivedDescriptor_AcceptsHonestDescriptor,
_RejectsTamperedSignature, _RejectsWrongIdentityBinding.جميع المفاتيح في PoC تُولَّد محلياً وقت الاختبار. لم تُستهدف أي خدمات حقيقية.
TestBlindedSign الأصلي لا يزال
ينجح).patch1 upstream لا يصلح الثغرة #1 أو #2. يجب تطبيق هذا التصحيح
فوق master (أو استخدام الشجرة المُضمّنة).go.mod عن go 1.18).go vet ./... نظيف؛ go build ./... ناجح.go test ./... → 8 حزم ok، 0 إخفاقات، لا انحدارات (بما في ذلك
اختبارات upstream الموجودة مسبقاً).