بوابة دخول الغربان لا تحد من عدد المحاولات وتقول بصراحة إن كان الاسم موجودا أو لا وكلمة مرور الزعيم ضعيفة من النوع الشائع اسم المستخدم admin
بوابة دخول الغربان نموذج تسجيل دخول كلمات المرور ضعيفة وشائعة ولا يوجد حد لعدد المحاولات ورسائل الخطأ تكشف إن كان المستخدم موجودا أم لا حساب admin هدفك
لماذا نجح الحل
اجتمعت هنا عيوب توثيق: كلمة مرور ضعيفة وشائعة ولا حد لعدد المحاولات (لا rate limit ولا قفل) ورسائل خطأ تكشف وجود المستخدم فصار التخمين سهلا الحل: افرض كلمات مرور قوية وامنع الشائعة منها وحد المحاولات (تأخير تصاعدي أو قفل مؤقت) ووحد رسالة الخطأ لكل الحالات وأضف تحققا بخطوتين للحسابات المهمة
السبب الجذري
ثلاث مشاكل تجتمع كلمة مرور ضعيفة وغياب حد للمحاولات ورسائل خطأ تميز بين مستخدم غير موجود وكلمة مرور خاطئة فتسهل تعداد المستخدمين والتخمين
كيف يصلح الكود
ثلاث طبقات: كلمات مرور قوية ومجزأة بـ bcrypt وحد للمحاولات ورسالة خطأ واحدة موحدة ثم تحقق بخطوتين
الكود المصاب
app.post('/login', (req, res) => {
const user = db.user(req.body.username);
if (!user) return res.json({ ok: false, error: 'No such user' }); // enumeration
// No rate limit, no lockout, weak password allowed.
if (user.password === req.body.password) { login(res, user); return res.json({ ok: true }); }
res.json({ ok: false, error: 'Wrong password' }); // different message
});
الكود الآمن
app.post('/login', rateLimit({ max: 5, per: '15m', lockout: true }), async (req, res) => {
const user = db.user(req.body.username);
const ok = user && await bcrypt.compare(req.body.password, user.hash);
if (!ok) return res.json({ ok: false, error: 'Invalid username or password' }); // one message
login(res, user); // plus 2FA for privileged accounts
res.json({ ok: true });
});
الأثر في الواقع
التخمين الآلي للكلمات credential stuffing و brute force يخترق الحسابات بكلمات مرور ضعيفة أو مسربة وهو من أكثر أسباب اختراق الحسابات في الواقع
كيف يكتشفها المدافعون
المدافع يرصد كثرة محاولات الدخول الفاشلة من مصدر واحد أو على حساب واحد ويوحد رسائل الخطأ ويفرض حدا للمعدل و MFA