Bảo Mật Ứng Dụng Web 2025: OWASP Top 10 và Các Biện Pháp Phòng Chống

Những lỗ hổng phổ biến nhất và cách khắc phục

Hướng dẫn9 tháng 12, 2025Lê Văn Bảo · Biên tập viên
Bảo Mật Ứng Dụng Web 2025: OWASP Top 10 và Các Biện Pháp Phòng Chống

Bảo mật là ưu tiên hàng đầu trong phát triển phần mềm. Tìm hiểu OWASP Top 10 năm 2025, các lỗ hổng bảo mật phổ biến và hướng dẫn thực hành bảo mật cho developer.

Bảo mật ứng dụng web - Không thể bỏ qua trong năm 2025

Với sự gia tăng của các cuộc tấn công mạng, bảo mật không còn là "nice-to-have" mà là yêu cầu bắt buộc. Bài viết này tổng hợp các lỗ hổng phổ biến theo OWASP Top 10 và cách phòng chống.

🔴 OWASP Top 10 - 2025 Edition

1. Broken Access Control

Vấn đề: User truy cập được resource không thuộc quyền của họ.


// ❌ Sai - Không kiểm tra ownership
app.get("/api/orders/:id", async (req, res) => {
  const order = await Order.findById(req.params.id);
  res.json(order);
});
// ✅ Đúng - Kiểm tra user sở hữu order app.get("/api/orders/:id", async (req, res) => { const order = await Order.findOne({ _id: req.params.id, userId: req.user.id // Chỉ lấy order của user hiện tại }); if (!order) return res.status(404).json({ error: "Not found" }); res.json(order); });

2. Cryptographic Failures

Vấn đề: Lưu trữ password, API key không đúng cách.


// ❌ Sai - Hash yếu
const hash = crypto.createHash("md5").update(password).digest("hex");
// ✅ Đúng - Dùng bcrypt với salt import bcrypt from "bcrypt"; const hash = await bcrypt.hash(password, 12); const isValid = await bcrypt.compare(input, hash);

3. Injection (SQL, NoSQL, Command)


// ❌ SQL Injection vulnerable
const query = `SELECT * FROM users WHERE email = "${email}"`;

// ✅ Parameterized query
const [users] = await db.query(
"SELECT * FROM users WHERE email = ?",
[email]
);

// ✅ Với Prisma ORM const user = await prisma.user.findUnique({ where: { email } });

4. Insecure Design

Thiết kế hệ thống thiếu security mindset từ đầu:

  • Không có rate limiting cho login → Brute force
  • Password reset không expire → Token reuse
  • Không validate file upload → Malware upload

5. Security Misconfiguration


// next.config.js - Security headers
const securityHeaders = [
  { key: "X-Frame-Options", value: "DENY" },
  { key: "X-Content-Type-Options", value: "nosniff" },
  { key: "X-XSS-Protection", value: "1; mode=block" },
  { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
  { key: "Content-Security-Policy", value: "default-src 'self'; ..." }
];
module.exports = { async headers() { return [{ source: "/(.*)", headers: securityHeaders }]; } };

🛡️ Checklist bảo mật cho Developer

Authentication & Authorization

  • ✅ Sử dụng JWT với expiration ngắn (15-30 phút)
  • ✅ Implement refresh token rotation
  • ✅ MFA cho admin và sensitive operations
  • ✅ Rate limiting: 5 login attempts / 15 phút

Input Validation


import { z } from "zod";

const UserSchema = z.object({
email: z.string().email(),
password: z.string().min(8).max(100),
age: z.number().min(18).max(120)
});

// Validate input const result = UserSchema.safeParse(req.body); if (!result.success) { return res.status(400).json({ errors: result.error.issues }); }

API Security

  • ✅ HTTPS only - redirect HTTP → HTTPS
  • ✅ CORS configuration chặt chẽ
  • ✅ API versioning
  • ✅ Request size limit

🔧 Tools bảo mật recommended

CategoryToolPurpose
SASTSonarQube, SemgrepStatic code analysis
DASTOWASP ZAP, Burp SuiteDynamic testing
DependencySnyk, npm auditVulnerable packages
SecretsGitLeaks, TruffleHogLeaked credentials

📝 Kết luận

Bảo mật là trách nhiệm của mọi developer, không chỉ security team. Hãy áp dụng các best practices từ đầu dự án để tránh các lỗ hổng tốn kém sau này. "Security by design, not by chance."