Những lỗi bảo mật mà các nhà phát triển Node.js thường đưa lên production

Tôi đã review code cho một startup vào năm ngoái. Mã nguồn trông rất sạch sẽ. Các bài kiểm tra đều vượt qua.

Sau đó, tôi thấy dòng này: const query = \SELECT * FROM users WHERE email = '${req.body.email}'``

Đây là một lỗi SQL injection. Startup này đã chạy mã này trên production suốt 8 tháng trời. Không một lập trình viên hay CTO nào phát hiện ra nó.

Những lỗi này thường vô hình vì mã vẫn hoạt động bình thường. Nó chỉ gặp vấn đề khi một người dùng nhập một câu lệnh độc hại vào trường dữ liệu đầu vào.

Hãy dừng ngay 5 sai lầm phổ biến sau:

  1. Sử dụng SQL thuần với dữ liệu đầu vào từ người dùng Đừng sử dụng template literals cho các câu truy vấn. Điều này cho phép kẻ tấn công truy cập vào cơ sở dữ liệu của bạn.
  • Sai: const query = \SELECT * FROM users WHERE email = '${email}'``
  • Đúng: Sử dụng parameterized queries. const query = 'SELECT * FROM users WHERE email = $1' db.query(query, [email])
  1. Làm rò rỉ thông tin bí mật trong Git Các lập trình viên thường commit các file .env vào repository. Điều này làm lộ URL cơ sở dữ liệu và các API key của bạn. Hãy luôn thêm .env vào file .gitignore.

  2. Sử dụng jwt.decode thay vì jwt.verify jwt.decode chỉ đọc token. Nó không kiểm tra xem token đó có thực sự hợp lệ hay không. Bất kỳ ai cũng có thể giả mạo một token đã được giải mã.

  • Sai: const user = jwt.decode(token)
  • Đúng: Luôn luôn xác thực chữ ký (signature). const user = jwt.verify(token, process.env.JWT_SECRET)
  1. Thiếu rate limiting trên các endpoint xác thực Nếu không có rate limiting, kẻ tấn công có thể thử hàng triệu mật khẩu thông qua tấn công brute force. Hãy sử dụng một thư viện để giới hạn số lần đăng nhập.
  • Đúng: Thêm giới hạn 10 lần thử trong mỗi 15 phút.
  1. Thông báo lỗi quá chi tiết Việc gửi các thông báo lỗi thô đến client giúp kẻ tấn công nắm bắt được cấu trúc hệ thống của bạn. Chúng có thể thấy tên bảng và loại cơ sở dữ liệu mà bạn đang dùng.
  • Sai: res.status(500).json({ error: error.message })
  • Đúng: Ghi log lỗi nội bộ. Gửi một thông báo chung chung cho người dùng. res.status(500).json({ error: 'Something went wrong' })

Trước khi triển khai một endpoint, hãy tự hỏi một câu: Điều gì sẽ xảy ra nếu người dùng gửi dữ liệu không mong muốn?

Các lỗi bảo mật hiếm khi phức tạp. Chúng xảy ra khi bạn quên mất việc phải tính đến những kẻ có ý đồ xấu.

Bạn đã từng phát hiện lỗi bảo mật nào trên production chưa?

Nguồn: https://dev.to/manolito99/the-security-bug-every-nodejs-developer-ships-to-production-49e6