SecOps Portal
Trang chủ › Nghiên Cứu Bảo Mật

Lập trình an toàn và các nguyên tắc bảo mật phần mềm

Ban biên tập SecOps Portal · · Cập nhật
Lập trình an toàn và các nguyên tắc bảo mật phần mềm

Lập trình an toàn là viết phần mềm sao cho nó vẫn hành xử đúng khi bị sử dụng sai một cách cố ý. Nền tảng của nó là một nhóm nguyên tắc ổn định qua nhiều thập kỷ: không tin dữ liệu đầu vào, cấp quyền tối thiểu, phòng thủ nhiều lớp, mặc định an toàn, thất bại một cách an toàn, giữ thiết kế đơn giản và không tự chế mật mã. Nắm vững các nguyên tắc này giúp lập trình viên tránh được cả những lỗ hổng chưa có tên.

Vì sao cần tư duy bảo mật khi viết mã

Lập trình viên quen nghĩ theo "đường đi đúng": người dùng nhập tên, hệ thống lưu tên. Kẻ tấn công nghĩ ngược lại: điều gì xảy ra nếu tên dài một triệu ký tự, chứa dấu nháy, chứa thẻ script, hoặc gửi khi chưa đăng nhập? Lập trình an toàn là thêm góc nhìn thứ hai vào từng quyết định thiết kế và từng dòng mã.

Sửa lỗ hổng sau khi phát hành tốn kém hơn nhiều so với tránh nó từ đầu: phải điều tra, vá khẩn cấp, thông báo người dùng, và có thể chịu thiệt hại uy tín. Mỗi lỗi bảo mật được ngăn ở giai đoạn viết mã là một sự cố không bao giờ xảy ra.

Nguyên tắc 1: Không tin bất kỳ đầu vào nào

Mọi dữ liệu từ bên ngoài ranh giới tin cậy đều có thể bị điều khiển: tham số URL, body yêu cầu, header, cookie, tệp tải lên, dữ liệu từ API bên thứ ba, thậm chí giá trị trong cơ sở dữ liệu nếu nó từng do người dùng nhập.

  • Kiểm tra theo danh sách cho phép (allowlist): định dạng, kiểu, độ dài, phạm vi giá trị hợp lệ.
  • Kiểm tra ở phía máy chủ; kiểm tra phía client chỉ để cải thiện trải nghiệm.
  • Mã hóa đầu ra theo ngữ cảnh: HTML, thuộc tính, JavaScript, URL mỗi nơi có cách mã hóa riêng.
  • Tách dữ liệu khỏi lệnh: dùng truy vấn tham số hóa thay vì nối chuỗi.

Hai lỗi kinh điển minh họa nguyên tắc này là SQL Injection và XSS, được phân tích trong bài lỗ hổng SQL Injection và bài ngăn chặn XSS.

Nguyên tắc 2: Quyền tối thiểu

Mỗi thành phần chỉ nên có đúng những quyền cần thiết để làm việc của nó:

  • Tài khoản cơ sở dữ liệu của ứng dụng không cần quyền xóa bảng hay tạo người dùng.
  • Tiến trình web không chạy bằng root.
  • Khóa API chỉ truy cập đúng dịch vụ cần dùng.
  • Người dùng chỉ thấy dữ liệu của mình trừ khi có lý do rõ ràng.

Khi một thành phần bị chiếm, quyền tối thiểu giới hạn những gì kẻ tấn công làm được tiếp theo.

Nguyên tắc 3: Phòng thủ nhiều lớp

Không dựa vào một biện pháp duy nhất. Ví dụ với XSS: kiểm tra đầu vào, mã hóa đầu ra, Content Security Policy, cookie HttpOnly. Nếu một lớp có sơ hở, lớp khác vẫn giảm thiệt hại.

Nguyên tắc 4: Mặc định an toàn

  • Tính năng mới mặc định yêu cầu đăng nhập và phân quyền, mở công khai phải là quyết định có chủ đích.
  • Cấu hình mặc định tắt debug, tắt liệt kê thư mục, bật HTTPS.
  • Tài khoản mới không có quyền quản trị.
  • Framework và thư viện nên được cấu hình với chế độ an toàn nhất mà ứng dụng vẫn chạy được.

Nguyên tắc 5: Thất bại an toàn và xử lý lỗi cẩn thận

Khi có lỗi, hệ thống nên từ chối thay vì cho phép. Nếu dịch vụ kiểm tra quyền không phản hồi, câu trả lời phải là "không được truy cập", không phải "bỏ qua kiểm tra". Thông báo lỗi trả cho người dùng nên chung chung; chi tiết như stack trace, truy vấn SQL chỉ ghi vào log nội bộ.

Nguyên tắc 6: Đơn giản và giảm bề mặt tấn công

Mã phức tạp khó rà soát và dễ chứa lỗi. Mỗi endpoint, tham số, tính năng, thư viện thêm vào là thêm chỗ có thể bị tấn công. Gỡ bỏ mã chết, endpoint không dùng, thư viện thừa. Mỗi thư viện phụ thuộc cũng là rủi ro cần quản lý, xem bài quản lý thư viện mã nguồn mở.

Nguyên tắc 7: Không tự chế mật mã

Thuật toán mật mã và giao thức an toàn rất khó thiết kế đúng. Dùng thư viện đã được kiểm chứng rộng rãi, với tham số mặc định do chuyên gia khuyến nghị:

Nhu cầuNên dùngTránh
Lưu mật khẩuHàm băm chậm có muối: bcrypt, scrypt, Argon2MD5, SHA-1, SHA-256 trần
Mã hóa dữ liệuThuật toán mã hóa có xác thực như AES-GCM qua thư viện chuẩnTự viết thuật toán, chế độ ECB
Số ngẫu nhiên cho tokenBộ sinh số ngẫu nhiên an toàn mật mã của nền tảngHàm random thông thường
Truyền dữ liệuTLS phiên bản hiện hànhGiao thức tự chế, tắt kiểm tra chứng chỉ

Nguyên tắc 8: Bí mật không nằm trong mã

Mật khẩu, khóa API, khóa ký không được viết cứng trong mã nguồn hay commit vào Git. Đọc chúng từ biến môi trường hoặc dịch vụ quản lý bí mật. Hướng dẫn chi tiết trong bài bảo mật tệp cấu hình nhạy cảm.

Áp dụng vào quy trình làm việc

  • Thiết kế: mô hình hóa mối đe dọa đơn giản cho tính năng mới: ai có thể lạm dụng, bằng cách nào, hậu quả gì.
  • Viết mã: dùng thư viện và framework có cơ chế an toàn sẵn; bật cảnh báo bảo mật trong trình soạn thảo.
  • Rà soát mã: thêm mục bảo mật vào checklist review.
  • Kiểm thử: viết test cho trường hợp lạm dụng, như người dùng A truy cập dữ liệu người dùng B.
  • Tự động hóa: quét mã tĩnh, quét thư viện, quét bí mật trong CI.
  • Học từ lỗi: mỗi lỗ hổng tìm được là dịp cập nhật checklist và chia sẻ cho cả nhóm.

Tài liệu tham khảo nên biết

Dự án OWASP cung cấp nhiều tài liệu miễn phí hữu ích cho lập trình viên: danh sách Top 10 rủi ro ứng dụng web, bộ Cheat Sheet hướng dẫn xử lý từng chủ đề cụ thể, và tiêu chuẩn kiểm tra bảo mật ứng dụng (ASVS) có thể dùng làm checklist. Các nguồn này được cộng đồng cập nhật thường xuyên và là điểm khởi đầu tốt cho nhóm chưa có chuyên gia bảo mật riêng.

Câu hỏi thường gặp

Framework hiện đại đã tự bảo vệ, lập trình viên còn cần lo bảo mật?

Framework giải quyết nhiều lỗi kỹ thuật như XSS cơ bản hay CSRF nếu dùng đúng cách. Nhưng phân quyền, logic nghiệp vụ và cấu hình vẫn phụ thuộc vào lập trình viên, và đây là nơi nhiều lỗ hổng nghiêm trọng xuất hiện.

Kiểm tra đầu vào hay mã hóa đầu ra quan trọng hơn?

Cả hai đều cần. Kiểm tra đầu vào loại bỏ dữ liệu không hợp lệ sớm, còn mã hóa đầu ra bảo đảm dữ liệu được hiểu đúng là dữ liệu trong từng ngữ cảnh hiển thị. Chống XSS chủ yếu dựa vào mã hóa đầu ra.

Nhóm nhỏ nên bắt đầu lập trình an toàn từ đâu?

Bắt đầu với ba việc: dùng truy vấn tham số hóa ở mọi nơi, kiểm tra phân quyền trên từng đối tượng dữ liệu và chạy công cụ quét thư viện, quét bí mật miễn phí trong CI.

Có cần học tấn công để lập trình an toàn không?

Hiểu cách tấn công hoạt động giúp bạn viết mã phòng thủ tốt hơn. Bạn không cần trở thành chuyên gia kiểm thử xâm nhập, nhưng nên thực hành trên ứng dụng cố ý có lỗi để thấy hậu quả thực tế.

Bài liên quan