DevSecOps Phần 2 - Security Fundamentals: CIA Triad Và Các Khái Niệm Cốt Lõi
Chào các bạn, mình quay lại đây! Ở [Phần 1] chúng ta đã hiểu DevSecOps là gì và vì sao Shift-Left lại quan trọng. Nhưng trước khi cầm "vũ khí" (SAST, DAST, Trivy...), có một chuyện mình học được: người làm bảo mật giỏi không phải người biết nhiều tool, mà là người hiểu rõ mình đang bảo vệ cái gì và chống lại điều gì.
Phần 2 này toàn khái niệm nền. Nghe có vẻ lý thuyết, nhưng mình hứa sẽ cố cho thật cụ thể - mỗi khái niệm đều đi kèm một ví dụ hoặc một đoạn code ngắn để bạn đọc là hình dung ra ngay, chứ không nói chay. Nắm chắc mấy cái ở đây thì mọi phần sau sẽ nhẹ nhàng hơn nhiều. 🔐

I. CIA Triad - Ba Mục Tiêu Của Mọi Biện Pháp Bảo Mật
Trong an toàn thông tin, gần như mọi thứ đều xoay quanh 3 mục tiêu, viết tắt là CIA (không liên quan gì tới cơ quan tình báo Mỹ nhé):
tải xuống (2).png
Ba mục tiêu này trừu tượng, nên mình gắn nó vào một thứ ai cũng có: tài khoản ngân hàng của bạn.
| Trụ cột | Nghĩa là gì | Với tài khoản ngân hàng | Nếu bị phá |
|---|---|---|---|
| Confidentiality | Chỉ người được phép mới xem được | Chỉ mình bạn thấy số dư của mình | Người lạ xem được số dư, thông tin cá nhân → lộ dữ liệu |
| Integrity | Dữ liệu không bị sửa lén | Số dư 10 triệu không tự thành 1 triệu | Hacker sửa số dư, tạo giao dịch giả → mất tiền |
| Availability | Lúc cần là dùng được | Mở app lên là chuyển khoản được | Bị tấn công làm sập app → không rút được tiền |
Mẹo mình hay dùng: khi gặp bất kỳ lỗ hổng nào, tự hỏi "nó phá vỡ chữ nào trong C-I-A?". Ví dụ:
- Mã hóa dữ liệu (khi lưu và khi truyền) → bảo vệ chữ C.
- Hàm băm (hash) và chữ ký số → bảo vệ chữ I (phát hiện dữ liệu bị sửa).
- Backup, cân bằng tải, chống DDoS → bảo vệ chữ A.
Cứ quy được lỗ hổng về C, I hay A là bạn hiểu ngay nó nguy hiểm ở chỗ nào.
II. Authentication vs Authorization - Rất Hay Bị Nhầm
Hai từ này nghe na ná nhau nhưng khác hẳn, và đây là câu hỏi phỏng vấn kinh điển:
- Authentication (AuthN) - "Bạn là ai?" → xác minh danh tính. Xảy ra trước. Ví dụ: nhập mật khẩu, quét vân tay, nhập mã OTP.
- Authorization (AuthZ) - "Bạn được làm gì?" → xác định quyền hạn. Xảy ra sau khi đã biết bạn là ai. Ví dụ: user thường không vào được trang
/admin.
Ví dụ đời thường: vào khách sạn, bạn đưa CMND ở lễ tân để chứng minh mình là khách đã đặt phòng - đó là Authentication. Cái thẻ từ họ đưa chỉ mở được phòng của bạn và hồ bơi, không mở được phòng người khác - đó là Authorization.
Với anh em code web thì ví dụ rõ nhất nằm ở mã trạng thái HTTP. Bạn gọi một API và nhận về:

Nhìn sơ đồ trên là rõ: request phải qua hai cánh cổng nối tiếp nhau. Cổng 1 (AuthN) hỏi "bạn là ai" - trượt ở đây thì nhận về 401. Qua được rồi mới tới cổng 2 (AuthZ) hỏi "bạn được làm gì" - đã biết bạn là ai nhưng thiếu quyền thì nhận 403.
Cái tên hơi ngược đời: mã 401 ghi chữ "Unauthorized" nhưng thực chất nói về authentication. Nhớ mẹo: 401 = chưa đăng nhập, 403 = đã đăng nhập nhưng không đủ quyền.
Nhầm lẫn giữa hai khái niệm này đẻ ra một lỗ hổng cực phổ biến tên là Broken Access Control - đang đứng hạng 1 trong danh sách OWASP Top 10. Cho bạn thấy nó cụ thể ra sao bằng một đoạn code hay gặp: một API trả về hóa đơn theo id.
// ❌ Có AuthN nhưng THIẾU AuthZ
app.get("/api/invoices/:id", requireLogin, (req, res) => {
const invoice = db.getInvoice(req.params.id); // lấy theo id trên URL
res.json(invoice); // trả về luôn, không kiểm chủ sở hữu
});
// User A đăng nhập rồi đổi URL /api/invoices/1001 → /api/invoices/1002
// → xem được hóa đơn của người khác! (lỗi này tên là IDOR)
// ✅ Kiểm tra quyền sở hữu trước khi trả
app.get("/api/invoices/:id", requireLogin, (req, res) => {
const invoice = db.getInvoice(req.params.id);
if (invoice.ownerId !== req.user.id) return res.sendStatus(403); // Forbidden
res.json(invoice);
});
Nhìn kỹ: hệ thống đã biết user là ai (requireLogin lo phần AuthN rồi), nhưng lại quên hỏi "user này có được xem hóa đơn đó không" (thiếu AuthZ). Chỉ đổi một con số trên URL là lộ dữ liệu người khác. Chúng ta sẽ tự tay khai thác đúng kiểu lỗi này trên Juice Shop ở các phần sau.
III. Threat, Vulnerability, Risk, Exploit - Phân Biệt Qua Một Ca Thật
Bốn từ này bị dùng lẫn lộn suốt. Thay vì định nghĩa suông, mình lấy đúng một tình huống SQL Injection rồi chỉ ra từng cái nằm ở đâu.
Bối cảnh: một trang đăng nhập lấy username/password rồi ghép thẳng vào câu lệnh SQL mà không kiểm tra gì:
-- Code phía server (viết ẩu, dính lỗi)
SELECT * FROM users
WHERE username = '<ô nhập>' AND password = '<ô nhập>';
Giờ soi bốn khái niệm:

Sơ đồ trên gói gọn cả bốn: lỗ hổng (cửa sổ không khóa) và mối đe dọa (tên trộm) là hai điều kiện có sẵn; khi tên trộm dùng đúng kỹ thuật trèo qua đúng cái cửa sổ đó thì thành exploit; còn rủi ro là kết quả cuối cùng - cao hay thấp tùy vào khả năng bị đánh và mất mát nếu bị đánh thật.
Công thức mình luôn ghi nhớ:
RISK = THREAT × VULNERABILITY × IMPACT
Muốn giảm rủi ro, bạn tác động vào một trong ba yếu tố: vá lỗ hổng (kiểm tra input), giảm cơ hội cho threat (giới hạn IP, thêm rate limit), hoặc giảm thiệt hại (mã hóa dữ liệu để dù bị lấy cũng khó đọc). Đây chính là tư duy nền của cả nghề bảo mật.
Một điểm hay bị bỏ qua: cùng một lỗ hổng nhưng rủi ro có thể rất khác nhau, tùy nó nằm ở đâu. Ví dụ cùng là lỗi SQL Injection:
- Nằm trên trang login của hệ thống ngân hàng (database chứa thông tin thẻ) → thiệt hại khổng lồ → rủi ro rất cao, phải vá ngay.
- Nằm trên một trang blog nội bộ chỉ chạy trong mạng LAN, không ai ngoài truy cập được → threat thấp, thiệt hại nhỏ → rủi ro thấp hơn nhiều.
Đây là lý do khi có một đống lỗ hổng cần sửa mà thời gian có hạn, ta không sửa lung tung mà ưu tiên theo rủi ro: cái nào vừa dễ bị khai thác vừa gây hại lớn thì xử trước. Ở Module 2 mình sẽ giới thiệu điểm số CVSS/EPSS - cách "chấm điểm" rủi ro cho từng lỗ hổng đúng theo tư duy này.
IV. Attack Surface - Bề Mặt Tấn Công
Attack Surface là tổng hợp tất cả những điểm mà kẻ tấn công có thể "chọc" vào hệ thống của bạn. Càng nhiều cửa thì càng khó canh.
BỀ MẶT TẤN CÔNG CỦA MỘT WEB APP
Trang login ┐
API cho mobile │
Ô upload file │
Cổng database mở ├──▶ [ HỆ THỐNG CỦA BẠN ]
Thư viện bên thứ 3 │
Cấu hình cloud sai │
Tài khoản admin cũ ┘
Mỗi cửa = một điểm hacker có thể thử.
Nguyên tắc gọn: cái gì không dùng thì tắt/gỡ đi. Đóng cổng thừa, gỡ tính năng không cần, xóa tài khoản cũ, ẩn thông tin phiên bản server. Ít cửa hơn thì ít chỗ để bị đánh hơn.
Làm sao biết máy mình đang "hở" những cửa nào? Dân bảo mật hay dùng nmap - một công cụ quét cổng - để tự soi bề mặt tấn công của chính hệ thống mình. Chỉ một lệnh nhỏ:
nmap -sV localhost # -sV: dò luôn tên và phiên bản dịch vụ ở mỗi cổng
Kết quả trả về đại loại thế này, mỗi dòng open là một cửa đang mở:
PORT STATE SERVICE VERSION
3000/tcp open http Node.js Express framework
5432/tcp open postgresql PostgreSQL 14 ← database phơi ra ngoài (!)
Nhìn ví dụ trên: cổng 3000 (web) mở là hợp lý, nhưng cổng 5432 của PostgreSQL mà mở ra ngoài thì rất nguy - database đáng lẽ chỉ nên cho server nội bộ gọi, giờ ai cũng chọc tới được. Đó chính là một "cửa thừa" cần đóng ngay. nmap giúp bạn phát hiện đúng những trường hợp như vậy trước khi hacker phát hiện.
Một lời nhắc quan trọng: chỉ quét localhost hoặc hệ thống của chính bạn. Quét cổng IP hay website của người khác khi chưa được phép là vi phạm pháp luật, dù bạn chỉ tò mò.
V. Defense in Depth - Phòng Thủ Nhiều Lớp
Một bài học mình tâm đắc: đừng bao giờ đặt cược vào một lớp bảo vệ duy nhất. Triết lý Defense in Depth nói rằng hãy xếp nhiều lớp, để một lớp thủng thì lớp sau vẫn đỡ.

Giống nhà bạn có hàng rào, rồi cửa khóa, rồi chó giữ nhà, rồi két sắt, rồi camera. Trộm qua được hàng rào vẫn còn bốn lớp nữa phải lo. Trong phần mềm cũng vậy: hacker vượt được firewall thì vẫn vướng phải xác thực; qua được xác thực thì dữ liệu vẫn đang mã hóa; và mọi động tĩnh đều bị log lại để cảnh báo.
VI. Least Privilege & Zero Trust
Hai nguyên tắc hiện đại này bạn sẽ gặp đi gặp lại suốt series.
Least Privilege (đặc quyền tối thiểu): mỗi người hoặc mỗi tiến trình chỉ được cấp đúng quyền cần để làm việc, không hơn.
- Sai: cho mọi nhân viên quyền admin database "cho tiện".
- Đúng: nhân viên kế toán chỉ đọc được bảng hóa đơn, không sửa được bảng lương.
Ví dụ gần gũi nhất với dân code là quyền file trên Linux. Giả sử bạn có một file chứa mật khẩu database. Xem quyền hiện tại của nó bằng ls -l:
$ ls -l secret.env
-rw-r--r-- 1 you staff 30 secret.env
│ │ └── others (người ngoài): r-- = ĐỌC ĐƯỢC file mật khẩu (!)
│ └───── group (nhóm): r-- = đọc được
└──────── owner (chủ): rw- = đọc + ghi
Thấy vấn đề chưa? Ba ký tự cuối r-- nghĩa là bất kỳ ai trên máy cũng đọc được file mật khẩu - thừa quyền, vi phạm Least Privilege. Siết lại cho chỉ mình chủ đọc/ghi:
$ chmod 600 secret.env # 6 = đọc(4)+ghi(2) cho chủ; 0 0 = nhóm & người ngoài không có gì
$ ls -l secret.env
-rw------- 1 you staff 30 secret.env # group + others: trắng trơn ✅
Mẹo đọc số quyền cho nhanh: mỗi chữ số là tổng của đọc = 4, ghi = 2, chạy = 1, và ba chữ số lần lượt cho chủ / nhóm / người ngoài. Vậy 600 = chỉ chủ đọc-ghi; 644 = chủ đọc-ghi, còn lại chỉ đọc (hợp cho file thường); 700 = chỉ chủ chạy được script. Cấp đúng mức tối thiểu như vậy chính là Least Privilege ở cấp file - một thói quen nhỏ nhưng chặn được vô số rò rỉ.
Zero Trust (không tin mặc định): phương châm là "never trust, always verify" - đừng tin một ai/thiết bị nào chỉ vì họ đã ở "bên trong" mạng. Mọi truy cập đều phải xác minh lại.
MÔ HÌNH CŨ (Castle-and-Moat) ZERO TRUST
──────────────────────────── ──────────────────────────
Vào được trong tường thành Mỗi cửa đều kiểm tra lại
= mặc nhiên được tin danh tính + quyền + thiết bị
1 lỗ thủng = toàn bộ sụp đổ 1 lỗ thủng = thiệt hại bị giới hạn
Mô hình cũ giống như: qua được cổng làng là đi đâu trong làng cũng được. Còn Zero Trust thì mỗi nhà vẫn khóa cửa riêng, ai vào cũng phải trình giấy - nghe hơi phiền nhưng an toàn hơn hẳn.
Tổng Kết
Phần 2 trang bị cho bạn bộ "từ vựng tư duy" của dân bảo mật:
- CIA Triad - ba mục tiêu Confidentiality, Integrity, Availability. Gặp lỗ hổng thì quy về C/I/A để hiểu nó nguy ở đâu.
- AuthN vs AuthZ - "bạn là ai" và "bạn được làm gì"; nhớ 401 vs 403.
- Threat / Vulnerability / Risk / Exploit - phân biệt qua ca SQL Injection, và công thức Risk = Threat × Vulnerability × Impact.
- Attack Surface (soi bằng nmap), Defense in Depth, Least Privilege (siết quyền file bằng chmod), Zero Trust - mỗi cái kèm một ví dụ cụ thể để nhớ lâu.
Công cụ rồi sẽ đổi theo thời gian, nhưng những nguyên tắc nền này thì luôn đúng. Hiểu chúng, bạn sẽ biết vì sao mỗi kỹ thuật tồn tại chứ không chỉ làm theo cho có.
Bài Tiếp Theo
Phần 3 - Shift-Left & Vòng Đời Phát Triển An Toàn (Secure SDLC): mình sẽ ghép mấy khái niệm hôm nay vào vòng đời phát triển phần mềm, xem bảo mật nên "chen" vào từng giai đoạn (thiết kế, code, test, deploy) ra sao, và đâu là những chốt kiểm tra tự động nên đặt ở mỗi bước. Có sơ đồ pipeline chi tiết đang chờ bạn.
Hẹn gặp lại ở phần sau! 🚀
All Rights Reserved