Nơi lưu trữ JWT trong trình duyệt? Làm thế nào để bảo vệ chống lại CSRF?


159

Tôi biết xác thực dựa trên cookie. Cờ SSL và httpOnly có thể được áp dụng để bảo vệ xác thực dựa trên cookie khỏi MITM và XSS. Tuy nhiên, sẽ cần nhiều biện pháp đặc biệt hơn để áp dụng để bảo vệ nó khỏi CSRF. Họ chỉ là một chút phức tạp. ( tham khảo )

Gần đây, tôi phát hiện ra rằng Mã thông báo Web JSON (JWT) khá nóng như một giải pháp để xác thực. Tôi biết những thứ về mã hóa, giải mã và xác minh JWT. Tuy nhiên, tôi không hiểu tại sao một số trang web / hướng dẫn không cần bảo vệ CSRF nếu JWT được sử dụng. Tôi đã đọc khá nhiều và cố gắng tóm tắt các vấn đề dưới đây. Tôi chỉ muốn ai đó có thể cung cấp bức tranh lớn về JWT và làm rõ các khái niệm tôi đã hiểu sai về JWT.

  1. Nếu JWT được lưu trữ trong cookie, tôi nghĩ nó giống như xác thực dựa trên cookie ngoại trừ việc máy chủ không cần phải có phiên để xác minh cookie / mã thông báo. Vẫn có rủi ro về CSRF nếu không có biện pháp đặc biệt nào được thực hiện. Không phải JWT được lưu trữ trong cookie?

  2. Nếu JWT được lưu trữ trong localStorage / sessionStorage, thì không có cookie nên không cần bảo vệ chống lại CRSF. Câu hỏi là làm thế nào để gửi JWT đến máy chủ. Tôi thấy ở đây gợi ý sử dụng jQuery để gửi JWT theo tiêu đề HTTP của các yêu cầu ajax. Vì vậy, chỉ có các yêu cầu ajax có thể thực hiện xác thực?

  3. Ngoài ra, tôi tìm thấy thêm một chương trình blog để sử dụng "Tiêu đề ủy quyền" và "Người mang" để gửi JWT. Tôi không hiểu phương pháp mà blog nói về. Ai đó có thể vui lòng giải thích thêm về "Tiêu đề ủy quyền" và "Người mang" không? Điều này có làm cho JWT được truyền bởi tiêu đề HTTP của TẤT CẢ các yêu cầu không? Nếu có, làm thế nào về CSRF?

Câu trả lời:


70

Mã thông báo JWT rất phổ biến vì chúng được sử dụng làm định dạng mã thông báo mặc định trong các giao thức xác thực và ủy quyền mới như OAuth 2.0OpenID Connect .

Khi mã thông báo được lưu trữ trong cookie, trình duyệt sẽ tự động gửi nó cùng với mỗi yêu cầu đến cùng một tên miền và điều này vẫn dễ bị tấn công CSRF.

Xác thực Bearer là một trong những lược đồ xác thực được xác định trong HTTP. Về cơ bản, điều đó có nghĩa là YOUgắn mã thông báo (JWT) trong tiêu đề HTTP ủy quyền của một yêu cầu. Trình duyệt sẽ NOTtự động làm điều này cho bạn, vì vậy nó không phù hợp để bảo vệ trang web của bạn. Vì trình duyệt không tự động thêm tiêu đề vào yêu cầu của bạn, nên nó không dễ bị tấn công CSRF, điều này phụ thuộc vào thông tin xác thực của bạn được gửi tự động đến tên miền ban đầu.

Lược đồ mang thường được sử dụng để bảo vệ API web (dịch vụ REST) ​​được sử dụng thông qua các cuộc gọi AJAX hoặc từ các máy khách di động.


1
@ Timespace7 Không, mã thông báo JWT cũng thường được sử dụng từ các khách hàng bản địa. OAuth 2.0 có các luồng khách hàng đặc biệt nhắm mục tiêu (di động). Điều họ không làm là xác thực trình duyệt ngầm định (như cookie hoặc xác thực cơ bản.).
MvdD

5
Tôi đang nói rằng nếu API của bạn chỉ lấy mã thông báo JWT từ tiêu đề Ủy quyền thì nó không dễ bị CSRF. Bất kỳ trang web hoặc API nào nhận được mã thông báo từ cookie đều cần giảm thiểu CSRF.
MvdD

13
Điều này có nghĩa là chúng tôi có thể lưu trữ jwt trong cookie một cách hiệu quả và nó sẽ được bảo mật nếu chúng tôi gửi yêu cầu với nó trong tiêu đề Ủy quyền?
quay phim

10
@cameronjroe bạn có thể lưu trữ nó trong cookie của mình nhưng chỉ khi bạn không sử dụng cookie để xác thực (bạn sử dụng các tiêu đề của mình trong trường hợp này)
Jaakko

1
Các cuộc gọi AJAX cũng bắt nguồn từ trình duyệt. Mã thông báo JWT chủ yếu được sử dụng để xác thực API web (dữ liệu phục vụ) so với cookie được sử dụng để xác thực ứng dụng web (phục vụ đánh dấu, hình ảnh, css và JavaScript)
MvdD

143

Chúng ta cần lưu trữ JWT trên máy khách. Nếu chúng ta lưu trữ nó trong LocalStorage / SessionStorage thì nó có thể dễ dàng bị bắt bởi một cuộc tấn công XSS. Nếu chúng tôi lưu trữ nó trong cookie thì tin tặc có thể sử dụng nó (mà không cần đọc) trong một cuộc tấn công CSRF và mạo danh người dùng và liên hệ với API của chúng tôi và gửi yêu cầu thực hiện hành động hoặc lấy thông tin thay mặt cho người dùng.

Nhưng có một số cách để bảo mật JWT trong cookie để không bị đánh cắp dễ dàng (nhưng vẫn có một số kỹ thuật tiên tiến để đánh cắp chúng). Nhưng nếu bạn muốn dựa vào LocalStorage / SessionStorage, thì nó có thể được truy cập bằng một cuộc tấn công XSS đơn giản.

Vì vậy, để giải quyết vấn đề CSRF, tôi sử dụng Double Gửi Cookies trong ứng dụng của mình.

Phương pháp gửi đôi

  1. Lưu trữ JWT trong cookie httpOnly và sử dụng nó trong chế độ bảo mật để chuyển qua HTTPS.

  2. Hầu hết các cuộc tấn công CSRF có tiêu đề nguồn gốc hoặc người giới thiệu khác với máy chủ ban đầu của bạn trong các yêu cầu của họ. Vì vậy, hãy kiểm tra xem bạn có bất kỳ ai trong số họ trong tiêu đề không, họ có đến từ miền của bạn hay không! Nếu không từ chối họ. Nếu cả nguồn gốc và người giới thiệu đều không có sẵn trong yêu cầu thì không phải lo lắng. Bạn có thể dựa vào kết quả xác thực tiêu đề X-XSRF-TOKEN mà tôi giải thích trong bước tiếp theo.

  3. Mặc dù trình duyệt sẽ tự động cung cấp cookie của bạn cho miền yêu cầu, nhưng có một hạn chế hữu ích: mã JavaScript đang chạy trên trang web không thể đọc cookie của các trang web khác. Chúng ta có thể tận dụng điều này để tạo ra giải pháp CSRF của mình. Để ngăn chặn các cuộc tấn công CSRF, chúng tôi phải tạo một cookie có thể đọc thêm Javascript được gọi là: XSRF-TOKEN. Cookie này phải được tạo khi người dùng đăng nhập và phải chứa một chuỗi ngẫu nhiên, không thể đoán được. Chúng tôi cũng lưu số này trong chính JWT như một yêu cầu riêng. Mỗi khi ứng dụng JavaScript muốn thực hiện một yêu cầu, nó sẽ cần đọc mã thông báo này và gửi nó trong một tiêu đề HTTP tùy chỉnh. Bởi vì các thao tác này (đọc cookie, đặt tiêu đề) chỉ có thể được thực hiện trên cùng một miền của ứng dụng JavaScript,

Angular JS làm cho cuộc sống của bạn dễ dàng

May mắn thay, tôi đang sử dụng Angular JS trong nền tảng của chúng tôi và các gói Angular tiếp cận mã thông báo CSRF, giúp chúng tôi thực hiện đơn giản hơn. Đối với mọi yêu cầu mà ứng dụng Angular của chúng tôi thực hiện đối với máy chủ, $httpdịch vụ Angular sẽ tự động thực hiện những việc này:

  • Hãy tìm một cookie có tên XSRF-TOKEN trên tên miền hiện tại.
  • Nếu cookie đó được tìm thấy, nó sẽ đọc giá trị và thêm nó vào yêu cầu dưới dạng tiêu đề X-XSRF-TOKEN.

Do đó, việc thực hiện phía máy khách được xử lý cho bạn, tự động! Chúng ta chỉ cần đặt một cookie có tên XSRF-TOKENtrên miền hiện tại ở phía máy chủ và khi API của chúng tôi nhận được bất kỳ cuộc gọi nào từ máy khách, nó phải kiểm tra X-XSRF-TOKENtiêu đề và so sánh nó với XSRF-TOKENJWT. Nếu chúng phù hợp, thì người dùng là có thật. Mặt khác, đó là một yêu cầu giả mạo và bạn có thể bỏ qua nó. Phương pháp này được lấy cảm hứng từ phương pháp "Double Gửi Cookie".

Thận trọng

Trên thực tế, bạn vẫn dễ bị XSS, chỉ là kẻ tấn công không thể đánh cắp mã thông báo JWT của bạn để sử dụng sau này, nhưng anh ta vẫn có thể yêu cầu thay mặt người dùng của bạn bằng XSS.

Cho dù bạn lưu trữ JWT của mình trong localStoragehoặc bạn lưu mã thông báo XSRF của bạn trong cookie không phải là HTTPOnly, cả hai đều có thể được XSS lấy một cách dễ dàng. Ngay cả JWT của bạn trong cookie HTTPOnly cũng có thể bị bắt bởi một cuộc tấn công XSS nâng cao như phương pháp XST .

Vì vậy, ngoài phương pháp Double Gửi Cookies, bạn phải luôn tuân theo các thực tiễn tốt nhất chống lại XSS bao gồm cả thoát nội dung. Điều này có nghĩa là loại bỏ bất kỳ mã thực thi nào có thể khiến trình duyệt làm điều gì đó mà bạn không muốn. Thông thường, điều này có nghĩa là loại bỏ // <![CDATA[các thẻ và thuộc tính HTML khiến JavaScript được đánh giá.

Đọc thêm tại đây:


1
@AranDehkharghani vâng Tôi đoán nó ngăn chặn cuộc tấn công lại đặc biệt là nếu bạn thay đổi JWT và hết hạn JWT trước đó mỗi khi nó được API sử dụng. điều đó có nghĩa là JWT của bạn sẽ trở thành giống như mật khẩu một lần (OTP). Bạn có thể sử dụng JWT theo nhiều cách khác nhau tùy thuộc vào mức độ bạn quan tâm đến bảo mật trong nền tảng của mình.
Iman Sedighi

7
Như bạn đã đề cập, nếu một trang web dễ bị XSS, thì đó chỉ là vấn đề thời gian trước khi người dùng bị khai thác. Có vẻ như chúng tôi đang giao dịch phức tạp đáng kể cho một sự gia tăng rất nhỏ về bảo mật.
shusson

3
@shusson Bạn phải quan tâm đến các cuộc tấn công XSS và XSRF để bảo vệ JWT của bạn. Tôi không đồng ý rằng bạn đang giao dịch phức tạp đáng kể cho sự gia tăng rất nhỏ về bảo mật. Nếu vấn đề bảo mật, thì bạn cần nỗ lực hết sức để không có lỗ hổng XSS. Phương pháp này được thiết kế để bảo vệ mã thông báo của bạn khỏi các cuộc tấn công XSRF. nhưng điều đó không có nghĩa là bạn có thể bỏ qua các lỗ hổng XSS.
Iman Sedighi

5
@ImanSedighi Tôi không rõ, bằng cách lưu trữ jwt trong cookie, bạn đang thêm độ phức tạp và giờ bạn phải bảo vệ chống lại XSRF. Vậy tại sao không sử dụng lưu trữ cục bộ với mã thông báo tuổi thọ ngắn và tập trung vào việc ngăn chặn XSS?
shusson

2
@Royi Namir: Việc giả mạo của Wireshark không phải là vấn đề đáng lo ngại nếu bạn sử dụng chứng chỉ SSL $ 10! Nếu bảo mật của trang web là quan trọng thì bạn nên mã hóa dữ liệu và sử dụng giao thức HTTPS.
Iman Sedighi

2

Một góc khác cho toàn bộ vấn đề lưu trữ JWT:

  1. JWT không bao giờ nên được lưu trữ trong localStorage của bạn
  2. Trên thực tế, chúng thậm chí không nên được lưu trữ trong cookie của bạn , trừ khi bạn có thể thực hiện bảo vệ CSRF rất nghiêm ngặt

Kiểm tra này để có động lực

  • JWT là một id_token giống như thông tin người dùng của bạn
  • JWT với tư cách là access_token giống như mã thông báo phiên của bạn

Tùy chọn an toàn nhất là trong bộ nhớ . Kiểm tra cái này để lặn sâu

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.