2012-02-01 30 views
25

Vì vậy, tôi đã có một phương thức POST cơ bản() cho một tệp PHP.Tôi có cần mã thông báo CSRF cho jQuery .ajax() không?

Tôi cần biện pháp bảo mật nào?

Một vài bài đăng xung quanh đã đề cập đến sử dụng trường nhập MD5 ẩn mà bạn gửi qua AJAX và xác minh trong tệp PHP. Đây có phải là phương pháp đủ tốt không?

Trả lời

34

Nguy cơ từ CSRF là trang web bên ngoài có thể gửi dữ liệu đến trang của bạn và trình duyệt của người dùng sẽ tự động gửi cookie xác thực cùng với nó.

Những gì bạn cần là một số cách cho hành động nhận (rằng phương thức $.ajax() của bạn đang gửi dữ liệu POST) để có thể kiểm tra xem yêu cầu đến từ một trang khác trên trang web của bạn chứ không phải trang web bên ngoài.

Có một số cách để thực hiện việc này, nhưng cách được khuyến nghị là thêm mã thông báo vào yêu cầu mà bạn có thể kiểm tra và tin tặc không thể truy cập.

Tại đơn giản nhất:

  • Ngày đăng nhập vào tạo ra một chuỗi ngẫu nhiên dài token và lưu nó so với người dùng.
  • Thêm thông số vào yêu cầu $.ajax() bao gồm mã thông báo.
  • Khi yêu cầu, hãy kiểm tra mã thông báo khớp với mã thông báo bạn đã lưu cho người dùng.
  • Nếu mã thông báo không phù hợp với bạn, bạn sẽ bị tấn công CSRF.

Hacker không thể truy cập DB của bạn và thực sự không thể đọc trang bạn đã gửi cho người dùng (trừ khi họ bị tấn công XSS, nhưng đó là một vấn đề khác) nên không thể giả mạo mã thông báo.

Tất cả những vấn đề quan trọng với mã thông báo là bạn có thể dự đoán (và xác thực) và tin tặc không thể.

Vì lý do này, bạn dễ dàng tạo ra một cái gì đó dài và ngẫu nhiên và lưu trữ nó trong DB, nhưng bạn có thể xây dựng thứ gì đó được mã hóa thay thế. Tôi sẽ không chỉ MD5 tên người dùng mặc dù - nếu những kẻ tấn công CSRF tìm ra cách để tạo ra các thẻ của bạn, bạn sẽ bị tấn công.

Một cách khác là lưu trữ mã thông báo trong cookie (chứ không phải cơ sở dữ liệu của bạn), vì những kẻ tấn công không thể đọc hoặc thay đổi cookie của bạn, chỉ khiến chúng được gửi lại. Sau đó, bạn là mã thông báo trong dữ liệu HTTP POST khớp với mã thông báo trong cookie.

Bạn có thể làm cho chúng phức tạp hơn, ví dụ: mã thông báo thay đổi mỗi khi được sử dụng thành công (ngăn gửi lại) hoặc mã thông báo cụ thể cho người dùng và hành động, nhưng đó là mẫu cơ bản.

+6

Làm cách nào người dùng có thể đăng yêu cầu AJAX từ một trang web khác mặc dù [Chính sách tương tự gốc] (https://en.wikipedia.org/wiki/Same-origin_policy) ngăn chặn hành vi như vậy? – Songo

+3

@ Không phải tất cả các trình duyệt đều hỗ trợ điều đó. Rất nhiều proxy tiêu đề dải và phá vỡ đó quá. Cuối cùng bạn có thể POST từ bên ngoài nguồn gốc, vì vậy ngay cả khi bạn có ý định AJAX với nó mà không có nghĩa là một kẻ tấn công sẽ. Về cơ bản, bạn nên có chính sách có nguồn gốc giống nhau, nhưng vì nó dựa trên các trình duyệt được xử lý tốt nên bạn không nên dựa vào nó. Sử dụng một mã thông báo CSRF cung cấp cho bạn một cái gì đó bạn có thể xác minh ngay cả khi cùng một nguồn gốc được phá vỡ. – Keith

+0

@Songo ngay cả với phiên bản Chrome mới nhất, bạn vẫn có thể thực hiện các yêu cầu GET (nghĩa là '' '' '' trên một trang web) và nó sẽ hoạt động. @Khi tôi không tin tưởng cookie khi trình duyệt tự động gửi cookie đến trang web cho mọi yêu cầu. Nếu kẻ tấn công sử dụng một iFrame hoặc một biểu mẫu gửi cookie sẽ tự động được gửi, tôi tin tưởng. – arleslie

2

Về mặt yêu cầu giả mạo, việc khách hàng gửi yêu cầu có quan trọng như thế nào không. Các quy tắc CSRF tương tự áp dụng cho bài đăng ajax như bất kỳ loại bài đăng nào khác.

Tôi khuyên bạn nên đọc CSRF prevention cheat sheet. Sử dụng mã thông báo bí mật cho mỗi người dùng là hình thức bảo vệ phổ biến nhất.

+2

Khá phổ biến cũng là mã thông báo một lần yêu cầu cho người dùng cụ thể và bị vô hiệu hóa sau lần sử dụng đầu tiên. – Tadeck

+2

@Tadeck Cách tiếp cận đó hữu ích hơn trong việc ngăn chặn hai lần gửi hơn CSRF. – rook

+2

Như đã nêu trong [nguồn bạn tham chiếu] (https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet), mã thông báo một lần là bảo mật rất mạnh được sử dụng trong các hàm có nguy cơ cao. Đây là điều trái ngược với việc "hữu ích hơn trong việc ngăn chặn các đệ trình kép so với CSRF_", đó là cách nghiêm ngặt hơn trong việc bảo vệ ứng dụng của bạn chống lại CSRF. – Tadeck

0

Không cần mã thông báo, nhưng bạn vẫn nên bảo vệ mọi chức năng thay đổi trạng thái chống lại CSRF.

Một cách đơn giản để thực hiện việc này là thêm tiêu đề được gửi cùng với yêu cầu AJAX. Không cần mã thông báo ngẫu nhiên.

này hoạt động bởi vì:

  • dạng HTML không thể có tiêu đề tùy chỉnh thêm cho họ bởi một kẻ tấn công.
  • Tiêu đề tùy chỉnh không thể chuyển qua miền chéo mà không bật CORS.

Tất nhiên mã phía máy chủ cần đảm bảo rằng tiêu đề có mặt trước khi thực hiện hành động của nó.

Thông tin khác: What's the point of the X-Requested-With header?

Các vấn đề liên quan