Ghi chú: Mục lục đầy đủ các ghi chú~ ps: Tôi là người mới bắt đầu, các ghi chú được tổng hợp dựa trên hiểu biết cá nhân, nếu có sai sót mong được chỉ bảo!
HTTPS & Xác thực danh tính
-
Giới thiệu: Bài viết trước chủ yếu giới thiệu cấu trúc và nội dung của gói dữ liệu Http, bài này sẽ thảo luận về các công nghệ như Https và xác thực danh tính.
-
Https
-
Tổng quan Vì gói Http được truyền dưới dạng văn bản thuần túy trên đường truyền, bất kỳ ai chặn được gói này đều có thể xem và sửa đổi nội dung. Điều này gây ra nhiều rủi ro bảo mật, như đánh cắp thông tin đăng nhập của nạn nhân, dẫn nạn nhân đến các trang web độc hại. Đây còn được gọi là tấn công trung gian (man-in-the-middle attack), và Https ra đời để giải quyết vấn đề này. Thông qua giao thức mã hóa TLS, Https đảm bảo dữ liệu không bị bên thứ ba đánh cắp và có thể xác thực danh tính của người dùng khi truy cập máy chủ.
-
Gói dữ liệu Https Dưới đây là minh họa các gói dữ liệu Http/Https được thu thập bằng WireShark.
-
Hỏi & Đáp Q1: Vì sao dữ liệu gói Https được mã hóa mà trình duyệt và các phần mềm capture vẫn có thể xem được nội dung thực? A1: Đây là dựa trên nguyên lý mã hóa TLS. Đơn giản, nội dung gói tin được mã hóa TLS, cả client và server khi nhận gói đều cần dùng chứng thư để giải mã mới được nội dung gốc. Trình duyệt của chúng ta đã cài sẵn chứng thư cần thiết, và các phần mềm capture cũng có chứng thư tích hợp sẵn. Q2: Vì sao nếu phần mềm capture đã có chứng thư để chặn và giải mã gói Https, chúng ta vẫn cần cài chứng thư của phần mềm capture vào máy? A2: Vì gói Https được phần mềm capture chuyển tiếp về máy local, chứng thư không chỉ có chức năng giải mã TLS mà còn xác thực server có hợp lệ không. Nếu không cài chứng thư capture, khi gói Https được chuyển tiếp về trình duyệt local, do không xác thực được chứng thư, trình duyệt sẽ cảnh báo an toàn và ngăn chặn giải mã. (Tất nhiên, nếu dùng trình duyệt đi kèm phần mềm capture thì không có vấn đề này, vì trình duyệt đó đã cài sẵn chứng thư phù hợp.)
-
Xác thực danh tính Giới thiệu: Https giải quyết vấn đề an toàn khi truyền dữ liệu giữa client và server, nhưng phía client vẫn tồn tại các vấn đề như truy cập vượt quyền, tài khoản mật khẩu người dùng bị brute-force, danh tính bị giả mạo. Vì vậy, công nghệ xác thực danh tính ra đời nhằm xác minh người dùng/hệ thống có hợp lệ khi truy cập tài nguyên nào đó. Dưới đây là giới thiệu các phương thức xác thực phổ biến.
-
Xác thực cơ bản của Http
-
Tổng quan: Kết hợp tài khoản & mật khẩu người dùng nhập vào và thực hiện mã hóa base64.
-
Quy trình xác thực
-
Yêu cầu một nội dung bị giới hạn.
-
Client nhập tài khoản & mật khẩu, tại phía client, tài khoản và mật khẩu được kết hợp và mã hóa base64.
-
Server nhận được, giải mã và xác minh tài khoản mật khẩu có chính xác không.
-
Tác động
-
Đối với người dùng: Mỗi khi truy cập nội dung bị giới hạn mới, dù có cùng domain hay không, đều phải nhập lại tài khoản & mật khẩu, rất bất tiện.
-
Đối với người kiểm tra an ninh: Tài khoản & mật khẩu tương đương với việc truyền văn bản thuần túy, các phương pháp kiểm tra thông thường vẫn hiệu quả, như brute-force, injection. Hiện nay gần như không còn phương thức xác thực này, chỉ được đề cập ở đây để tham khảo.
-
Session - Cookie
-
Tổng quan: Session - Cookie được phát triển để giải quyết vấn đề người dùng phải đăng nhập lại mỗi khi truy cập trang giới hạn mới.
-
Quy trình xác thực
-
Yêu cầu một nội dung bị giới hạn, client nhập tài khoản & mật khẩu.
-
Server nhận được, tạo Session dựa trên thông tin người dùng nhập vào và lưu trữ.
-
Lúc này, trong gói phản hồi của server, có trường Set-Cookie trong header, giá trị của nó là định danh duy nhất của Session vừa tạo.
-
Client nhận được, sẽ lưu giá trị của Set-Cookie (Session ID) vào Cookie của trình duyệt.
-
Khi client truy cập các trang khác nhau cùng site, gói yêu cầu sẽ mang theo Cookie.
-
Server nhận được, chỉ cần so sánh Session đã lưu với Session ID từ Cookie của client, qua đó xác định phiên làm việc có tồn tại không. Nếu có, server sẽ xác thực danh tính client dựa trên nội dung phiên, không cần client nhập lại tài khoản mật khẩu. Bổ sung: Chúng ta thường thấy Cookie gửi đến server có nhiều nội dung, vì ngoài chứa thông tin đăng nhập, Cookie còn chứa một số cài đặt cá nhân hoặc dữ liệu cần ghi nhớ khác.
-
Tác động
-
Đối với server: Server cần lưu trữ Session của mỗi user, và Session sẽ hết hạn (mặc định hết khi đóng trình duyệt, server cũng có thể tự định nghĩa thời gian hết hạn), server cần dọn dẹp Session hết hạn định kỳ, ảnh hưởng đến hiệu năng server.
-
Đối với người kiểm tra an ninh: Nếu Cookie của người dùng bị đánh cắp và Session trên server chưa hết hạn, kẻ tấn công có thể sử dụng Cookie đó để đăng nhập, giả mạo thao tác của người dùng, đây cũng là nguyên lý của tấn công XSS, CSRF. Bổ sung: Các cuộc tấn công dựa trên Session - Cookie thường là đánh cắp Cookie lưu trữ trên client, nhưng chúng ta biết thông tin xác thực thực sự chỉ là Session ID trong Cookie, vậy liệu Session ID có thể bị phá mã và giả mạo không? (emmm... câu hỏi từ người mới bắt đầu)
-
Token
-
Tổng quan: Cơ chế hoạt động & chức năng thực hiện, tương tự Session - Cookie, nhưng Token thường chứa đầy đủ thông tin xác thực danh tính người dùng.
-
Quy trình xác thực
-
Yêu cầu nội dung bị giới hạn, client nhập tài khoản & mật khẩu.
-
Server nhận được tài khoản mật khẩu, theo logic phía sau, tạo Token đã mã hóa và trả về cho client.
-
Client nhận Token và lưu vào trình duyệt. (Ngoài lưu vào Cookie, Token cũng có thể lưu vào localStorage, sessionStorage.)
-
Khi client yêu cầu lại nội dung bị giới hạn, gói yêu cầu sẽ mang theo Token.
-
Server nhận và xác minh Token có hợp lệ không, từ đó xác thực danh tính.
-
Tác động
-
Đối với server: Vì Token đã chứa đầy đủ thông tin người dùng, so với Session - Cookie, server không cần lưu trữ phiên làm việc của mỗi user, Token thì không cần lưu trữ, server chỉ cần nhận và xác minh. Tiết kiệm hiệu năng server.
-
Đối với người kiểm tra an ninh: Token thường được đặt thời gian hết hạn, thường thời gian này ngắn. So với Session - Cookie, an toàn hơn.
-
JWT
-
Tổng quan: Viết tắt của JSON Web Token, như tên gọi, JWT cũng là một dạng xác thực bằng Token.
-
Quy trình xác thực: Tương tự Token.
-
Đặc điểm JWT có những đặc điểm rõ ràng, nên ở đây sẽ thảo luận thêm. Cấu trúc JWT: Header . Payload . Signature (đầu . tải . chữ ký) Header: Lưu trữ thông tin cơ bản của JWT, như loại Token, thuật toán ký tên, và được mã hóa base64. Dưới đây là ví dụ từ chính thức:
// Header sau khi mã hóa base64
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
// Giải mã ra
{
"alg": "HS256",// thuật toán ký tên jwt
"typ": "JWT"// loại token
}
Payload: Lưu trữ thông tin hợp lệ của JWT & người dùng, như thời gian hết hạn của JWT, id người dùng, tên người dùng, và được mã hóa base64. Cũng là ví dụ từ chính thức:
// Payload sau khi mã hóa base64
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
// Giải mã ra
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
// Chúng ta gọi: sub, name, iat... là các claims
// Trong đó sub, iat là claims đăng ký của JWT, mỗi claim đăng ký đều có ý nghĩa riêng.
Dưới đây là bảng các claims đăng ký của JWT
| Tên trường | Ý nghĩa |
|---|---|
| **iss** | Người cấp phát (Issuer), cho biết nhà tạo ra JWT hoặc dịch vụ cấp phát. |
| **sub** | Chủ đề (Subject), cho biết đối tượng của JWT, thường là định danh duy nhất của người dùng. |
| **aud** | Đối tượng (Audience), cho biết người nhận JWT, thường là định danh của ứng dụng. |
| **exp** | Thời gian hết hạn (Expiration Time), cho biết thời điểm hết hạn của Token, là timestamp theo giây. |
| **nbf** | Thời điểm có hiệu lực (Not Before), cho biết thời điểm JWT bắt đầu có hiệu lực. Trước thời điểm này, JWT không hợp lệ. |
| **iat** | Thời điểm cấp phát (Issued At), cho biết thời điểm JWT được tạo ra. |
| **jti** | ID JWT, định danh duy nhất của Token, thường dùng để tránh sử dụng lại Token (ngăn chặn tấn công replay). |
Signature: Xác tính toàn vẹn của JWT, cách tính Signature:
Thuật toán mã hóa trong Header(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secrect// khóa bí mật
)
// Ví dụ Signature chính thức
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Kết hợp ba phần này bằng "." ta có JWT hoàn chỉnh
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Hiểu được cấu trúc này, ta có thể nhận biết đặc điểm của JWT: eyJxxxxxx.eyJxxxxxx.signature. 4. Tác động
-
Đối với server: Tương tự Token.
-
Đối với người kiểm tra an ninh: Vì hai phần đầu của JWT chỉ được mã hóa base64, nên khi thuật toán và khóa bí mật của JWT bị lấy cắp & brute-force, kẻ tấn công có thể giả mạo JWT.
-
OAuth
-
Tổng quan: OAuth là một framework cho phép ủy quyền, cho phép người dùng ủy quyền ứng dụng thứ ba truy cập tài nguyên được bảo hộ trên nhà cung cấp dịch vụ khác mà không cần tiết lộ thông tin xác thực của họ. Đơn giản nói, sử dụng OAuth, người dùng có thể cho phép ứng dụng thứ ba truy cập một phần tài nguyên mà không cần tiết lộ tài khoản mật khẩu cho ứng dụng đó. Ví dụ: Sử dụng tài khoản QQ để đăng nhập vào Baidu, sau khi thực hiện thao tác ủy quyền, Baidu không cần lấy được tài khoản & mật khẩu QQ nhưng vẫn 1. Thực hiện được đăng nhập. 2. Tạo tài khoản Baidu dựa trên thông tin tài khoản QQ nhận được.
-
Quy trình ủy quyền Lưu ý: Vì tiêu chuẩn OAuth2.0 định nghĩa 4 phương thức ủy quyền, lần lượt là: authorization code, implicit, password credentials và client credentials. Trong đó, phương thức authorization code được sử dụng nhiều nhất hiện nay, nên bài này chỉ giới thiệu quy trình ủy quyền sử dụng phương thức authorization code, nếu muốn tìm hiểu các phương thức khác có thể tham khảo: https://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html
-
Trong quy trình OAuth ủy quyền có 3 vai trò: client mà người dùng thuộc về, ứng dụng thứ ba mà người dùng truy cập, và server tài nguyên mà ứng dụng thứ ba cần yêu cầu (trong server này lại tồn tại dịch vụ ủy quyền và dịch vụ tài nguyên).
-
Khi ứng dụng thứ ba mà client truy cập muốn lấy tài nguyên từ server, cần trước tiên đăng ký với server dịch vụ ủy quyền để nhận được client_id & client_secrect.
-
Sau đó, client cần thay mặt ứng dụng thứ ba yêu cầu mã ủy quyền từ server dịch vụ ủy quyền, nếu thành công, server dịch vụ ủy quyền sẽ chuyển mã ủy quyền cho ứng dụng thứ ba.
# Yêu cầu mã ủy quyền
/oauth/authorize?client_id=xxxx&response_type=code&scope=read&redirect_uri=http://"ứng dụng thứ ba"
# Trong đó response_type thể hiện phương thức ủy quyền
# scope thể hiện phạm vi ủy quyền
# redirect_uri là địa chỉ chuyển hướng, thường là địa chỉ của ứng dụng thứ ba
# Yêu cầu mã ủy quyền thành công, sẽ trả về ứng dụng thứ ba qua redirect_uri
http://"ứng dụng thứ ba"/callback?code=mãủyquyền
# Trong đó giá trị code là mã ủy quyền
- Ứng dụng thứ ba nhận được mã ủy quyền, tiếp tục yêu cầu Token từ server dịch vụ ủy quyền, nếu thành công, server sẽ trả Token cho ứng dụng thứ ba. Vì Token chỉ truyền giữa ứng dụng thứ ba và server, không bị người dùng lấy cắp, nên an toàn hơn.
# Ứng dụng thứ ba yêu cầu Token từ server dịch vụ ủy quyền
/oauth/token?client_id=xxxx&client_secrect=xxxx&grant_type=mãủyquyền&code=mãủyquyền&redirect_uri=http://"ứng dụng thứ ba"/
# Trong đó grant_type là phương thức ủy quyền
# code là mã ủy quyền ứng dụng thứ ba nhận được
# Yêu cầu thành công, server dịch vụ ủy quyền sẽ trả Token cho ứng dụng thứ ba
-
Sau đó, ứng dụng thứ ba sử dụng Token để lấy tài nguyên từ server dịch vụ tài nguyên.
-
Tác động
-
Đối với server: Giải quyết vấn đề xác thực danh tính khi truy cập tài nguyên bị giới hạn.
-
Đối với người kiểm tra an ninh: Các vấn đề bảo mật liên quan đến framework OAuth sẽ được thảo luận ở bài sau, hiện tại chỉ cần có nhận thức cơ bản. (ps: Thực ra là tác giả chưa gặp nhiều)