1. Tấn công CSRF là gì?

Cách tốt nhất để hiểu một cuộc tấn công CSRF là xem một ví dụ cụ thể.

Giả sử rằng trang web ngân hàng của bạn cung cấp biểu mẫu cho phép chuyển tiền từ người dùng hiện đang đăng nhập sang tài khoản ngân hàng khác. Ví dụ: biểu mẫu chuyển khoản có thể trông như sau:

Mẫu chuyển nhượng
vidu1

Yêu cầu HTTP tương ứng có thể trông giống như:

Chuyển yêu cầu HTTP
vidu2

Bây giờ hãy giả vờ bạn xác thực với trang web ngân hàng của mình và sau đó, không cần đăng xuất, hãy truy cập một trang web độc hại. Trang web độc ác chứa một trang HTML có dạng sau:

Hình thức chuyển độc hại
vidu3

Bạn thích giành được tiền nên bạn nhấp vào nút gửi. Trong quá trình này, bạn đã vô tình chuyển 100 USD cho một người dùng có ác ý. Điều này xảy ra bởi vì, mặc dù trang web độc hại không thể nhìn thấy cookie của bạn nhưng các cookie được liên kết với ngân hàng của bạn vẫn được gửi cùng với yêu cầu.

Tệ hơn nữa, toàn bộ quá trình này có thể đã được tự động hóa bằng cách sử dụng JavaScript. Điều này có nghĩa là bạn thậm chí không cần phải bấm vào nút. Hơn nữa, điều này có thể dễ dàng xảy ra khi truy cập một trang web trung thực là nạn nhân của cuộc tấn công XSS . Vậy làm cách nào để bảo vệ người dùng của mình khỏi các cuộc tấn công như vậy?

2. Bảo vệ chống lại các cuộc tấn công CSRF

Lý do có thể xảy ra một cuộc tấn công CSRF là do yêu cầu HTTP từ trang web của nạn nhân và yêu cầu từ trang web của kẻ tấn công hoàn toàn giống nhau. Điều này có nghĩa là không có cách nào để từ chối các yêu cầu đến từ trang web độc ác và chỉ cho phép các yêu cầu đến từ trang web của ngân hàng. Để bảo vệ khỏi các cuộc tấn công CSRF, chúng tôi cần đảm bảo có điều gì đó trong yêu cầu mà trang web xấu không thể cung cấp để chúng tôi có thể phân biệt hai yêu cầu.

Spring cung cấp hai cơ chế để bảo vệ chống lại các cuộc tấn công CSRF:

  • The Synchronizer Token Pattern

  • Chỉ định thuộc tính SameSite trên phiên cookie của bạn

Để bảo vệ chống lại CSRF hoạt động, ứng dụng phải đảm bảo rằng các phương thức HTTP “an toàn” ở chế độ chỉ đọc . Điều này có nghĩa là các yêu cầu với các phương thức HTTP GET, HEAD, OPTIONSvà TRACEsẽ không thay đổi trạng thái của ứng dụng.

2.1. Synchronizer Token Pattern

Cách chủ yếu và toàn diện nhất để bảo vệ chống lại các cuộc tấn công CSRF là sử dụng Mẫu mã thông báo đồng bộ hóa . Giải pháp này nhằm đảm bảo rằng ngoài cookie phiên của chúng tôi, mỗi yêu cầu HTTP còn yêu cầu một giá trị được tạo ngẫu nhiên an toàn được gọi là mã thông báo CSRF phải có trong yêu cầu HTTP.

Khi yêu cầu HTTP được gửi, máy chủ phải tra cứu mã thông báo CSRF dự kiến và so sánh nó với mã thông báo CSRF thực tế trong yêu cầu HTTP. Nếu các giá trị không khớp, yêu cầu HTTP sẽ bị từ chối.

Chìa khóa để làm việc này là mã thông báo CSRF thực tế phải nằm trong một phần của yêu cầu HTTP mà trình duyệt không tự động đưa vào. Ví dụ: yêu cầu mã thông báo CSRF thực tế trong tham số HTTP hoặc tiêu đề HTTP sẽ bảo vệ khỏi các cuộc tấn công CSRF. Yêu cầu mã thông báo CSRF thực tế trong cookie không hoạt động vì cookie được trình duyệt tự động đưa vào yêu cầu HTTP.

Chúng tôi có thể giảm bớt kỳ vọng khi chỉ yêu cầu mã thông báo CSRF thực tế cho mỗi yêu cầu HTTP cập nhật trạng thái của ứng dụng. Để điều đó hoạt động, ứng dụng của chúng tôi phải đảm bảo rằng các phương thức HTTP an toàn ở chế độ chỉ đọc . Điều này cải thiện khả năng sử dụng vì chúng tôi muốn cho phép liên kết đến trang web của chúng tôi từ các trang bên ngoài. Ngoài ra, chúng tôi không muốn đưa mã thông báo ngẫu nhiên vào HTTP GET vì điều này có thể khiến mã thông báo bị rò rỉ.

Hãy xem ví dụ của chúng tôi sẽ thay đổi như thế nào khi chúng tôi sử dụng Mẫu mã thông báo đồng bộ hóa. Giả sử rằng mã thông báo CSRF thực tế bắt buộc phải có tham số HTTP có tên _csrf. Biểu mẫu chuyển khoản của ứng dụng của chúng tôi sẽ trông như sau:

Biểu mẫu mã thông báo đồng bộ hóa
vidu4

Biểu mẫu hiện chứa đầu vào ẩn có giá trị của mã thông báo CSRF. Các trang web bên ngoài không thể đọc mã thông báo CSRF vì chính sách xuất xứ tương tự đảm bảo trang web độc hại không thể đọc phản hồi.

Yêu cầu HTTP tương ứng để chuyển tiền sẽ như thế này:

Yêu cầu mã thông báo đồng bộ hóa
vidu5

Bạn sẽ nhận thấy rằng yêu cầu HTTP hiện chứa _csrftham số có giá trị ngẫu nhiên an toàn. Trang web độc ác sẽ không thể cung cấp giá trị chính xác cho _csrftham số (phải được cung cấp rõ ràng trên trang web độc ác) và quá trình truyền sẽ không thành công khi máy chủ so sánh mã thông báo CSRF thực tế với mã thông báo CSRF dự kiến.

2.2. SameSite Attribute

Một cách mới nổi để bảo vệ chống lại các cuộc tấn công CSRF là chỉ định Thuộc tính SameSite trên cookie. Máy chủ có thể chỉ định thuộc tính SameSite khi đặt cookie để cho biết rằng cookie không được gửi khi đến từ các trang web bên ngoài.

Spring Security không trực tiếp kiểm soát việc tạo session cookie nên không cung cấp hỗ trợ cho thuộc tính SameSite. Spring session cung cấp hỗ trợ cho thuộc tính SameSite trong các ứng dụng dựa trên servlet. Spring Framework CookieWebSessionIdResolver cung cấp hỗ trợ vượt trội cho thuộc tính SameSite này trong các ứng dụng dựa trên WebFlux.

Một ví dụ về tiêu đề phản hồi HTTP có thuộc tính SameSite có thể trông giống như:

Phản hồi HTTP SameSite
vidu6

Đã sao chép!
Các giá trị hợp lệ cho thuộc tính SameSite là:

  • Strict: Khi được chỉ định, mọi yêu cầu đến từ cùng một trang web sẽ bao gồm cookie. Nếu không, cookie sẽ không được đưa vào yêu cầu HTTP.

  • Lax: Khi được chỉ định, cookie sẽ được gửi khi đến từ cùng một trang web hoặc khi yêu cầu đến từ điều hướng cấp cao nhất và phương thức này là chỉ đọc . Nếu không, cookie sẽ không được đưa vào yêu cầu HTTP.

Hãy xem xét ví dụ của chúng tôi có thể được bảo vệ như thế nào bằng cách sử dụng thuộc tính SameSite này. Ứng dụng ngân hàng có thể bảo vệ chống lại CSRF bằng cách chỉ định thuộc tính SameSite trên cookie phiên.

Với thuộc tính SameSite được đặt trên phiên cookie của chúng tôi, trình duyệt tiếp tục gửi JSESSIONIDcookie với các yêu cầu đến từ trang web ngân hàng. Tuy nhiên, trình duyệt không còn gửi JSESSIONIDcookie với yêu cầu chuyển đến từ trang web độc ác nữa. Vì phiên không còn xuất hiện trong yêu cầu chuyển đến từ trang web độc hại nên ứng dụng được bảo vệ khỏi cuộc tấn công CSRF.

Có một số cân nhắc quan trọng cần lưu ý khi sử dụng SameSite thuộc tính để bảo vệ chống lại các cuộc tấn công CSRF.

Việc đặt SameSitethuộc tính để Strictcung cấp khả năng phòng thủ mạnh mẽ hơn nhưng có thể khiến người dùng bối rối. Hãy xem xét một người dùng luôn đăng nhập vào một trang mạng xã hội được lưu trữ tại social.example.com . Người dùng nhận được email tại email.example.org bao gồm liên kết đến trang truyền thông xã hội. Nếu người dùng nhấp vào liên kết, họ thực sự mong đợi được xác thực với trang mạng xã hội. Tuy nhiên, nếu SameSitethuộc tính là Strict, cookie sẽ không được gửi và do đó người dùng sẽ không được xác thực.

Chúng tôi có thể cải thiện khả năng bảo vệ và khả năng sử dụng tính năng SameSite bảo vệ chống lại các cuộc tấn công CSRF bằng cách triển khai gh-7537 .

Một điều cần cân nhắc rõ ràng khác là, để thuộc SameSitetính bảo vệ người dùng, trình duyệt phải hỗ trợ SameSitethuộc tính đó. Hầu hết các trình duyệt hiện đại đều hỗ trợ thuộc tính SameSite . Tuy nhiên, các trình duyệt cũ hơn vẫn đang được sử dụng có thể không có.

Vì lý do này, bạn nên sử dụng SameSite thuộc tính này làm biện pháp phòng thủ theo chiều sâu thay vì biện pháp bảo vệ duy nhất chống lại các cuộc tấn công CSRF.

Kết luận:
Spring cung cấp hỗ trợ toàn diện để bảo vệ chống lại các cuộc tấn công giả mạo yêu cầu trang web chéo (CSRF) . Trong các phần trên, chúng ta khám phá:

  • Tấn công CSRF là gì?

  • Bảo vệ chống lại các cuộc tấn công CSRF

Nguồn: https://docs.spring.io/spring-security/reference/features/exploits/csrf.html#csrf-protection-ssa