Tiếng Việt

JWT được giải mã chứng minh điều gì

Bộ giải mã JWT hiển thị cho bạn nội dung yêu cầu của mã thông báo. Nó không thể cho bạn thấy liệu những tuyên bố đó có đúng hay không. Hướng dẫn này đề cập đến ba phân đoạn là gì, việc giải mã nào thực hiện và không thiết lập cũng như các cuộc tấn công tồn tại trong khoảng trống giữa hai phân đoạn.

Ba phân đoạn, hai trong số đó chỉ là JSON

JWT ở dạng phổ biến là JWS: ba đoạn base64url được phân tách bằng dấu chấm. Đầu tiên là tiêu đề, thứ hai là tải trọng, thứ ba là chữ ký.

Tiêu đề và tải trọng là các đối tượng JSON thông thường đã được mã hóa base64url. Đã mã hóa, không được mã hóa. Bất kỳ ai nắm giữ mã thông báo đều có thể đọc cả hai ngay lập tức mà không cần phím - đó không phải là sai sót, đó là do thiết kế. JWT là một bản tuyên bố có chữ ký chứ không phải một phong bì dán kín. Chữ ký đảm bảo rằng tuyên bố không bị thay đổi; nó không làm gì để giữ nó riêng tư.

Hậu quả đáng được nêu rõ vì nó thường xuyên bị bỏ qua: không bao giờ đặt bất kỳ điều gì bí mật vào trọng tải JWT. Không phải mật khẩu, không phải mã định danh quốc gia đầy đủ, không phải thông tin chi tiết về hệ thống nội bộ. Giả sử tải trọng là công khai vì đối với bất kỳ ai có mã thông báo thì nó là như vậy.

Phân đoạn thứ ba là chữ ký, được tính toán trên hai phân đoạn đầu tiên. Đây là phần duy nhất mang bất kỳ giá trị bảo mật nào và là phần mà bộ giải mã không thể đánh giá được.

Giải mã chứng minh điều gì: không có gì

Đây là điểm của toàn bộ hướng dẫn. Giải mã JWT phân tích hai chuỗi base64url thành JSON. Nó xác nhận rằng mã thông báo được định dạng tốt. Nó không xác nhận rằng mã thông báo là chính hãng, nó được phát hành bởi bên có tên trong khiếu nại "iss", rằng các khiếu nại đó chưa được chỉnh sửa hoặc nó đã từng hợp lệ.

Bất kỳ ai cũng có thể tạo mã thông báo. Lấy bất kỳ JWT nào, thay đổi "role": "user" thành "role": "admin", mã hóa lại trọng tải, ghim bất kỳ chữ ký nào ở cuối và bộ giải mã sẽ hiển thị các xác nhận quyền sở hữu đã chỉnh sửa của bạn một cách chính xác như hiển thị bản gốc. Không có cách nào để biết sự khác biệt, bởi vì việc kiểm tra sự khác biệt là một thao tác khác yêu cầu khóa mà bộ giải mã không có.

Vì vậy, khi bộ giải mã — cái này hoặc bất kỳ cái nào khác — hiển thị cho bạn "exp: 2026-01-01", điều nó thực sự cho bạn biết là: mã thông báo này chứa xác nhận rằng nó sẽ hết hạn vào ngày đó. Tuyên bố đó có ý nghĩa gì hay không hoàn toàn phụ thuộc vào việc chữ ký có hợp lệ hay không và chưa được kiểm tra.

Công cụ này chỉ giải mã và ghi như vậy trên trang, bên cạnh kết quả, mọi lúc. Không có trong chú thích cuối trang. Lý do là một bộ giải mã giữ im lặng về điều này đang huấn luyện người dùng đọc dữ liệu chưa được xác minh như thể nó đã được xác minh và thói quen đó là gốc rễ của cả một nhóm lỗi xác thực.

Tại sao công cụ này không cung cấp xác minh

Việc xác minh cần ba thứ mà một trang web không thể có: khóa của nhà phát hành, thuật toán được ghim trước và chính sách về những gì cần từ chối.

Điều quan trọng là vấn đề rõ ràng. Đối với thuật toán HMAC (HS256 và bạn bè), khóa là bí mật chung — bí mật tương tự được sử dụng để tạo mã thông báo. Dán nó vào trang web có nghĩa là dán thông tin xác thực có thể tạo mã thông báo hợp lệ vào trang web. Đối với RSA và ECDSA khóa chung không phải là bí mật nhưng bạn vẫn cần tìm nạp khóa đúng từ điểm cuối JWKS phù hợp và tin tưởng rằng bạn đã có.

Thuật toán là một vấn đề phức tạp và là nguồn gốc của hai cuộc tấn công nổi tiếng. Đầu tiên là alg: "none": tiêu đề xác nhận mã thông báo chưa được ký và trình xác minh tôn trọng tiêu đề thay vì cấu hình của chính nó sẽ chấp nhận mọi thứ. Thứ hai là nhầm lẫn RS256-to-HS256: kẻ tấn công lấy khóa chung — theo định nghĩa là khóa công khai — thay đổi tiêu đề thành HS256 và ký mã thông báo bằng khóa chung đó làm bí mật HMAC. Trình xác minh đọc thuật toán từ mã thông báo và tra cứu "khóa" sẽ xác thực thuật toán đó.

Cả hai cuộc tấn công đều xuất phát từ cùng một lỗi: để mã thông báo cho người xác minh biết cách kiểm tra mã thông báo. Trình xác minh chính xác sẽ bỏ qua thuật toán của tiêu đề và sử dụng thuật toán được định cấu hình. Đó là quyết định thuộc về hệ thống tin cậy mã thông báo - không thuộc về một công cụ tiện lợi và không thuộc về bất kỳ ai đã dán nội dung nào đó vào biểu mẫu.

Tại sao không dán mã thông báo sản xuất ở bất cứ đâu

Mã thông báo truy cập là thông tin xác thực mang. Đó là ý nghĩa của "người mang" trong tiêu đề Ủy quyền: người mang nó là bạn. Không có yếu tố thứ hai và thường không có cách nào để phân biệt mã thông báo bị đánh cắp với mã thông báo hợp pháp. Cho đến khi hết hạn, nó sẽ là chìa khóa hoạt động cho tài khoản của bạn.

Vì vậy, việc dán mã thông báo trực tiếp vào bất kỳ trang web nào cũng đồng nghĩa với việc cấp thông tin xác thực cho trang đó. Công cụ này giải mã mọi thứ cục bộ và không đưa ra yêu cầu mạng nào sau khi tải trang - bạn có thể xác nhận điều đó trong bảng điều khiển mạng của trình duyệt và bạn nên làm như vậy vì quá trình này mất 10 giây. Nhưng hãy chú ý xem lập luận đó thực sự là gì: một tuyên bố trên một trang web rằng trang web đó đáng tin cậy. Mọi trang web lọc mã thông báo đều đưa ra xác nhận chính xác giống nhau và khách truy cập không thể nhận ra sự khác biệt trong nháy mắt.

Thói quen an toàn không phụ thuộc vào việc đánh giá chính xác các địa điểm. Sử dụng mã thông báo đã hết hạn, mã thông báo môi trường thử nghiệm hoặc mã thông báo bạn đã tạo ra cho mục đích này. Nếu bạn đã dán mã thông báo sản xuất ở đâu đó — ở bất kỳ đâu — hãy xoay nó. Việc thu hồi là rẻ; một sự cố thì không.

Điều tương tự cũng áp dụng với lực mạnh hơn để ký các phím. Không có lý do chính đáng nào để nhập bí mật HMAC hoặc khóa riêng tư vào một trang web và bất kỳ trang web nào yêu cầu một trang web "xác minh" mã thông báo của bạn đều yêu cầu khả năng giả mạo mã thông báo. Đó là lý do cụ thể khiến công cụ này không có tính năng xác minh: tính năng này yêu cầu yêu cầu.

Đọc những tuyên bố quan trọng

RFC 7519 đăng ký một nhóm nhỏ tên xác nhận quyền sở hữu. "iss" là nhà phát hành, "phụ" chủ đề mà mã thông báo nói đến, "kiểm tra" đối tượng dự định, "exp" hết hạn, "nbf" thời gian hợp lệ sớm nhất, "iat" thời gian phát hành và "jti" id duy nhất để phát hiện phát lại. Mọi thứ khác đều dành riêng cho ứng dụng.

Xác nhận quyền sở hữu thời gian là các giá trị NumericDate: giây kể từ kỷ nguyên Unix, không phải mili giây. Điều này khiến mọi người liên tục bối rối vì hầu hết các giá trị thời gian JavaScript đều là mili giây. Mã thông báo có vẻ hết hạn sau 1970 thường được cấp giá trị mili giây; một cái dường như hết hạn vào năm 55000 thường có giá trị thứ hai nhân với 1000 ở đâu đó.

"aud" xứng đáng được chú ý đặc biệt khi bạn gỡ lỗi. Mã thông báo hoàn toàn hợp lệ vẫn có thể là mã thông báo sai vì nó được phát hành cho đối tượng khác. Người xác minh kiểm tra chữ ký nhưng không phải đối tượng sẽ chấp nhận hoàn toàn mã thông báo được tạo cho một dịch vụ khác - đây là đường dẫn leo thang đặc quyền thực sự trong các hệ thống dùng chung nhà cung cấp danh tính.

Công cụ này hiển thị các xác nhận thời gian trong UTC, đánh dấu mã thông báo đã hết hạn là đã hết hạn và ghép nối với lời nhắc rằng xác nhận quyền sở hữu hết hạn chỉ có ý nghĩa gì đó nếu chữ ký hợp lệ. Lời nhắc ở đó vì "nó nói là nó chưa hết hạn" là thời điểm chính xác mà thói quen sử dụng dữ liệu chưa được xác minh gây ra thiệt hại.

Một danh sách kiểm tra ngắn dành cho hệ thống thực hiện việc tin cậy

Nếu bạn đang viết mã chấp nhận mã thông báo thay vì chỉ kiểm tra mã thông báo thì sau đây là phiên bản ngắn gọn về công việc của người xác minh chính xác.

  1. Trước tiên, hãy xác minh chữ ký bằng khóa bạn lấy được ngoài băng tần trước khi đọc bất kỳ khiếu nại nào.
  2. Ghim thuật toán trong cấu hình của riêng bạn. Không bao giờ đọc nó từ tiêu đề mã thông báo. Từ chối "không" một cách vô điều kiện.
  3. Kiểm tra "exp" và "nbf" theo đồng hồ đáng tin cậy, với dung sai sai lệch tối đa là nhỏ.
  4. Kiểm tra "iss" và "aud" với các giá trị bạn mong đợi. Chữ ký hợp lệ trên mã thông báo dành cho người khác vẫn là mã thông báo sai.
  5. Sử dụng thư viện đã được kiểm duyệt cho nền tảng của bạn thay vì tự lắp ráp nó. Mọi mục trong danh sách này đều có trong đó vì việc triển khai đã sai.
  6. Giữ thời gian tồn tại của mã thông báo ngắn và có đường dẫn thu hồi. Mã thông báo tồn tại trong thời gian ngắn sẽ hạn chế thiệt hại do rò rỉ mà bạn chưa nhận thấy.

Điều gì xảy ra với những gì bạn dán

  • Mọi chuyển đổi, băm, giải mã và tìm khác biệt đều chạy trong tab trình duyệt của bạn. Không có đầu vào nào được tải lên, ghi lại hoặc lưu trữ trên máy chủ vì không có máy chủ nào liên quan sau khi trang được tải.
  • Băm đến từ việc triển khai Web Crypto của chính trình duyệt và UUID từ trình tạo ngẫu nhiên được bảo mật bằng mật mã của nó. Không liên quan đến cuộc gọi mạng.
  • Không có nội dung nào bạn nhập được ghi vào bộ nhớ cục bộ hoặc cookie. Tải lại trang sẽ loại bỏ nó; đóng tab sẽ loại bỏ nó.
  • Phân tích trên toàn trang web chỉ chạy trên máy chủ sản xuất chuẩn đã được định cấu hình và được tiết lộ trong Chính sách quyền riêng tư; máy chủ cục bộ và bản xem trước từ chối nó. Các giá trị, mã thông báo, URL và nội dung tệp đã dán sẽ bị loại trừ khỏi các sự kiện phân tích của chính ToolAcre. Quảng cáo bị vô hiệu hóa trong cấu hình hiện tại.
  • Điều đó cho biết: khóa JWT hoặc API là thông tin xác thực trực tiếp. Thói quen an toàn là không bao giờ dán nội dung này vào trang web mà bạn không viết, cho dù những tuyên bố của trang đó có đáng tin cậy đến đâu đi nữa - bao gồm cả trang này.

Câu hỏi

Công cụ này có xác minh chữ ký không?

Không, và nó sẽ không bao giờ như vậy. Nó giải mã tiêu đề và tải trọng và cho bạn thấy chúng chứa gì. Nó không kiểm tra chữ ký, vì vậy không có gì nó hiển thị chứng minh mã thông báo là xác thực, không bị thay đổi hoặc được phát hành bởi bất kỳ ai mà nó đặt tên.

Vậy thì làm sao tôi biết mã thông báo là chính hãng?

Bằng cách xác minh chữ ký bằng khóa của nhà phát hành, sử dụng thư viện đã được kiểm duyệt, với thuật toán được ghim trong cấu hình của riêng bạn thay vì đọc từ mã thông báo. Đó là công việc dành cho dịch vụ tin cậy mã thông báo, trong môi trường nắm giữ khóa một cách hợp pháp.

Mã thông báo của tôi có được gửi đi bất cứ đâu khi tôi giải mã nó ở đây không?

Không. Quá trình giải mã diễn ra trong tab trình duyệt của bạn bằng cách sử dụng JavaScript của chính trang đó và trang này không thực hiện yêu cầu mạng nào sau khi tải. Bạn có thể xác minh điều này trong bảng mạng của trình duyệt. Bạn vẫn không nên dán mã thông báo sản xuất vào các công cụ web như một thói quen, bởi vì thói quen đó phải phát huy tác dụng trên những trang web không trung thực về nó.

Tại sao mọi người có thể đọc tải trọng JWT của tôi?

Bởi vì tải trọng được mã hóa base64url, không được mã hóa. JWS là một tuyên bố đã được ký, không phải là một tuyên bố được niêm phong. Nếu bạn muốn nội dung không thể đọc được thì bạn cần JWE, định dạng mã thông báo được mã hóa — và khi đó bộ giải mã không thể hiển thị cho bạn bất kỳ nội dung nào nếu không có khóa.

Alg: "không" là gì?

Giá trị tiêu đề khai báo rằng mã thông báo chưa được ký. Nó tồn tại trong đặc tả dành cho các bối cảnh trong đó tính toàn vẹn được đảm bảo bằng các phương tiện khác và là một cái bẫy thường trực: trình xác minh tin tưởng vào thuật toán của tiêu đề sẽ chấp nhận bất kỳ mã thông báo nào xác nhận "không có". Công cụ này gắn cờ nó bất cứ khi nào nó xuất hiện.

Mã thông báo của tôi có năm phân đoạn và sẽ không giải mã được. Tại sao?

Năm phân đoạn có nghĩa là JWE — mã thông báo được mã hóa — thay vì JWS đã ký. Không thể đọc được nội dung của nó nếu không có khóa giải mã, vì vậy thực sự không có gì để bộ giải mã hiển thị. Công cụ này xác định trường hợp đó một cách rõ ràng thay vì báo cáo lỗi phân tích cú pháp mơ hồ.

Ngày hết hạn có vẻ sai theo hệ số 1000.

JWT yêu cầu thời gian là NumericDate: giây kể từ kỷ nguyên, không phải mili giây. Giá trị được tạo bởi Date.now() quá lớn gấp nghìn lần. Tiện ích dấu thời gian trong bộ công cụ này chuyển đổi giữa hai tiện ích này và luôn cho bạn biết nó đã sử dụng đơn vị nào.

Có an toàn khi lưu trữ JWT trong localStorage không?

Đó là một sự đánh đổi, không phải là có hay không. localStorage có thể đọc được bởi bất kỳ JavaScript nào chạy trên nguồn gốc của bạn, do đó, một lỗ hổng XSS sẽ làm mất mã thông báo. JavaScript không thể đọc cookie httpOnly nhưng cần được bảo vệ CSRF. Tóm tắt trung thực là cả hai đều không miễn phí và quyết định thuộc về mô hình mối đe dọa của ứng dụng của bạn.

Hạn chế

  • Công cụ này chỉ giải mã. Nó không xác minh chữ ký và đó là một quyết định thiết kế vĩnh viễn chứ không phải là một tính năng bị thiếu - hãy xem hướng dẫn ở trên để biết lý do.
  • Mã thông báo được mã hóa (JWE, năm phân đoạn) hoàn toàn không thể được giải mã nếu không có khóa. Công cụ xác định chúng và dừng lại.
  • JWT lồng nhau — một mã thông báo có tải trọng chính là mã thông báo — không được tự động mở gói. Giải mã mã thông báo bên trong thành một bước riêng biệt.
  • Ý nghĩa của xác nhận quyền sở hữu ngoài tập hợp đã đăng ký được xác định trong RFC 7519 là dành riêng cho ứng dụng nên công cụ này hiển thị các giá trị của chúng mà không diễn giải chúng.
  • Thời hạn sử dụng được hiển thị ở đây chỉ phản ánh những gì mã thông báo tuyên bố về chính nó. Tuyên bố đó có ý nghĩa hay không phụ thuộc vào chữ ký mà công cụ này không kiểm tra.
  • Tokens larger than 200,000 characters are refused. Bất kỳ JWT thực nào đều có cấp độ lớn nhỏ hơn.