باگ‌های امنیتی که توسعه‌دهندگان Node.js به محیط عملیاتی (Production) می‌فرستند

سال گذشته کدهای یک استارتاپ را بازبینی کردم. کدها تمیز به نظر می‌رسیدند. تست‌ها هم با موفقیت پاس می‌شدند.

سپس این خط را دیدم: const query = \SELECT * FROM users WHERE email = '${req.body.email}'``

این یک باگ SQL injection است. این استارتاپ ۸ ماه این کد را در محیط عملیاتی اجرا کرد. هیچ توسعه‌دهنده یا مدیر فنی (CTO) متوجه آن نشد.

این باگ‌ها نامرئی هستند چون کد به درستی کار می‌کند. کد تا زمانی درست کار می‌کند که یک کاربر یک دستور مخرب را در یک فیلد ورودی تایپ کند.

این ۵ اشتباه رایج را متوقف کنید:

۱. استفاده از SQL خام با ورودی کاربر برای کوئری‌ها از template literals استفاده نکنید. این کار به مهاجمان اجازه می‌دهد به پایگاه داده شما دسترسی پیدا کنند.

  • بد: const query = \SELECT * FROM users WHERE email = '${email}'``
  • خوب: از parameterized queries استفاده کنید. const query = 'SELECT * FROM users WHERE email = $1' db.query(query, [email])

۲. لو رفتن اطلاعات حساس در Git توسعه‌دهندگان اغلب فایل‌های .env را در مخازن (repositories) کامیت می‌کنند. این کار باعث افشای URLهای پایگاه داده و کلیدهای API شما می‌شود. همیشه .env را به فایل .gitignore خود اضافه کنید.

۳. استفاده از jwt.decode به جای jwt.verify متد jwt.decode فقط توکن را می‌خواند. این متد بررسی نمی‌کند که آیا توکن واقعی است یا خیر. هر کسی می‌تواند یک توکن رمزگشایی‌شده را جعل کند.

  • بد: const user = jwt.decode(token)
  • خوب: همیشه امضا (signature) را تأیید کنید. const user = jwt.verify(token, process.env.JWT_SECRET)

۴. نبود محدودیت نرخ درخواست (rate limiting) در اندپوینت‌های احراز هویت بدون محدودیت نرخ درخواست، مهاجمان می‌توانند میلیون‌ها رمز عبور را از طریق حمله brute force امتحان کنند. از یک کتابخانه برای محدود کردن تلاش‌های ورود استفاده کنید.

  • خوب: محدودیتی معادل ۱۰ تلاش در هر ۱۵ دقیقه اعمال کنید.

۵. پیام‌های خطای بیش از حد جزئی (Verbose) ارسال پیام‌های خطای خام به کلاینت به مهاجمان کمک می‌کند تا ساختار سیستم شما را شناسایی کنند. آن‌ها نام جداول و نوع پایگاه داده شما را می‌بینند.

  • بد: res.status(500).json({ error: error.message })
  • خوب: خطا را به صورت داخلی لاگ کنید. یک پیام عمومی به کاربر ارسال کنید. res.status(500).json({ error: 'Something went wrong' })

قبل از اینکه یک اندپوینت را منتشر کنید، این سوال را بپرسید: اگر کاربر داده‌های غیرمنتظره‌ای ارسال کند چه اتفاقی می‌افتد؟

باگ‌های امنیتی به ندرت پیچیده هستند. آن‌ها زمانی رخ می‌دهند که فراموش می‌کنید به عاملان مخرب فکر کنید.

شما چه باگ امنیتی‌ای را در محیط عملیاتی پیدا کرده‌اید؟

منبع: https://dev.to/manolito99/the-security-bug-every-nodejs-developer-ships-to-production-49e6