Loading...

Bài 63. Bảo mật ứng dụng: input validation, SAST/DAST, sandboxing, code signing, secrets scanning

Khóa học CompTIA Security+ SY0-801 · Phần 4: Vận hành bảo mật · Bài 63 · 🎯 Objective 4.1 · ⏱️ Đọc khoảng 18 phút · 🧪 Không cần lab · 📝 5 câu bài tập cuối bài

🎯 Mục tiêu bài học

  • Hiểu nguyên tắc không tin dữ liệu từ người dùng: xác thực đầu vào (input validation), truy vấn tham số hóa, mã hóa đầu ra và cookie an toàn.
  • Phân biệt SAST (phân tích tĩnh), DAST (phân tích động), SCA/SBOM (thành phần bên thứ ba) và fuzzing.
  • Hiểu sandboxing, code signing và secrets scanning giải quyết vấn đề gì.
  • Hình dung được vị trí từng công cụ trong pipeline DevSecOps và nguyên lý shift left.

📎 Vị trí trong đề thi: bài này là phần phòng thủ của các lỗ hổng ứng dụng bạn đã học: injection, buffer overflow, hardcoded secrets (Bài 24) và lỗ hổng web như SQL injection, XSS, CSRF (Bài 25), và rủi ro chuỗi cung ứng (Bài 20). Code signing dùng lại chữ ký số và PKI (Bài 10, Bài 11). Lab khai thác và vá lỗi web nằm ở Bài 37.

💡 Liên hệ thực tế: lỗi nằm trong chính website của công ty

Công ty chị Lan thuê một nhóm lập trình viết lại website bán hàng. Một tuần sau khi ra mắt, Nam thử nhập một chuỗi lạ vào ô tìm kiếm và thấy trang trả về dữ liệu không nên có. Kiểm tra mã, anh thấy lập trình viên nối thẳng chuỗi người dùng nhập vào câu lệnh SQL. Anh lại tìm thấy trong kho mã một khóa truy cập cơ sở dữ liệu gõ cứng trong file cấu hình. Đây là tình huống minh họa, không phải vụ việc có thật.

Nam nói: "Tường lửa tốt đến đâu cũng không cứu được một ứng dụng tự mở cửa cho kẻ tấn công. Bảo mật phải nằm ngay trong cách viết và kiểm tra ứng dụng, từ sớm, chứ không phải đợi tới lúc đã chạy thật mới vá."

🔧 Hình 63a. Mỗi giai đoạn của pipeline có một loại kiểm tra riêng; phát hiện lỗi càng sớm thì sửa càng rẻ.

📘 Kiến thức cốt lõi

🧼 Xác thực đầu vào (input validation)

Mọi dữ liệu đi vào ứng dụng từ bên ngoài (ô nhập, tham số URL, header, file tải lên, dữ liệu từ API) đều phải coi là không đáng tin cho tới khi được kiểm tra. Input validation kiểm tra dữ liệu có đúng kiểu, độ dài, phạm vi, định dạng mong đợi không.

  • Ưu tiên allow list (chỉ chấp nhận cái hợp lệ đã định nghĩa) thay vì deny list (cố liệt kê mọi thứ xấu, rất dễ bỏ sót).
  • Kiểm tra ở phía máy chủ. Kiểm tra ở trình duyệt chỉ để người dùng tiện lợi; kẻ tấn công có thể gửi yêu cầu trực tiếp mà không qua trình duyệt.
  • Chuẩn hóa (normalize) dữ liệu trước khi kiểm tra để tránh bị đánh lừa bởi các cách mã hóa khác nhau của cùng một chuỗi.
  • Từ chối dữ liệu không hợp lệ và ghi log để phát hiện hành vi dò quét.

🛡️ Các kỹ thuật bổ trợ

Kỹ thuậtChống lạiÝ chính
Truy vấn tham số hóa (prepared statement) SQL injection Câu lệnh SQL viết sẵn với chỗ trống; dữ liệu người dùng truyền vào riêng, nên không bao giờ bị hiểu là lệnh
Mã hóa/escape đầu ra (output encoding) XSS Chuyển ký tự đặc biệt thành dạng an toàn trước khi hiển thị trên trang
Secure cookies Đánh cắp phiên, CSRF Secure (chỉ gửi qua HTTPS), HttpOnly (mã trên trang không đọc được), SameSite (hạn chế gửi chéo trang)
Xử lý lỗi an toàn Lộ thông tin Không hiển thị thông báo lỗi chi tiết (đường dẫn, câu lệnh SQL) cho người dùng cuối; ghi chi tiết vào log
Quyền tối thiểu cho tài khoản ứng dụng Mở rộng thiệt hại Tài khoản ứng dụng kết nối cơ sở dữ liệu chỉ có quyền cần thiết

Quan trọng: xác thực đầu vào không thay thế truy vấn tham số hóa. Hai lớp bảo vệ cùng tồn tại: nếu một lớp bị bỏ sót, lớp kia vẫn đỡ.

🧼 Hình 63b. Dữ liệu không hợp lệ bị từ chối; dữ liệu hợp lệ vẫn đi qua truy vấn tham số hóa nên không bị chạy như lệnh.

🔬 Phân tích tĩnh (SAST) và review mã

SAST (Static Application Security Testing) phân tích mã nguồn (hoặc mã đã biên dịch) khi ứng dụng chưa chạy, tìm mẫu mã nguy hiểm như nối chuỗi vào SQL, dùng hàm không an toàn, mật mã yếu.

  • Ưu điểm: dùng được rất sớm (ngay khi lập trình viên commit), chỉ ra đúng dòng mã cần sửa.
  • Hạn chế: có thể có nhiều cảnh báo sai (false positive), phụ thuộc ngôn ngữ, và không thấy lỗi chỉ xuất hiện khi chạy (cấu hình sai môi trường, lỗi logic nghiệp vụ).
  • Code review (source code review) do con người thực hiện bổ sung cho SAST, đặc biệt với lỗi logic.

🎯 Phân tích động (DAST) và fuzzing

DAST (Dynamic Application Security Testing) kiểm thử ứng dụng đang chạy từ bên ngoài, như một kẻ tấn công: gửi yêu cầu độc hại thử tới trang web hoặc API rồi quan sát phản hồi. Không cần xem mã nguồn (kiểu black-box).

  • Ưu điểm: thấy được lỗi chỉ xuất hiện lúc chạy (cấu hình sai, lỗi xác thực, injection thật sự khai thác được), độc lập với ngôn ngữ lập trình.
  • Hạn chế: chạy muộn hơn, không chỉ ra dòng mã lỗi; có thể bỏ sót đường đi chưa được thăm dò.
  • Fuzzing là một kỹ thuật động: gửi lượng lớn dữ liệu bất thường hoặc ngẫu nhiên vào ứng dụng để tìm trường hợp làm nó treo, lỗi hoặc xử lý sai.

Cách nhớ: SAST = nhìn vào mã khi chưa chạy; DAST = tấn công thử ứng dụng khi đang chạy. Hai công cụ bổ sung nhau, không thay thế nhau.

📦 Thành phần bên thứ ba: SCA và SBOM

Phần lớn ứng dụng hiện đại dùng nhiều thư viện và gói bên thứ ba. SCA (Software Composition Analysis) liệt kê các thành phần đó và đối chiếu với lỗ hổng đã công bố (CVE) để cảnh báo thư viện cần cập nhật. SBOM (Software Bill of Materials) là danh mục các thành phần của một sản phẩm phần mềm, giúp trả lời nhanh câu hỏi "khi một thư viện bị phát hiện lỗi, sản phẩm nào của chúng ta bị ảnh hưởng?". Đây là biện pháp giảm rủi ro chuỗi cung ứng phần mềm (Bài 20). Hãy cũng giám sát gói bị chiếm quyền hoặc giả mạo tên khi tải về từ kho công cộng.

📦 Sandboxing

Sandboxing chạy một ứng dụng hoặc đoạn mã trong môi trường cô lập với quyền và tài nguyên bị giới hạn, để nếu nó độc hại hoặc bị khai thác thì thiệt hại không lan ra hệ thống chính. Ví dụ: trình duyệt chạy mỗi tab trong sandbox, container cô lập ứng dụng, secure email gateway chạy thử tệp đính kèm trong sandbox (Bài 62), phân tích mã độc trong máy ảo cô lập.

Giới hạn: lỗi trong sandbox có thể cho phép thoát ra ngoài (sandbox escape), và một số mã độc nhận biết môi trường sandbox rồi tạm thời không biểu hiện. Sandbox giảm thiệt hại chứ không phải bảo đảm tuyệt đối.

✍️ Code signing

Code signing là việc nhà phát hành ký số mã hoặc bản phát hành bằng khóa riêng. Hệ điều hành, kho ứng dụng hoặc người dùng xác minh bằng chứng chỉ (khóa công khai) tương ứng. Kết quả:

  • Xác thực nguồn gốc: phần mềm đến từ nhà phát hành đã ký.
  • Toàn vẹn: mã chưa bị sửa đổi sau khi ký.

Hạn chế cần nhớ: chữ ký không chứng minh mã an toàn, chỉ chứng minh ai đã ký và chưa bị sửa. Nếu khóa ký bị đánh cắp, kẻ tấn công có thể ký mã độc như thật, nên khóa ký phải được bảo vệ chặt (lưu ở HSM hoặc dịch vụ quản lý khóa, Bài 12), giới hạn người dùng, ghi log, và có kế hoạch thu hồi chứng chỉ khi nghi ngờ lộ.

🔑 Secrets scanning

Secrets là thông tin xác thực nằm trong mã hoặc cấu hình: mật khẩu, khóa API, token, khóa riêng, chuỗi kết nối cơ sở dữ liệu. Gõ cứng secrets vào mã (hardcoded secrets, Bài 24) là lỗi rất phổ biến vì mã thường được chia sẻ rộng và lưu trong lịch sử kho mã.

Secrets scanning là quét tự động mã nguồn, file cấu hình và lịch sử commit để tìm secrets lọt vào, thường chạy ở pre-commit hook (chặn trước khi commit) và trong pipeline.

Nếu một secret đã bị lộ:

  1. Thu hồi và cấp lại (rotate) secret ngay. Chỉ xóa dòng khỏi code là không đủ vì bản cũ vẫn nằm trong lịch sử kho mã, bản sao, hoặc đã có người lấy.
  2. Kiểm tra log xem secret đó đã bị dùng trái phép chưa.
  3. Dọn lịch sử nếu cần và bổ sung biện pháp phòng ngừa.

Cách phòng ngừa đúng là không để secrets trong mã: dùng dịch vụ quản lý secrets (vault) hoặc biến môi trường được cấp động lúc chạy, kèm quyền truy cập tối thiểu và xoay vòng định kỳ.

🔁 DevSecOps và shift left

DevSecOps đưa bảo mật vào toàn bộ vòng đời phát triển và vận hành thay vì để cuối cùng mới kiểm tra. Shift left nghĩa là dịch việc kiểm tra bảo mật về phía trái (sớm) của quy trình: lỗi tìm ở giai đoạn viết mã rẻ hơn rất nhiều so với tìm khi đã lên môi trường sản xuất. Trong pipeline CI/CD, các bước kiểm tra tự động chạy mỗi lần có thay đổi: secrets scanning và SAST ở giai đoạn đầu, SCA khi build, DAST trên môi trường thử nghiệm, rồi ký và triển khai. Hạ tầng cũng được kiểm tra tương tự khi mô tả bằng mã (IaC, Bài 41).

🎯 Mẹo làm bài: "Phân tích mã nguồn khi chưa chạy" → SAST. "Kiểm thử ứng dụng đang chạy từ bên ngoài" → DAST. "Gửi lượng lớn dữ liệu bất thường để tìm lỗi" → fuzzing. "Danh mục thành phần phần mềm" → SBOM; "quét thư viện bên thứ ba tìm lỗ hổng" → SCA. "Chạy trong môi trường cô lập, giới hạn quyền" → sandboxing. "Ký số mã để xác minh nguồn và toàn vẹn" → code signing. "Tìm mật khẩu, khóa API trong mã" → secrets scanning (xử lý: rotate ngay). "Chống SQL injection ở tầng mã" → truy vấn tham số hóa (cộng input validation). "Chống XSS khi hiển thị dữ liệu" → mã hóa/escape đầu ra. "Kiểm tra bảo mật sớm trong quy trình" → shift left / DevSecOps.

🧠 Áp vào câu chuyện của Nam

Phát hiện của NamBiện pháp
Chuỗi người dùng nhập bị nối thẳng vào câu SQL Truy vấn tham số hóa và xác thực đầu vào phía máy chủ
Khóa cơ sở dữ liệu gõ cứng trong file cấu hình Rotate khóa ngay, chuyển sang vault, bật secrets scanning
Muốn phát hiện lỗi từ khi lập trình viên commit SAST và code review trong pipeline
Muốn thử tấn công bản đang chạy trước khi ra mắt DAST trên môi trường thử nghiệm
Lo thư viện bên thứ ba có lỗ hổng SCA và SBOM
Muốn khách hàng chắc bản cập nhật đúng của công ty Code signing, bảo vệ khóa ký

📖 Thuật ngữ cần nhớ

Thuật ngữNghĩa
Input validation Kiểm tra dữ liệu đầu vào có đúng kiểu, độ dài, định dạng mong đợi.
Parameterized query Truy vấn tách dữ liệu khỏi câu lệnh SQL, chống SQL injection.
Output encoding Chuyển ký tự đặc biệt thành dạng an toàn trước khi hiển thị, chống XSS.
SAST Phân tích tĩnh mã nguồn khi chưa chạy.
DAST Kiểm thử ứng dụng đang chạy từ bên ngoài.
Fuzzing Gửi dữ liệu bất thường hoặc ngẫu nhiên số lượng lớn để tìm lỗi.
SCA / SBOM Quét thành phần bên thứ ba / danh mục thành phần phần mềm.
Sandboxing Chạy trong môi trường cô lập, giới hạn quyền.
Code signing Ký số mã để xác minh nguồn gốc và toàn vẹn.
Secrets scanning Quét tìm mật khẩu, khóa, token lọt vào mã.
Shift left Đưa kiểm tra bảo mật về giai đoạn sớm hơn.

📌 Tóm tắt nhanh

  • Coi mọi dữ liệu từ ngoài là không đáng tin: xác thực đầu vào theo allow list ở máy chủ, truy vấn tham số hóa chống SQL injection, mã hóa đầu ra chống XSS, cookie an toàn.
  • SAST nhìn mã khi chưa chạy; DAST tấn công thử khi đang chạy; fuzzing thử dữ liệu bất thường; SCA/SBOM quản lý thành phần bên thứ ba.
  • Sandboxing cô lập để giới hạn thiệt hại; code signing chứng minh nguồn và toàn vẹn nhưng không chứng minh an toàn, và phải bảo vệ khóa ký.
  • Secrets scanning phát hiện secrets lọt vào mã; khi lộ phải rotate, không chỉ xóa dòng.
  • DevSecOps và shift left: kiểm tra tự động ở từng giai đoạn pipeline, từ sớm.

💬 Hỏi & Đáp nhanh

❓ Dùng SAST rồi có cần DAST không? Có. SAST thấy lỗi trong mã nhưng không thấy lỗi chỉ xuất hiện khi ứng dụng chạy trong môi trường thật (cấu hình, tích hợp, xác thực). DAST thấy hành vi thật khi bị tấn công nhưng không chỉ ra dòng mã. Hai công cụ bổ sung nhau.

❓ Chỉ cần kiểm tra đầu vào bằng JavaScript trên trình duyệt có được không? Không. Kẻ tấn công bỏ qua trình duyệt và gửi yêu cầu trực tiếp tới máy chủ. Kiểm tra phía trình duyệt chỉ để tiện cho người dùng; kiểm tra bắt buộc phải ở phía máy chủ.

❓ Phần mềm đã code signing thì chắc chắn an toàn? Không. Chữ ký chứng minh ai ký và mã chưa bị sửa sau khi ký, chứ không chứng minh nội dung lành. Kẻ tấn công cũng có thể ký mã độc nếu lấy được khóa ký hoặc mua được chứng chỉ hợp lệ, nên cần kết hợp các biện pháp khác như kiểm thử, giám sát và bảo vệ khóa ký.

📝 Bài tập đánh giá

Tự chọn đáp án cho từng câu, rồi đối chiếu với phần đáp án ở cuối bài.

Câu 1. Cách bảo vệ tốt nhất ở tầng mã nguồn để chống SQL injection là gì?

  • A. Chỉ kiểm tra dữ liệu bằng JavaScript trên trình duyệt
  • B. Nối trực tiếp chuỗi người dùng nhập vào câu lệnh SQL
  • C. Ẩn thông báo lỗi và không làm gì thêm
  • D. Dùng truy vấn tham số hóa và kiểm tra đầu vào ở phía máy chủ

Câu 2. Công cụ nào phân tích mã nguồn khi ứng dụng chưa chạy và thường được dùng rất sớm trong pipeline?

  • A. SAST
  • B. DAST
  • C. Fuzzing đối với ứng dụng đang chạy
  • D. Penetration test từ Internet

Câu 3. Một công cụ gửi các yêu cầu tấn công thử tới ứng dụng web đang chạy trong môi trường thử nghiệm để tìm lỗ hổng, không cần xem mã nguồn. Đây là loại kiểm thử nào?

  • A. SAST
  • B. SBOM
  • C. DAST
  • D. Code review thủ công

Câu 4. Mục đích chính của code signing là gì?

  • A. Mã hóa toàn bộ mã nguồn để không ai đọc được
  • B. Cho phép xác minh nhà phát hành và mã chưa bị sửa đổi sau khi ký
  • C. Chứng minh phần mềm hoàn toàn không có lỗ hổng
  • D. Tăng tốc độ chạy của ứng dụng

Câu 5. Lập trình viên lỡ commit khóa API của dịch vụ đám mây lên kho mã. Việc cần ưu tiên làm đầu tiên là gì?

  • A. Thu hồi và cấp lại khóa (rotate), kiểm tra log sử dụng, rồi bổ sung secrets scanning
  • B. Chỉ xóa dòng chứa khóa trong commit mới nhất
  • C. Đổi tên file chứa khóa
  • D. Không làm gì vì kho mã là riêng tư

👉 Đáp án

Câu 1: D — Truy vấn tham số hóa tách dữ liệu khỏi câu lệnh SQL, kết hợp xác thực đầu vào ở máy chủ. Kiểm tra ở trình duyệt có thể bị bỏ qua, nối chuỗi trực tiếp chính là nguyên nhân gây lỗi.

Câu 2: A — SAST phân tích mã nguồn khi chưa chạy; DAST và fuzzing cần ứng dụng đang chạy.

Câu 3: C — DAST kiểm thử ứng dụng đang chạy từ bên ngoài như kẻ tấn công, không cần mã nguồn.

Câu 4: B — Code signing cho phép xác minh nhà phát hành và tính toàn vẹn của mã; nó không chứng minh phần mềm an toàn.

Câu 5: A — Khóa đã lộ phải được thu hồi và cấp lại ngay; chỉ xóa dòng là không đủ vì lịch sử kho mã vẫn còn và khóa có thể đã bị lấy.


📚 Bài viết thuộc khóa học CompTIA Security+ của VNExperts

🧭 Điều hướng

⬅️ Bài trước🏠 Mục lục khóa họcBài kế tiếp ➡️
Bài 62: Bảo mật email: SPF, DKIM, DMARC, BIMI Mục lục khóa học CompTIA Security+ Bài 64: Kỹ thuật đánh lừa kẻ tấn công: honeypot, honeytoken, canary