تخطَّ إلى المحتوى
ARAB CODEمجتمع المطورين العرب

تجزئة كلمات المرور وإدارة الجلسات: ما الذي يجب أن تفعله بالضبط

درسنُشر ٢٤ أكتوبر ٢٠٢٦ · 0 رد · 1 مشاهدة#أمان#كلمات-المرور#جلسات#مصادقة
قبل ساعتين

مقدمة

تسريبات قواعد البيانات تحدث حتى لأكبر الشركات. السؤال: عندما تُسرّب قاعدتك، هل يستطيع المهاجم معرفة كلمات مرور أعضائك (التي يعيد كثيرون استخدامها في مواقع أخرى)؟ وهل يستطيع انتحال جلساتهم؟ الإجابة تعتمد على قرارين تتخذهما الآن.

أهداف التعلم

  • فهم الفرق بين التشفير والتجزئة، ولماذا نحتاج تجزئة بطيئة مع ملح.
  • اختيار Argon2id أو bcrypt أو scrypt بمعاملات مناسبة.
  • ترقية التجزئات القديمة بأمان عند الدخول.
  • بناء جلسات آمنة وإبطالها.

1. لا تشفير، ولا تجزئة سريعة

  • التشفير قابل للعكس بالمفتاح؛ إن سُرق المفتاح سُرقت كل كلمات المرور.
  • التجزئة السريعة (MD5، SHA-1، SHA-256) سريعة جداً عن قصد؛ بطاقة رسوميات واحدة تجرب مليارات الكلمات في الثانية.

المطلوب: دالة بطيئة ومكلفة عمداً مع ملح عشوائي لكل مستخدم (حتى لا تتطابق تجزئتان لكلمة واحدة ولا تنفع الجداول الجاهزة).

2. الخوارزميات الموصى بها

حسب توصيات OWASP الحالية:

  • Argon2id (الخيار الأول): مثلاً ذاكرة 19 ميغابايت، تكرارين، توازي 1 كحد أدنى.
  • scrypt: عند عدم توفر Argon2id.
  • bcrypt: مدعوم في كل مكان؛ بعامل تكلفة 10 على الأقل (كثيرون يستخدمون 12). انتبه أن bcrypt يتجاهل ما بعد 72 بايت من كلمة المرور.
import bcrypt from 'bcryptjs';

const COST = 12;
const hash = await bcrypt.hash(password, COST);        // الملح يُولد ويُخزن داخل الناتج
const ok = await bcrypt.compare(attempt, hash);        // مقارنة ثابتة الزمن

اختر التكلفة بحيث تستغرق التجزئة نحو ربع ثانية على خادمك؛ بطيئة للمهاجم ومقبولة للمستخدم.

3. ترقية التجزئات القديمة

إن ورثت قاعدة بتجزئات أضعف (bcrypt بتكلفة 10، أو صيغة قديمة)، لا تطلب من الجميع تغيير كلمة المرور. عند كل دخول ناجح أنت تعرف كلمة المرور الصحيحة لحظياً، فأعد تجزئتها بالإعداد الجديد:

if (ok && bcrypt.getRounds(user.passwordHash) < COST) {
  await db.user.update({ where: { id: user.id }, data: { passwordHash: await bcrypt.hash(password, COST) } });
}

4. سياسة كلمات المرور

  • طول أدنى 8 أحرف (يفضل 12+)، وطول أقصى معقول (64 مثلاً) دون منع الرموز أو المسافات.
  • ارفض كلمات المرور الشائعة والمسربة (قائمة كلمات شائعة أو خدمة مثل Have I Been Pwned بطريقة k-anonymity).
  • لا تفرض قواعد تعقيد مزعجة (حرف كبير + رمز + رقم)؛ الطول وحظر الشائع أهم.
  • قيّد محاولات الدخول لكل IP ولكل حساب.

5. الجلسات

import crypto from 'node:crypto';

const token = crypto.randomBytes(32).toString('base64url');          // 256 بت عشوائية
const tokenHash = crypto.createHash('sha256').update(token).digest('hex');
await db.session.create({ data: { userId, tokenHash, expiresAt } }); // نخزن البصمة فقط
res.cookie('session', token, { httpOnly: true, secure: true, sameSite: 'lax' });
  • رمز عشوائي قوي من مولد آمن تشفيرياً، لا معرّف متسلسل.
  • خزّن بصمته فقط (هنا SHA-256 كافية لأن الرمز عشوائي طويل، بخلاف كلمات المرور).
  • انتهاء صلاحية مطلق وخامل، وإبطال فوري عند الخروج.
  • عند تغيير كلمة المرور أو تفعيل التحقق بخطوتين: أبطل كل الجلسات الأخرى.
  • أنشئ جلسة جديدة عند الدخول (لا تعِد استخدام رمز سابق) لمنع تثبيت الجلسة (Session fixation).

6. التحقق بخطوتين

TOTP (تطبيقات المصادقة) يحمي حتى لو سُرقت كلمة المرور. خزّن السر مشفراً، واقبل نافذة زمنية صغيرة، وامنع إعادة استخدام الرمز نفسه، ووفر رموز استرداد تُعرض مرة واحدة.

تمرين عملي

  1. قِس زمن bcrypt.hash على جهازك بتكلفة 10 و12 و14 واختر المناسب.
  2. اكتب دالة دخول تُرقي التجزئات ذات التكلفة المنخفضة تلقائياً، مع اختبار يثبت الترقية.
  3. اكتب اختباراً يتأكد أن تغيير كلمة المرور يبطل كل الجلسات عدا الحالية.

أخطاء شائعة

  • SHA-256 أو MD5 لكلمات المرور، حتى مع ملح.
  • تخزين رموز الجلسات كما هي في القاعدة.
  • رسائل تكشف هل الخطأ في اسم المستخدم أم كلمة المرور.
  • عدم إبطال الجلسات عند تغيير كلمة المرور.
  • كتابة خوارزمية تجزئة خاصة بك.

الخلاصة

Argon2id أو bcrypt بمعاملات حديثة مع ترقية تلقائية للقديم، وحظر الكلمات الشائعة، وجلسات برموز عشوائية تُخزن بصمتها وتنتهي وتُبطل. هذه الأساسيات تحمي أعضاءك حتى في أسوأ الأيام.

مصادر مقترحة

  • OWASP Cheat Sheets: «Password Storage» و«Session Management» و«Authentication».
  • NIST SP 800-63B (إرشادات الهوية الرقمية).
  • خدمة Have I Been Pwned (واجهة Pwned Passwords).

الرد على الموضوع

سجّل الدخول للمشاركة في النقاش.

نقاشات مشابهة