Nếu JWT bị đánh cắp thì sao?


201

Tôi đang cố gắng thực hiện xác thực không trạng thái với JWT cho các API RESTful của mình.

AFAIK, JWT về cơ bản là một chuỗi được mã hóa được truyền dưới dạng các tiêu đề HTTP trong khi gọi REST.

Nhưng chuyện gì sẽ xảy ra nếu có kẻ nghe trộm nhìn thấy yêu cầu và đánh cắp mã thông báo ? Sau đó, anh ta sẽ có thể giả mạo yêu cầu với danh tính của tôi?

Trên thực tế, mối quan tâm này áp dụng cho tất cả xác thực dựa trên mã thông báo .

Làm thế nào để ngăn chặn điều đó? Một kênh an toàn như HTTPS?


1
Đây là lý do tại sao mã thông báo thường chỉ có giá trị trong một khoảng thời gian ngắn. Và có, bạn nên sử dụng HTTPS nếu bạn lo ngại về tính bảo mật của dữ liệu của mình.
Jonathon Reinhart

4
@JonathonReinhart Nhưng nếu mã thông báo hết hạn sớm, khách hàng của tôi sẽ phải nhận mã thông báo mới bằng cách tự xác thực lại theo thời gian. Nó không phải là tẻ nhạt?
smwikipedia

@JonathonReinhart Tôi nghĩ rằng tôi hiểu được lý do tại sao mã thông báo chỉ tồn tại trong thời gian ngắn. Bởi vì theo cách đó, máy chủ không cần theo dõi hết hạn mã thông báo và do đó mở đường cho khả năng mở rộng. Đó là một loại trade-offgiữa having finer control of token expirationhaving better scalability.
smwikipedia

2
Điều này cũng có thể giúp đỡ? - "Một cơ chế bảo mật phổ biến để phát hiện hành vi trộm cắp mã thông báo là theo dõi nguồn gốc địa chỉ IP yêu cầu." - được mô tả chi tiết trong phần cuối tại đây - firebase.google.com/docs/auth/admin/manage-simes
Ula

3
Về mặt lý thuyết, không thể ngăn chặn hành vi trộm cắp mã thông báo. Điều tốt nhất chúng ta có thể làm là phát hiện điều đó đã xảy ra và sau đó thu hồi phiên càng sớm càng tốt. Phương pháp tốt nhất để phát hiện là sử dụng mã thông báo làm mới xoay (theo đề xuất của RFC 6819). Đây là một blog giải thích điều này một cách chi tiết: supertokens.io/blog/ Kẻ
Rishabh Poddar

Câu trả lời:


284

Tôi là tác giả của một thư viện nút xử lý xác thực ở một số độ sâu, tốc độ nhanh , vì vậy tôi sẽ đồng ý với một số thông tin ở đây.

Trước hết, JWT thường KHÔNG được mã hóa. Mặc dù có một cách để mã hóa JWT (xem: JWEs ), nhưng điều này không phổ biến trong thực tế vì nhiều lý do.

Tiếp theo, bất kỳ hình thức xác thực nào (có sử dụng JWT hay không), đều phải chịu các cuộc tấn công MitM (người trung gian). Những cuộc tấn công này xảy ra khi kẻ tấn công có thể XEM lưu lượng MẠNG CỦA BẠN khi bạn thực hiện các yêu cầu qua internet. Đây là những gì ISP của bạn có thể thấy, NSA, v.v.

Đây là những gì SSL giúp ngăn chặn: bằng cách mã hóa lưu lượng NETWORK từ máy tính của bạn -> một số máy chủ khi xác thực, bên thứ ba đang theo dõi lưu lượng truy cập mạng của bạn KHÔNG thể thấy mã thông báo, mật khẩu hoặc bất cứ thứ gì tương tự trừ khi chúng có thể bằng cách nào đó để có một bản sao khóa SSL riêng của máy chủ (không chắc). Đây là lý do SSL là BẮT BUỘC cho tất cả các hình thức xác thực.

Tuy nhiên, giả sử ai đó có thể khai thác SSL của bạn và có thể xem mã thông báo của bạn: câu trả lời cho câu hỏi của bạn là , kẻ tấn công sẽ có thể sử dụng mã thông báo đó để mạo danh bạn và yêu cầu máy chủ của bạn.

Bây giờ, đây là nơi các giao thức đến.

JWT chỉ là một tiêu chuẩn cho mã thông báo xác thực. Chúng có thể được sử dụng cho khá nhiều thứ. Lý do JWT thú vị là vì bạn có thể nhúng thông tin bổ sung vào đó và bạn có thể xác thực rằng không ai đã nhầm lẫn với nó (ký).

TUY NHIÊN, bản thân JWT không liên quan gì đến 'bảo mật'. Đối với tất cả ý định và mục đích, JWT ít nhiều giống với khóa API: chỉ là các chuỗi ngẫu nhiên mà bạn sử dụng để xác thực đối với một số máy chủ ở đâu đó.

Điều làm cho câu hỏi của bạn thú vị hơn là giao thức đang được sử dụng (rất có thể là OAuth2).

Cách thức hoạt động của OAuth2 là nó được thiết kế để cung cấp cho khách hàng mã thông báo TẠM THỜI (như JWTs!) Để xác thực cho CHỈ CÓ THỜI GIAN NGẮN HẠN!

Ý tưởng là nếu mã thông báo của bạn bị đánh cắp, kẻ tấn công chỉ có thể sử dụng nó trong một khoảng thời gian ngắn.

Với OAuth2, bạn phải tự xác thực lại với máy chủ thường xuyên bằng cách cung cấp tên người dùng / mật khẩu HOẶC thông tin API và sau đó nhận lại mã thông báo.

Bởi vì quá trình này xảy ra mọi lúc, mã thông báo của bạn sẽ thường xuyên thay đổi, khiến kẻ tấn công khó liên tục mạo danh bạn hơn mà không gặp phải rắc rối lớn.

Hy vọng điều này sẽ giúp ^^


3
Tác giả của bài viết sau đây lập luận rằng một nhược điểm của JWT là cách duy nhất để phục hồi từ JWT bị đánh cắp là tạo cặp khóa mới và đăng xuất hiệu quả tất cả người dùng. Trong khi với id phiên được lưu trữ trong DB, trang web chỉ có thể xóa các phiên của người dùng bị ảnh hưởng và đăng xuất anh ta khỏi tất cả các thiết bị. Tôi không chắc chắn làm thế nào OAuth2 phù hợp với hình ảnh ở đây hoặc liệu nó có giúp giảm thiểu những nhược điểm được trình bày hay không. Medium.com/@rahulgolwalkar/ từ
Marcel

4
Tác giả không chính xác. Có các mẫu thiết kế khác nhau mà bạn có thể sử dụng để làm mất hiệu lực mã thông báo. Nhưng nói chung: sử dụng JWT cho bất kỳ mục đích xác thực nào là một ý tưởng tồi. Hiệu quả hơn nhiều khi sử dụng cookie phiên với ý tưởng phiên được nhúng bên trong được ký bằng mật mã.
rdegges

1
@rdegges vui lòng cho tôi biết JWT là ý tưởng tồi để xác thực như thế nào? và làm thế nào tôi có thể sử dụng cookie phiên mà bạn đã đề cập trong nhận xét của bạn ở trên?
tufail noman

6
Đây là cách quá dài để gõ một phản hồi. Nếu bạn muốn tìm hiểu thêm, tôi đã nói chuyện chi tiết về chủ đề này. Bạn có thể xem các trang trình bày của tôi trực tuyến: loadeck.com/rdegges/jwts-suck-and-are-stool
ndegges

2
Về mặt lý thuyết, không thể ngăn chặn hành vi trộm cắp mã thông báo. Điều tốt nhất chúng ta có thể làm là phát hiện điều đó đã xảy ra và sau đó thu hồi phiên càng sớm càng tốt. Phương pháp tốt nhất để phát hiện là sử dụng mã thông báo làm mới xoay (theo đề xuất của RFC 6819). Đây là một blog giải thích điều này một cách chi tiết: supertokens.io/blog/ Kẻ
Rishabh Poddar

31

Tôi biết đây là một câu hỏi cũ nhưng tôi nghĩ rằng tôi có thể giảm 0,5 đô la của mình ở đây, có lẽ ai đó có thể cải thiện hoặc đưa ra một lập luận để từ chối hoàn toàn cách tiếp cận của tôi. Tôi đang sử dụng JWT trong API RESTful qua HTTPS (ofc).

Để điều này hoạt động, bạn phải luôn phát hành các mã thông báo ngắn hạn (tùy thuộc vào hầu hết các trường hợp, trong ứng dụng của tôi, tôi thực sự đặt expyêu cầu là 30 phút và ttlđến 3 ngày, vì vậy bạn có thể làm mới mã thông báo này miễn ttllà vẫn còn hợp lệ và mã thông báo chưa được đưa vào danh sách đen )

Đối với authentication service, để vô hiệu hóa mã thông báo, tôi muốn sử dụng lớp bộ nhớ cache trong bộ nhớ ( làm lại trong trường hợp của tôi) làm JWT blacklist/ ban-listở phía trước, tùy thuộc vào một số tiêu chí: (Tôi biết rằng nó phá vỡ triết lý RESTful, nhưng các tài liệu được lưu trữ là thực sự ngắn ngủi, khi tôi đưa vào danh sách đen cho thời gian còn sống của họ - ttlyêu cầu-)

Lưu ý: mã thông báo trong danh sách đen không thể được làm mới tự động

  • Nếu user.passwordhoặc user.emailđã được cập nhật (yêu cầu xác nhận mật khẩu), dịch vụ xác thực sẽ trả lại mã thông báo được làm mới và không hợp lệ (danh sách đen) trước đó, vì vậy nếu khách hàng của bạn phát hiện ra rằng danh tính người dùng đã bị xâm phạm bằng cách nào đó, bạn có thể yêu cầu người dùng đó thay đổi mật khẩu của mình. . Nếu bạn không muốn sử dụng danh sách đen cho nó, bạn có thể (nhưng tôi không khuyến khích bạn) xác thực yêu cầu iat(ban hành tại) đối với user.updated_attrường (nếu jwt.iat < user.updated_atsau đó JWT không hợp lệ).
  • Người dùng cố tình đăng xuất.

Cuối cùng, bạn xác nhận mã thông báo như mọi người vẫn làm.

Lưu ý 2: thay vì sử dụng chính mã thông báo (thực sự dài) làm khóa của bộ đệm, tôi khuyên bạn nên tạo và sử dụng mã thông báo UUID cho jtikhiếu nại. Điều này là tốt và tôi nghĩ (không chắc vì nó xuất hiện trong tâm trí của tôi), bạn cũng có thể sử dụng UUID này giống như mã thông báo CSRF, bằng cách trả lại secure/ non-http-onlycookie với nó và thực hiện đúng X-XSRF-TOKENtiêu đề bằng js. Bằng cách này, bạn sẽ tránh được công việc tính toán khi tạo một mã thông báo khác để kiểm tra CSRF.


9
Không bao giờ là quá muộn để đóng góp ý tưởng của bạn. Cảm ơn vì đã trả lời.
smwikipedia

2
Nếu bạn lưu trữ một danh sách đen trên máy chủ cần được kiểm tra cho mọi yêu cầu, tại sao không sử dụng phiên cũ đơn giản?
Franklin Yu

@FranklinYu Một danh sách đen là cách "rẻ hơn" so với một cửa hàng phiên đầy đủ. Vì bạn đang lưu trữ các đối tượng giá trị khóa có thời gian tồn tại ngắn (tùy thuộc vào thời gian tồn tại còn lại của chúng, khá ngắn) và điều đó chỉ xảy ra đối với các hành động đăng xuất và các hành động đó làm mất hiệu lực mã thông báo, do đó, không phải mọi mã thông báo là lưu trữ ofc.
Frondor

2
Làm thế nào nó có thể rẻ? Trước hết, nếu bạn vẫn đang lưu trữ bất cứ thứ gì ở phía máy chủ, bạn sẽ không được hưởng lợi ích khả năng mở rộng quy mô, được JWT yêu cầu bởi vì vẫn còn một máy chủ danh sách đen trung tâm mà tất cả các máy chủ ứng dụng cần nói chuyện trước khi làm bất cứ điều gì. Nếu bạn chỉ cần lưu trữ danh sách đen 1k do hết hạn nhanh chóng, bạn có thể làm tương tự cho các phiên và do đó chỉ cần lưu trữ 1k phiên.
Franklin Yu

3
Tôi thích cách tiếp cận này. Bạn thực sự không phải kiểm tra danh sách đen theo từng yêu cầu, chỉ trên một yêu cầu xảy ra sau khi JWT hết hạn (mà bạn có thể đọc từ chính mã thông báo) và cho đến khoảng thời gian sau đó. Trong trường hợp sử dụng "tiêu chuẩn", điều đó sẽ xảy ra, nhiều nhất là một lần trong vòng đời của một mã thông báo nhất định. Sau khi được làm mới, bạn có thể từ chối mọi yêu cầu làm mới trong tương lai. Cảm ơn @Frondor
John Ackerman

7

Xin lỗi vì đã muộn một chút về điều này, nhưng có những mối quan tâm tương tự và bây giờ muốn đóng góp một cái gì đó trên cùng.

1) ndegges đã thêm một điểm tuyệt vời, rằng JWT không liên quan gì đến "bảo mật" và chỉ đơn giản là xác nhận, nếu bất kỳ ai đã nhầm lẫn với tải trọng hay không (ký); ssl giúp ngăn chặn vi phạm.

2) Bây giờ, nếu ssl cũng bị xâm phạm bằng cách nào đó, bất kỳ kẻ nghe trộm nào cũng có thể đánh cắp mã thông báo mang của chúng tôi (JWT) và mạo danh người dùng chính hãng, bước tiếp theo có thể được thực hiện là tìm kiếm "bằng chứng sở hữu" JWT từ khách hàng .

3) Bây giờ, với cách tiếp cận này, người trình bày của JWT có một khóa Proof-Of-Sở hữu (POP) cụ thể, người nhận có thể xác nhận bằng mật mã liệu yêu cầu đó có phải từ cùng một người dùng xác thực hay không.

Tôi đã giới thiệu bài viết Proof of Possesion cho điều này và bị thuyết phục với apporach.

Tôi sẽ rất vui mừng, nếu có thể đóng góp bất cứ điều gì.

Chúc mừng (y)


0

Chúng tôi không thể thêm ip của máy chủ ban đầu đã yêu cầu tạo mã thông báo JWT này như một phần của khiếu nại? Bây giờ khi JWT bị đánh cắp và được sử dụng từ một máy khác, khi máy chủ xác thực mã thông báo này, chúng tôi có thể xác minh xem ip máy được yêu cầu có khớp với một bộ như một phần của yêu cầu không. Điều này sẽ không phù hợp và do đó mã thông báo có thể bị từ chối. Ngoài ra, nếu người dùng cố gắng thao tác mã thông báo bằng cách đặt ip của riêng mình thành mã thông báo, mã thông báo sẽ bị từ chối khi mã thông báo bị thay đổi.


Đó là một giải pháp khả thi nhưng đối với các khách hàng đứng sau tường lửa, địa chỉ IP điển hình sẽ được chọn từ nhóm địa chỉ và có thể thay đổi bất cứ lúc nào.
SpeedOfSpin
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.