Ở bài JWT & Token Authentication, ta đã biết JWT được sử dụng để xác thực user sau khi đăng nhập:

Login
  ↓
Server xác thực username/password
  ↓
Access Token + Refresh Token
  ↓
Client lưu token
  ↓
Gửi Access Token trong mỗi request

Ví dụ:

GET /api/profile
Authorization: Bearer <access-token>

Server nhận token, verify token rồi xác định user đang thực hiện request.

Từ đây có một câu hỏi rất quan trọng về security Nếu attacker lấy được JWT thì họ có thể sửa Payload, ví dụ đổi userId từ 10 thành 20 để giả làm user khác không?

Để hiểu điều này, cần hiểu rõ Payload và Signature hoạt động như thế nào.

1. JWT gồm những gì?

như bài trước jwt gồm 3 phần header .payload .signature

Ví dụ:

eyJhbGciOiJIUzI1NiJ9 (header)
.
eyJ1c2VyX2lkIjoxMCwiZXhwIjoxNzk5OTk5OTk5fQ (payload)
.
abc123... (signature)

Ba phần này có vai trò khác nhau:

Header
→ JWT sử dụng thuật toán nào

Payload
→ chứa các claims như userId, role, exp...

Signature
→ dùng để kiểm tra token có bị thay đổi hay không

Ví dụ Payload có thể là:

{
    "userId": 10,
    "role": "user",
    "exp": 1799999999
}

2. Payload của JWT có được mã hóa không?

Thông thường, JWT không encrypt Payload Payload thường chỉ được encode. Điều này có nghĩa là nếu attacker có JWT, họ có thể decode Payload để xem nội dung.

Ví dụ:

{
    "userId": 10,
    "role": "user"
}

Hacker có thể biết:

userId = 10
role = user

Nhưng việc Có thể đọc Payload không có nghĩa là có thể sửa Payload rồi tạo ra một JWT hợp lệ.

Đây là điểm quan trọng nhất của phần này.

3. Hacker có thể sửa userId không?

Về mặt kỹ thuật, attacker có thể thay đổi phần Payload.

Ví dụ token ban đầu:

{
    "userId": 10,
    "role": "user"
}

Hacker sửa thành:

{
    "userId": 20,
    "role": "user"
}

hoặc thâm chí có thể sửa cả role

{
    "userId": 20,
    "role": "admin"
}
tuy nhiên payload có thể sửa nhưng phần quan trọng của jwt nằm ở phần signature.

4. Signature dùng để làm gì?

Khi server tạo JWT, server sẽ tạo Signature dựa trên Header + Payload và secret/private key.

Có thể hình dung:

Header + Payload
       +
    Secret Key
       ↓
    Signature

Ví dụ ban đầu:

Payload:

{
    "userId": 10,
    "role": "user"
}

Server tạo:

Signature A

Sau đó JWT trở thành:

Header.Payload.Signature-A

Khi client gửi JWT trở lại server, server sẽ verify Signature.

Nếu Hacker đổi phần payload thì signature sẽ báo sai ngay vì không khớp với cái payload ban đầu đã băm ra.

Giả sử JWT ban đầu:

{
    "userId": 10,
    "role": "user"
}

và có:

Signature A

Attacker sửa Payload:

{
    "userId": 20,
    "role": "user"
}

nhưng vẫn giữ Signature A.

Token lúc này về mặt nội dung là:

Header.Payload-mới.Signature-A

Server sẽ tính lại Signature dựa trên Payload mới:

Header + Payload-mới
        +
    Secret Key
        ↓
    Signature B

Kết quả:

Signature A ≠ Signature B

5. Tại sao attacker không tạo Signature mới?

đúng vậy, tại sao về kỹ thuật có thể đổi payload thì sao không đổi cái singnature cho khớp.

Hacker có thể biết:

Header
Payload

nhưng không có:

Secret Key

đây mới là cái quan trọng Secret Key.

Nếu server sử dụng một secret để ký JWT:

JWT_SECRET = ...

thì chỉ server mới có secret đó.

Muốn tạo Signature hợp lệ cho Payload mới, hacker cần có key tương ứng.

Có thể hình dung:

Hacker

Header
   +
Payload mới
   ↓
??? Signature

Không có secret/private key:

→ Không tạo được Signature hợp lệ

Vì vậy hacker có thể sửa Payload, nhưng không thể biến Payload đã sửa thành một JWT hợp lệ nếu không có key cần thiết để tạo Signature.

6. Nhưng JWT vẫn có thể bị khai thác nếu server triển khai sai

JWT có Signature không có nghĩa là application tự động an toàn.

Server vẫn có thể mắc lỗi.

Ví dụ nguy hiểm nhất là không verify Signature đúng cách.

Nếu application làm:

JWT
 ↓
Decode Payload
 ↓
Lấy userId
 ↓
Tin luôn

thì hacker có thể thay đổi Payload mà server không phát hiện.

Một lỗi khác là:

Secret Key bị lộ

Nếu hacker có được secret/private key dùng để ký token, họ có thể tạo token mới với claims khác rồi ký token đó.

Ví dụ về mặt khái niệm:

{
    "userId": 20,
    "role": "admin"
}

Sau đó tạo Signature hợp lệ bằng key bị lộ.

Server sẽ thấy:

Signature hợp lệ

và nếu application tin các claims đó, attacker có thể đạt được quyền không được phép.

Vì vậy JWT Secret hoặc private key phải được bảo vệ như một credential cực kỳ nhạy cảm Không commit vào Git repository, không đưa lên frontend và không log ra console. và các key nhạy cảm thì sẽ được đặc trong file .env riêng biệt để tránh push lên git.

Chốt lại:

JWT dùng Signature để đảm bảo Payload không bị thay đổi một cách âm thầm. Nếu hacker sửa Payload, Signature sẽ không còn khớp và token sẽ bị từ chối. Tuy nhiên, Signature không bảo vệ JWT khỏi việc bị đánh cắp. Nếu hacker lấy được một JWT hợp lệ, họ có thể sử dụng chính token đó cho đến khi token hết hạn hoặc bị hệ thống vô hiệu hóa. vì vậy để tránh tình trạng xấu xảy ra có kết hợp nhiều lớp bảo vệ sử dụng https để bảo vệ token truyền qua mạng vì HTTPS là URL đã được mã hóa an toàn. dùng access token có thời gian hiệu lực ngắn nhất có thể. bảo vệ refesh token cẩn thận luôn verify chữ ký (signature) và kiểm tra expiration. thực hiện authorization để đảm bảo user chỉ được sử dụng và truy cập các api hay tài nguyên phù hợp. luôn bảo vệ nghiêm ngặt scret key và thông tin nhạy cảm.

Bài viết khác

Test Types(Các loại kiểm thử phần mềm)

1. Lời mở đầu và vai trò định hình phạm vi của Test Types trong kiểm thử phần mềm: Trong quy trình phát triển và kiểm định chất lượng phần mềm, nếu như Testing Levels (Các cấp độ kiểm thử như Unit, Integration, System, Acceptance) giải quyết câu hỏi kiểm thử được thực hiện ở […]

PHP & Laravel Fundamentals

1. PHP là gì? PHP là ngôn ngữ lập trình phía server, thường dùng để xây dựng backend và web application. Flow cơ bản: Client ↓ HTTP Request PHP / Laravel ↓ Business Logic ↓ Database ↓ HTTP Response Laravel được xây dựng trên PHP, nên muốn học Laravel cần nắm những nền tảng PHP […]

JWT & Token Authentication

1. Token Authentication là gì? Token Authentication là cơ chế xác thực trong đó Client đăng nhập và nhận một Token từ Server. Sau đó, Client sử dụng Token này trong các request tiếp theo để chứng minh rằng request đã được xác thực. Thay vì gửi lại username/password cho mỗi request: Login ↓ Access […]

Series 1 — Web Fundamentals: DNS – Browser

Series 1 — Web Fundamentals   Internet → HTTP/HTTPS → DNS → Browser   Bài 3 :DNS & Domain   DNS & Domain – Làm thế nào Domain được chuyển thành IP? Ở hai bài trước, chúng ta đã tìm hiểu: Internet là gì? Client và Server là gì? IP Address là gì? HTTP/HTTPS dùng […]

Authentication & Authorization

1. Authentication & Authorization là gì? Hai khái niệm này thường đi cùng nhau nhưng khác nhau hoàn toàn. Authentication – Xác thực trả lời cho câu hỏi bạn là ai Ví dụ: Đăng nhập bằng: – Username + Password – Access Token – JWT – OAuth 2.0 Server xác định danh tính của User. […]

API Error Handling – Xử lý lỗi trong API

1. API Error Handling là gì? API Error Handling là cách API phát hiện, xử lý và trả về lỗi một cách nhất quán khi request không thể thực hiện thành công. Ví dụ: Client ↓ API ↓ Có lỗi? ├── Không → Success Response └── Có → Error Handling → Error Response mục tiêu […]

Leave a Reply

Your email address will not be published. Required fields are marked *