Files
tripz-llc/docs/21-siro-audit.md
T
Hamza-AyedandClaude Opus 4.8 4e9d4d9be1 docs: تدقيق سيرو — 17 عيباً أمنياً مصنَّفاً بالخطورة (للمعالجة لاحقاً)
سجلّ قابل للمعالجة لكل ما رُصد في كود سيرو الحيّ أثناء بناء Tripz: IDOR
السحب · double-spend · تسرّب رسم 3500 · 5 كتابات بلا معاملة · مقارنة كلمة
مرور نصّية تتجاوز الـhash · كلمة مرور مشتركة ثابتة · OTP 3 خانات · مسح
جدول وفكّ تشفير للتحقق · AES-CBC بـIV ثابت · إلخ. كل بند بخطورته وإصلاحه
المقترح لسيرو وكيف عالجناه في Tripz.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 19:38:18 +03:00

7.5 KiB

21 — تدقيق سيرو: العيوب الأمنية والمشاكل المرصودة

سجلّ قابل للمعالجة لكل ما رُصد في كود سيرو الحيّ (~/development/App/Siro) أثناء بنائنا لـTripz. الغرض مزدوج: (1) ألّا نكرّرها في Tripz، (2) قائمة إصلاحات جاهزة لسيرو نفسه حين نعالجه.

كل ما يلي في سيرو (PHP/MySQL) لا في Tripz. حيث أصلحنا المكافئ في Tripz، أُشير إليه. الخطورة: 🔴 حرجة · 🟠 متوسطة · 🟡 منخفضة/جودة.

آخر تحديث: 2026-07-17.


المدفوعات والسحب (payment_server/ · request_payout.php · finalizePayout)

# الخطورة العيب الإصلاح المقترح لسيرو حالنا في Tripz
S1 🔴 IDOR في السحب: request_payout.php يأخذ driverId/phone من جسم الطلب لا من التوكن — سائق يسحب رصيد غيره إلى هاتفه. اشتقاق هوية السائق من JWT الموقَّع حصراً. ✅ نظيف — payouts.request يستعمل user.userId من التوكن.
S2 🔴 لا حجز رصيد عند طلب السحب → طلبات متزامنة تمرّ كلها = double-spend. حجز ذرّي عند التأكيد قبل أي تحويل. ✅ خصم ذرّي عند confirm (I1/I4).
S3 🔴 رسم 3500 يناقض نفسه: الفحص يتطلب amount + 3500 والإنهاء يخصم amount - 3500 = تسرّب مال. الرقم مكتوب يدوياً مرّتين. ثابت واحد + اختبار يطابق الفحص بالخصم. ✅ لا رسم مكرّر؛ العمولة من الرصيد التشغيلي (docs/18).
S4 🔴 finalizePayout يعمل 5 كتابات بلا معاملة/تراجع → فشل في المنتصف يترك سحباً نصف مُسوّى. لفّ الكتابات في transaction واحدة. ✅ الخصم والقيد في معاملة واحدة (I1).
S5 🟠 driverWallet.amount نوعه varchar(10) — المال مخزَّن نصّاً، وSUM() على نصوص. تحويله DECIMAL(12,3). ✅ numeric(12,3) + CHECK (balance >= 0).
S6 🟠 لا OTP على السحب — phone_verification موجود لكنه مربوط بالتسجيل/الدخول فقط. OTP + تحقّق قبل التحويل. ✅ OTP على السحب عبر المُوزِّع (I4).
S7 🟡 جدولان متداخلان لنفس المفهوم: payout_requests وdriver_withdrawal_requests. توحيدهما في جدول واحد. ✅ جدول pay_payouts واحد.

المصادقة وكلمة المرور (auth/)

# الخطورة العيب الإصلاح المقترح لسيرو حالنا في Tripz
S8 🔴 مقارنة كلمة مرور نصّية: loginUsingCredentialsWithoutGoogle.php سطر 114 — `password_verify(...) $password === $data['password']`. الشقّ الثاني يتجاوز الـhash كلياً، ويطابق كلمة المرور المخزَّنة نصّاً لو كانت كذلك.
S9 🟠 كلمة مرور مشتركة ثابتة 'SiroPassenger2026!' للحسابات التجريبية في الكود. نقلها لمتغيّر بيئة على الأقل، والأفضل إزالة المسار. ✅ لا مسار كلمة مرور.
S10 🟡 password = hash($email) وهمي عند التسجيل — حقل بلا معنى يوحي بأمان غير موجود. إزالة العمود إن لم يُستعمل. ✅ لا عمود كلمة مرور.
S11 🟠 user_type يُؤخذ من الطلب بلا تحقّق توقيع (تعليقهم صريح: "JWT not trusted without signature verification") — عميل يدّعي admin. يُلطَّف جزئياً بقائمة ADMIN_PHONE_NUMBERS. التحقق من توقيع JWT واعتماد الدور منه. ✅ الدور من التوكن الموقَّع (RolesGuard).

الـOTP (auth/otp/)

# الخطورة العيب الإصلاح المقترح لسيرو حالنا في Tripz
S12 🟠 رمز OTP من 3 خانات (1000 احتمال فقط) — قابل للتخمين. 6 خانات + قفل بعد المحاولات. ✅ 4 خانات (قابل للرفع) + قفل 5 محاولات (D4). عند النقل نرفعه لـ6.
S13 🟠 مسح جدول كامل وفكّ تشفير كل صف للتحقق من الرمز (verify.php: SELECT * ... foreach decrypt) — بطيء ويتسرّب توقيتاً. فهرس أعمى (blind index) على الهاتف. ✅ phone_bidx (HMAC حتمي) للبحث المباشر (docs/16).
S14 🟡 مساران متوازيان للـOTP: request.php/verify.php (قاعدة، مشفّر) وOtpService.php (Redis) — تكرار وتضارب. توحيد على مسار واحد. ✅ مسار Redis واحد.
S15 🟡 echo لأخطاء المزوّد الخام في sendIntaleqOtp ("Temporarily echo the raw error") — تسريب تشخيصي في الإنتاج. إزالة الـecho، لوغ فقط. ✅ لا echo؛ لوغ خادمي.
S16 🟡 تخزين OTP مشفَّراً بـGCM في القاعدة ثم مسح الجدول لفكّه — تكلفة بلا فائدة (الرمز قصير العمر، الأنسب Redis + hash). Redis + password_hash كما في OtpService. ✅ Redis مباشرةً.

التشفير (core/Security/EncryptionHelper.php)

# الخطورة العيب الإصلاح المقترح لسيرو حالنا في Tripz
S17 🔴 AES-CBC بـIV ثابت (موثَّق سابقاً في docs/16) — نفس النص ينتج نفس الشيفرة، ويسرّب الأنماط. AES-256-GCM + IV عشوائي لكل قيمة. ✅ منفَّذ (docs/16).

حدّ الطلبات (core/Auth/RateLimiter.php) — جيد، للنسخ لا للإصلاح

تصميمه سليم: حدود مسمّاة لكل نوع + fallback بملف عند تعطّل Redis (fail-closed). النقطة الوحيدة: يتتبّع بـIP:userId — جيد، لكن نقاط ما قبل الدخول بالـIP وحده (لا مفرّ). ليس عيباً — مرجع نتعلّم منه.

نقاط تحتاج تأكيد المالك (لم أجزم بها)

  • هل raw_sms_log + Gemini (تسوية الدفع من رسائل المزوّد) يُدقَّق ضد إعادة الاستعمال (نفس الرسالة تُسوّى مرتين)؟ — يحتاج فحص webhook_sms/webhook.php عند معالجة سيرو.
  • هل توكنات Nabeh/مفاتيح Kazumi في متغيّرات بيئة على كل الخوادم أم مكتوبة في مكان ما؟ — يُتحقَّق عند النقل.

← ذو صلة: 16-encryption · 17-backend-backlog · 18-driver-credit-commission