OWASP Top 10 (2021)
| # | Lỗ hổng | Mô tả ngắn | Đã học? |
|---|---|---|---|
| A01 | Broken Access Control | User A xem được dữ liệu user B | ⚠️ Chưa |
| A02 | Cryptographic Failures | Mã hoá yếu hoặc thiếu | ✅ bcrypt (g2 l10) |
| A03 | Injection | SQL/NoSQL injection | ⚠️ Chưa demo |
| A04 | Insecure Design | Thiết kế không tính tới security | ✅ Phần nào (g3) |
| A05 | Security Misconfiguration | Config sai: default password, debug mode | ✅ Helmet (g2 l11) |
| A06 | Vulnerable Components | Dùng thư viện có lỗ hổng đã biết | ⚠️ Chưa |
| A07 | Auth Failures | Brute force, weak password | ✅ JWT + rate limit |
| A08 | Software Integrity Failures | CI/CD bị tấn công, dependency bị hack | ⚠️ Chưa |
| A09 | Logging & Monitoring Failures | Không phát hiện được tấn công | ✅ Logging (g3 l14) |
| A10 | SSRF | Server bị lừa gọi URL nội bộ | ⚠️ Chưa |
SQL Injection: tấn công và phòng chống
// File: sqli.js
// ❌ SQL Injection: GHÉP CHUỖI = MỞ CỬA CHO HACKER
const query = `SELECT * FROM users WHERE email = '${email}'`
// Hacker nhập email: ' OR 1=1 --
// Query thành: SELECT * FROM users WHERE email = '' OR 1=1 --'
// → Trả về TẤT CẢ users trong database!
// Tệ hơn: '; DROP TABLE users; --
// → XOÁ TOÀN BỘ BẢNG USERS
// File: safe.js
// ✅ Parameterized query: database tự escape input
const query = "SELECT * FROM users WHERE email = $1"
const result = await db.query(query, [email])
// ✅ ORM (Knex): tự parameterize
const users = await knex("users").where({ email })
// ✅ Zod validate input trước khi dùng
const EmailSchema = z.string().email()
const safeEmail = EmailSchema.parse(email) // throw nếu không phải email
XSS (Cross-Site Scripting)
Hacker nhập <script>alert(“hacked”)</script> vào form. Nếu app hiển thị input này mà không escape, script sẽ chạy trên trình duyệt của MỌI USER nhìn thấy nội dung đó.
// File: xss.js
// ❌ SAI: render HTML trực tiếp từ user input
element.innerHTML = userComment // nếu userComment có <script> → chạy!
// ✅ ĐÚNG: dùng textContent (tự escape HTML)
element.textContent = userComment
// ✅ React: tự escape mặc định
// <p>{userComment}</p> → an toàn, React tự escape
// ⚠️ NGUY HIỂM: dangerouslySetInnerHTML
// <div dangerouslySetInnerHTML={{ __html: userComment }} />
// → CHỈ dùng khi bạn TIN TƯỞNG 100% nội dung (ví dụ: từ CMS admin)
Broken Access Control: ai xem được gì?
// File: access.js
// ❌ SAI: không kiểm tra ownership
app.get("/api/orders/:id", async (req, res) => {
const order = await db.orders.findById(req.params.id)
res.json(order) // User A có thể xem order của User B!
})
// ✅ ĐÚNG: kiểm tra user_id trước khi trả data
app.get("/api/orders/:id", authMiddleware, async (req, res) => {
const order = await db.orders.findById(req.params.id)
// Kiểm tra: order này có phải của user đang đăng nhập?
if (order.userId !== req.user.id) {
return res.status(403).json({ error: "Không có quyền" })
}
res.json(order)
})
SSRF: Server bị lừa gọi URL nội bộ
// File: ssrf.js
// ❌ SAI: server fetch URL do user cung cấp mà không kiểm tra
app.post("/api/preview", async (req, res) => {
const { url } = req.body
const html = await fetch(url).then(r => r.text()) // NGUY HIỂM!
// Hacker gửi url = "http://169.254.169.254/metadata"
// → Server fetch metadata AWS → lộ credentials
})
// ✅ ĐÚNG: validate URL, block IP nội bộ
import { URL } from 'url'
function isInternalIp(hostname) {
const blocked = ["localhost", "127.0.0.1", "0.0.0.0", "169.254.169.254"]
if (blocked.includes(hostname)) return true
if (hostname.startsWith("10.")) return true
if (hostname.startsWith("192.168.")) return true
if (hostname.startsWith("172.")) return true
return false
}
app.post("/api/preview", async (req, res) => {
const parsed = new URL(req.body.url)
if (isInternalIp(parsed.hostname)) {
return res.status(400).json({ error: "URL nội bộ không được phép" })
}
// ... tiếp tục fetch an toàn
})
⚠ npm audit: quét lỗ hổng thư viện
Chạy npm audit thường xuyên để phát hiện thư viện có lỗ hổng đã biết (CVE). Dùng npm audit fix để tự động cập nhật. Thiết lập Dependabot trên GitHub để nhận alert tự động.
❓ Cách phòng SQL injection hiệu quả nhất?
- Nói được ít nhất 5 trong OWASP Top 10
- Demo SQL injection và viết code phòng chống
- Phân biệt XSS stored và reflected
- Kiểm tra access control (ownership check)
- Validate URL để chống SSRF
- Chạy npm audit và hiểu kết quả