Top 10 việc cân làm để bảo mật API của bạn
Trong bài viết này sẽ giới thiệu đến ban top 10 việc cần làm để bảo mật API của bạn. Thì những cách bảo mật này là được đề OWASP đưa ra những lời khuyên để bảo mật API Backend của hệ thống.
Sau đây là danh sách các công việc cần làm để bảo mật API:
Trên đây là những task list cần thực hiện.
Broken Object Level Authorization
Nguyên Nhân
Trong REST API có một nguyên tắc mà hầu như ai cũng biết, đó là dùng id để tương tác giữa client và server. Chính vì vấn đề này mà các kẻ tấn công có thể dựa vào đó mà khai thác. Nguy hiểm hơn nữa là nếu như bạn để ID là số tăng dần thì hiểm họa bị đánh cắp hoặc bị kẻ tấn công đoán được ID và có thể cào dữ liệu. Những thông tin này thì rất dễ bị khai thác bởi ké tấn công. Để rõ hơn vấn đề này mình sẽ ví dụ cụ thể bên dưới nhé.
Ví dụ về User thì ID thường là tăng dần, thì khi request đến server để lấy thông tin user theo Id thì thường sẽ là GET
api/users/5
Thấy đó, con số 5 này là gì? Nó là ID của user, vậy con số 6, 10, 50, 100 thì cũng sẽ đoán ra được. Như vậy giả sử mình viết 1 đoạn loop từ 1 đến 9999 và mình call API get user theo ID hoặc thậm chí là delete user theo ID. Thì bạn thấy đó nó sẽ dễ dàng bị tấn công rất nhiều lần.
Tất cả các API đề truy cập ID của object để thao tác chúng, và làm bất cứ action gì trên đối tượng đó. Trước khi thao tác đối tượng thì bạn nên kiểm tra quyền trước khi cho phép user đang đăng nhập có được phép access đối tượng đó hay không? (Object Level Authorization)
Giải pháp
Tích hợp phần phân cấp role theo cơ chế và cấp độ cho hợp lý.
Luôn luôn kiểm tra quyền user đang đăng nhập với các action đến server. Quan trọng là khi có 1 request nào thao tác đến DB thì cần kiểm tra kỹ lưỡng.
Thay đổi dùng objectID là hash code hay dùng GUID để lưu trữ vào DB.
Broken Authentication
Nguyên Nhân
Nôm na là kẻ tấn côn sẽ tấn cao vào những API mà bạn không bảo mật như login, register, forgot password, reset password,...
Một số hành vi sau có thể sẽ ảnh hưởng đến:
Cho phép người dùng thay đổi mật khẩu dễ dàng, mà không hỏi mật khẩu cũ.
Cho phép người dùng thay đổi những thông tin nhạy cảm của họ mà không hỏi mật hiện tại.
Người dùng đặt mật khẩu kém, khiến kẻ tấn công có thể rà soát ra.
Không kiểm tra tính xác thực của token gửi đến server.
Không kiểm tra thông tin hết hạn của token.
Sử dụng key mã hóa quá dễ đoán, không phức tạp.
Trong thiết kế microservice, một vấn đề quan trọng là: Các service giao tiếp với nhau mà không cần xác thực.
Giả sử vài trường hợp tấn công:
Tấn công username, password:
Để gửi yêu cầu xác thực, thì bên phía FE sẽ gửi theo yêu cầu như sau:
POST /graphql { "query":"mutation { login (username:"",password:"") { token } }" }
Gửi như vậy thì sẽ có vấn đề lộ thông tin ở username, thì hacker có thể lấy username này để loop qua để đánh phần login và dò mật khẩu. Điều tệ hơn là nếu password của bạn để nguyên thủy khi gửi lên Server mà không mã hóa, thì nó là 1 vấn đề rất nghiệm trọng. Bên phía FE nên mã hóa trước khi gửi dữ liệu lên Server.
Giả sử biết được user là victim thì sẽ tấn công như sau:
POST /graphql [ {"query":"mutation{login(username:"victim",password:"password"){token}}"}, {"query":"mutation{login(username:"victim",password:"123456"){token}}"}, {"query":"mutation{login(username:"victim",password:"qwerty"){token}}"}, ... {"query":"mutation{login(username:"victim",password:"123"){token}}"}, ]
Lộ token
Giả sử bạn bị đánh cắp token, thì trong token có API change password, nếu như API này không hỏi current password, thì tài khoản này đã bị đánh cắp như chơi. Giả sử như vầy:
PUT /api/users/change-password Authorization: Bearer
{ "new_password": "new_password" }
Đó, bạn thấy vấn đề đúng không, điều tốt nhất là thêm biến currentPassword.
Trong trường hợp, email của bạn là thông tin đăng nhập, thì nếu như để API như thế này:
PUT /account Authorization: Bearer
{ "email": "<new_email_address>" }
Thì tài khoản của bạn cũng đã bị đánh cắp. Vì vậy, bên phía BE thường hay thêm biến currentPassword để xác thực thêm.
Giải pháp
Hãy đảm bảo 100% các API, các hành động đều thông qua xác thực, bất kể các API gì đi nữa, trừ các API như login, register,.. Nhưng cũng có 1 cơ chế gì đó để đảm bảo.
Hiểu rõ cơ chế xác thực, và bạn phải biết rõ tại sao token đó lại gọi api đó. Lưu ý, Oauth, API Key không phải cơ chế xác thực.
Đừng cố gắng suy nghĩ, tạo ra xác thực, password generate. Hãy sử dụng những tiêu chuẩn.
Nên yêu cầu xác thực lại với những phương thức nhạy cảm. (Password, Email, 2FA)
Hãy triển khai xác thực nhiều yếu tố khác nhau.
Tích hợp re-capcha/ account lockout để chống lại, và bắt buộc mật khẩu phải mạnh mẽ.
API Keys không phải là xác thực, nó chỉ sử dụng cho external server, những app muốn tích hợp vào hệ thống chúng ta.
Broken Object Property Level Authorization
Nguyên Nhân
Việc request và response dữ liệu của các project trong object thì cần phải có sự access hay không, đặc biệt với những dữ liệu nhạy cảm như user: email, password, phone,... Nếu như response trả về các thông tin nhạy cảm mà trong khi đó người request lại không có quyền được xem, thì vấn đề lộ thông tin nhạy cảm rất quan trọng.
Không nên cho phép người dùng truy cập hoặc điều chỉnh những thông tin nhạy cảm một cách dễ dàng. Ví dụ như việc phone hay status của user, thì status có nhiều dạng như Active, Inactive, Deleted. Thì nếu bạn cho phép người dùng update status một cách tùy tiện, thì điều đó là không tốt. Phải có nghiệp vụ rõ ràng về vấn đề này như thêm phương thức xác thực.
Giải pháp
Khi để lộ ra những thông tin của object, thì phải xem xét kỹ và kiểm tra user request có quyền truy cập hay không? Nếu không thì không nên response ra.
Chỉ cho phép client thay đổi 1 số thuộc tính nhất định.
Hãy giữ cho data response ở mức nhỏ nhất có thể, theo yêu cầu nghiệp vụ của API đó thôi.
Unrestricted Resource Consumption
Nguyên Nhân
Last updated