Weak Login: خمّن لحد ما تزبط
Password Listباسوردات مسربة من مواقع تانية
Login Formآلاف المحاولات
Accountحد كان مستخدم نفس الباسورد
المهاجم مش لازم يخمّن عشوائي. الناس بتكرر نفس الباسورد في مواقع كتير، وقوايم الباسوردات المسربة متاحة. فبيجرب الإيميل + الباسورد المسرب على موقعك (اسمها credential stuffing)، أو يجرب أشهر الباسوردات على حسابات كتير.
الحل: طبقات
⏱️ Rate limit
حد للمحاولات لكل IP ولكل حساب. الاتنين مهمين: IP واحد بيجرب على حسابات كتير، أو IPs كتير على حساب واحد.
📱 MFA
TOTP (تطبيق authenticator) أو passkeys. الباسورد المسرب لوحده مبقاش كفاية.
login.js
import rateLimit from "express-rate-limit";const loginLimiter = rateLimit({ windowMs: 15 * 60 * 1000, limit: 10, // 10 محاولات لكل IP كل ربع ساعة standardHeaders: true,});app.post("/login", loginLimiter, async (req, res) => { const user = await findUserByEmail(req.body.email); const ok = user && (await argon2.verify(user.passwordHash, req.body.password)); if (!ok) { await recordFailedAttempt(req.body.email); // عدّاد لكل حساب + تأخير متزايد return res.status(401).json({ error: "الإيميل أو الباسورد غلط" }); }...});Open Redirect: لينك بدومينك يودّي لموقع مزيّف
Your Domainالمستخدم شايف اسم موقعك
next Paramاللي المهاجم حطه
Fake Siteصفحة login مزيفة
بعد الـ login بنرجّع المستخدم للصفحة اللي كان فيها: /login?next=/dashboard. لو السيرفر بيعمل redirect لأي قيمة، المهاجم يبعت لينك زي yoursite.com/login?next=https://evil.example. الإيميل فيه دومين حقيقي، المستخدم يعمل login، ويتحوّل لصفحة شبه موقعك تطلب منه الباسورد تاني.
login.js
// ❌ أي قيمةres.redirect(req.query.next);الحل: relative paths بس، أو allow-list
safeRedirect.js
export function safeNext(next) { // لازم يبدأ بـ / ومينفعش // أو /\ (دول بيتفهموا كدومين تاني) if (typeof next !== "string" || !next.startsWith("/") || next.startsWith("//") || next.startsWith("/\\")) { return "/"; } return next;}res.redirect(safeNext(req.query.next));خلّصت الفصل لما
🧠 اختبر نفسك
١) عملت rate limit لكل IP بس. إيه اللي فاتك؟
هجوم من IPs كتير (botnet) على نفس الحساب. لازم حد لكل حساب كمان.
٢) ليه open redirect خطر مع إنه مش بيسرق حاجة لوحده؟
عشان اللينك بدومينك الحقيقي، فالمستخدم بيثق فيه ويروح لصفحة phishing.
٣) القيمة //evil.example بتبدأ بـ / . آمنة؟
لأ. المتصفح بيفهم // كـ URL لدومين تاني. ارفضها.