Tôi đang thiết kế API cho một nhóm trang web. Các trang web là rất giống nhau (loại giống như StackOverflow, SuperUser và ServerFault), và nó làm cho tinh thần cho họ để có một phụ trợ được chia sẻ. Do đó, chúng tôi đã quyết định thử và có một API REST tốt đẹp như một phụ trợ, và một loạt các giao diện rất giống nhau nhưng khác nhau tiêu thụ API nói trên. Các giao diện tốt nhất nên là tất cả các tĩnh, nhưng đó không phải là một yêu cầu khó khăn nếu nó hóa ra là đường biên giới không thể.Làm thế nào để bạn bảo mật API RESTful được một trình duyệt từ các cuộc tấn công CSRF tiêu thụ?
Tôi đang thiết kế API đó ngay bây giờ và tôi lo lắng về các tác động bảo mật, đặc biệt là CSRF. Từ hiểu biết cơ bản về tấn công CSRF của tôi, chúng bao gồm hai thành phần quan trọng:
Có thể đặt tên cho tài nguyên và phần yêu cầu.
Lừa người dùng/trình duyệt vào sử dụng auth môi trường xung quanh (như phiên) để thực hiện yêu cầu tới tài nguyên đó được xác thực.
Rất nhiều cách tiếp cận cổ điển để khắc phục các cuộc tấn công CSRF dựa trên phiên. Vì API REST của tôi không thực sự thực hiện các phiên, cả hai đều ngăn chặn rất nhiều vectơ và cũng có khá nhiều cách để khắc phục chúng. Ví dụ: việc gửi hai lần không có ý nghĩa vì không có gì để gửi đôi.
Cách tiếp cận ban đầu của tôi liên quan đến tấn công phần 2 của cuộc tấn công CSRF. Nếu tôi xác thực tất cả các yêu cầu (nói bằng cách sử dụng xác thực cơ bản HTTP) và trình duyệt không lưu trữ các thông tin đăng nhập đó (ví dụ như một số JS đã thực hiện yêu cầu), chỉ JS có thông tin xác thực mới có thể thực hiện yêu cầu và chúng tôi đã hoàn tất . Nhược điểm rõ ràng là ứng dụng cần biết thông tin đăng nhập của người dùng. Nhược điểm khác ít rõ ràng hơn là nếu tôi muốn lưu trữ thông tin đăng nhập một cách an toàn vào cuối API, thì việc xác minh mật khẩu sẽ mất một khoảng thời gian cố định, không nhỏ. Nếu xác minh mật khẩu một cách an toàn mất 100ms, sau đó mọi yêu cầu khác sẽ mất ít nhất 100ms + eps, và nó sẽ mất một số thủ thuật khách hàng thông minh darn để làm cho rằng không cảm thấy chậm. Tôi có thể nhớ cache (vì thông tin đăng nhập sẽ luôn giống nhau) và nếu tôi rất cẩn thận, tôi có thể quản lý để làm điều đó mà không đưa ra lỗ hổng thời gian, nhưng âm thanh giống như tổ của hornet.
OAuth 2.0 có vẻ hơi hơn trên đầu, nhưng tôi đoán nó có thể là giải pháp tốt nhất sau tất cả, vì sợ rằng tôi sẽ thực hiện nó kém. Tôi cho rằng tôi có thể thực hiện điều xác thực cơ bản HTTP ngay bây giờ và chuyển sang OAuth khi chúng tôi có nhà phát triển ứng dụng bên thứ ba.
Có một chút trở kháng không khớp với OAuth. OAuth thực sự muốn giúp các ứng dụng truy cập nội dung trên ứng dụng khác, về cơ bản. Tôi muốn người dùng đăng ký trên một trong các giao diện người dùng, trước khi một tài khoản như vậy tồn tại.
Tôi cũng đã xem xét điểm tấn công 1 bằng cách tạo các URL ngẫu nhiên - nghĩa là thêm mã thông báo vào chuỗi truy vấn. Điều này chắc chắn sẽ hoạt động và nó rất gần với cách mã thông báo ngẫu nhiên truyền thống trong một biểu mẫu hoạt động, và cho HATEOAS nó thậm chí còn khá yên tĩnh, mặc dù điều này đặt ra hai câu hỏi: 1) bạn bắt đầu từ đâu? Có một điểm bắt đầu API bắt buộc khi bạn đăng nhập bằng HTTP Basic Auth không? 2) Làm thế nào nó có thể làm cho các nhà phát triển ứng dụng hạnh phúc nếu họ không thể dự đoán một URL lên phía trước, HATEOAS được damned?
Tôi đã xem How to prevent CSRF in a RESTful application?, nhưng tôi không đồng ý với tiền đề rằng các URI ngẫu nhiên nhất thiết là không ổn định. Ngoài ra, câu hỏi đó không thực sự có bất kỳ câu trả lời thỏa đáng nào và không đề cập đến OAuth. Ngoài ra, giải pháp gửi đôi phiên không hợp lệ, như tôi đã đề cập ở trên (miền khác cho giao diện người dùng tĩnh hơn điểm cuối API).
Tôi nhận ra rằng những gì tôi về cơ bản cố gắng làm ở đây là cố gắng cho phép các yêu cầu chéo từ một miền và không cho phép chúng từ miền khác và điều đó không dễ dàng. Chắc chắn phải có một số giải pháp hợp lý?
Vấn đề, như bạn nói, là bạn muốn cả hai ngăn chặn và cho phép yêu cầu qua nhiều trang web. Hãy hỏi Schrödinger. –
Điều đó không có nghĩa là không có cách nào để giải quyết vấn đề. Tôi thậm chí còn cung cấp một cái có thể, mặc dù hơi chậm. – lvh