Bảo mật thường bị coi là việc của "đội security", còn lập trình viên chỉ cần lo tính năng. Thực tế lại ngược lại: phần lớn lỗ hổng xuất phát từ chính những dòng code hằng ngày, như một API quên kiểm tra quyền, một câu truy vấn nối chuỗi hay một thông báo lỗi tiết lộ quá nhiều. OWASP Top 10 là tài liệu tham chiếu nổi tiếng, liệt kê mười nhóm rủi ro bảo mật nghiêm trọng nhất đối với ứng dụng web, được tổng hợp từ dữ liệu kiểm thử thực tế và khảo sát cộng đồng. Phiên bản mới nhất là OWASP Top 10:2025. Bài viết này giải thích từng mục bằng ngôn ngữ đời thường, kèm gợi ý phòng tránh.
A01: Broken Access Control – Kiểm soát truy cập bị phá vỡ
Người dùng làm được những việc lẽ ra họ không được phép. Ví dụ kinh điển: đổi /api/orders/1001 thành /api/orders/1002 và xem được đơn hàng của người khác. Trong bản 2025, lỗi giả mạo yêu cầu phía máy chủ (SSRF) cũng được gộp vào nhóm này.
- Kiểm tra quyền ở phía server cho mọi request, không tin vào việc ẩn nút trên giao diện.
- Mặc định từ chối, chỉ cho phép khi có quy tắc rõ ràng.
- Luôn kiểm tra tài nguyên có thuộc về người dùng hiện tại hay không.
A02: Security Misconfiguration – Cấu hình sai
Tài khoản mặc định chưa đổi mật khẩu, bucket lưu trữ để công khai, bật chế độ debug trên production, thiếu các HTTP header bảo mật. Khi ứng dụng ngày càng phụ thuộc vào cấu hình, nhóm rủi ro này càng phổ biến.
- Tự động hoá cấu hình bằng hạ tầng dưới dạng mã (IaC) để dễ rà soát.
- Tắt tính năng, cổng và dịch vụ không dùng đến.
A03: Software Supply Chain Failures – Lỗi chuỗi cung ứng phần mềm
Đây là bản mở rộng của mục "thành phần lỗi thời" trước đây. Rủi ro không chỉ đến từ thư viện cũ có lỗ hổng, mà còn từ package độc hại, công cụ build hay pipeline CI/CD bị xâm nhập.
- Dùng lock file và quét dependency định kỳ bằng công cụ như
npm audit, Dependabot. - Chỉ cài package từ nguồn tin cậy, cẩn thận với tên package na ná nhau.
- Bảo vệ pipeline CI/CD: giới hạn quyền, quản lý secrets chặt chẽ.
A04: Cryptographic Failures – Lỗi mã hoá
Dữ liệu nhạy cảm bị lộ do không mã hoá hoặc mã hoá sai cách: truyền qua HTTP thường, lưu mật khẩu bằng MD5, tự chế thuật toán mã hoá.
- Bắt buộc HTTPS, bật HSTS.
- Băm mật khẩu bằng thuật toán chuyên dụng như Argon2id hoặc bcrypt.
- Không tự viết thuật toán mã hoá; dùng thư viện đã được kiểm chứng.
A05: Injection – Chèn mã độc
Dữ liệu người dùng được ghép thẳng vào câu lệnh SQL, lệnh hệ điều hành hay HTML. Cross-site scripting (XSS) cũng thuộc nhóm này.
// Nguy hiểm: nối chuỗi
db.query(`SELECT * FROM users WHERE email = '${email}'`);
// An toàn: truy vấn tham số hoá
db.query('SELECT * FROM users WHERE email = $1', [email]);- Luôn dùng truy vấn tham số hoá hoặc ORM.
- Escape dữ liệu theo đúng ngữ cảnh khi hiển thị; tận dụng cơ chế tự escape của framework.
- Kiểm tra đầu vào theo danh sách cho phép.
A06: Insecure Design – Thiết kế không an toàn
Lỗ hổng nằm ở chính logic thiết kế chứ không phải lỗi code. Ví dụ: luồng đặt lại mật khẩu dựa vào câu hỏi bí mật dễ đoán, hay không giới hạn số lần áp mã giảm giá.
- Thực hiện mô hình hoá mối đe doạ (threat modeling) từ giai đoạn thiết kế.
- Đặt giới hạn tần suất cho các thao tác nhạy cảm.
A07: Authentication Failures – Lỗi xác thực
Cho phép đăng nhập thử mật khẩu vô hạn lần, chấp nhận mật khẩu yếu, không vô hiệu hoá phiên khi đăng xuất, để lộ session ID trên URL.
- Hỗ trợ xác thực đa yếu tố (MFA).
- Giới hạn và làm chậm các lần đăng nhập sai.
- Tạo session ID mới sau khi đăng nhập, huỷ phiên khi đăng xuất.
A08: Software or Data Integrity Failures – Lỗi toàn vẹn dữ liệu và phần mềm
Ứng dụng tin tưởng dữ liệu hoặc mã mà không kiểm tra tính toàn vẹn: giải tuần tự hoá (deserialize) dữ liệu không tin cậy, tải script từ CDN không có kiểm tra, cập nhật tự động không xác minh chữ ký.
- Dùng chữ ký số hoặc checksum cho bản cập nhật và artifact.
- Dùng Subresource Integrity (SRI) khi nhúng script từ bên ngoài.
- Tránh deserialize dữ liệu từ nguồn không tin cậy.
A09: Security Logging and Alerting Failures – Thiếu ghi log và cảnh báo
Bị tấn công nhưng không ai biết, vì không có log hoặc có log mà không có cảnh báo. Nhiều sự cố chỉ được phát hiện sau thời gian dài.
- Ghi log các sự kiện quan trọng: đăng nhập thất bại, thay đổi quyền, lỗi kiểm soát truy cập.
- Không ghi mật khẩu, token hay dữ liệu nhạy cảm vào log.
- Thiết lập cảnh báo và quy trình phản ứng khi có dấu hiệu bất thường.
A10: Mishandling of Exceptional Conditions – Xử lý sai tình huống ngoại lệ
Nhóm mới trong bản 2025, tập trung vào việc xử lý lỗi không đúng: trả stack trace cho người dùng, bỏ qua exception, hoặc nguy hiểm hơn là "fail open", tức khi kiểm tra quyền gặp lỗi thì hệ thống lại cho phép đi tiếp.
- Thiết kế theo nguyên tắc "fail closed": có lỗi thì từ chối.
- Bắt và xử lý exception có chủ đích, trả thông báo lỗi chung cho người dùng, ghi chi tiết vào log nội bộ.
- Kiểm thử các tình huống bất thường: timeout, dữ liệu rỗng, dịch vụ phụ thuộc ngừng hoạt động.
Kết luận
Phần lớn lỗ hổng trong OWASP Top 10 có thể ngăn chặn bằng những thói quen lập trình đúng: kiểm tra quyền ở server, tham số hoá truy vấn, mã hoá đúng cách, quản lý dependency cẩn thận và xử lý lỗi theo hướng an toàn. Hãy đưa các mục này vào checklist review code và tích hợp công cụ quét vào CI. Bảo mật không phải bước cuối cùng trước khi phát hành, mà là trách nhiệm xuyên suốt của mỗi lập trình viên.






