TOTP là lớp xác thực thứ hai phổ biến vì hoạt động ngoại tuyến, tương thích với nhiều ứng dụng và không phụ thuộc nhà mạng. Tuy nhiên, một ô nhập sáu chữ số chưa tự động tạo ra hệ thống MFA an toàn. Chất lượng triển khai còn phụ thuộc vào cách sinh và giữ secret, cửa sổ thời gian, chống thử mã, chống phát lại, quy trình recovery và cách xử lý phishing.
Bài viết này đi từ thuật toán trong RFC 6238 đến checklist vận hành thực tế. Mục tiêu không phải tự viết mật mã, mà là hiểu các thuộc tính để cấu hình thư viện đúng và biết giới hạn của TOTP.
1. TOTP là gì?
TOTP, viết tắt của Time-Based One-Time Password, là biến thể theo thời gian của HOTP. Thiết bị xác thực và máy chủ cùng giữ một secret K. Cả hai chuyển thời gian hiện tại thành một bộ đếm T, sau đó dùng HOTP để tạo cùng một mã ngắn.
T = floor((unix_time - T0) / X)
TOTP = HOTP(K, T)
Theo RFC 6238, giá trị mặc định thường dùng là T0 = 0 và bước thời gian X = 30 giây. RFC yêu cầu hai phía dùng cùng secret, cùng bước thời gian và có nguồn thời gian Unix đủ đồng bộ. Thuật toán có thể dùng HMAC-SHA-1, HMAC-SHA-256 hoặc HMAC-SHA-512 nếu hai phía thống nhất.
2. Một lần đăng nhập diễn ra ra sao?
- Trong lúc kích hoạt MFA, máy chủ tạo một secret ngẫu nhiên riêng cho tài khoản.
- Ứng dụng xác thực nhận secret, thường qua URI được biểu diễn thành QR.
- Mỗi khoảng thời gian, ứng dụng tính bộ đếm và hiển thị mã TOTP.
- Khi đăng nhập, máy chủ tính mã cho bước thời gian hiện tại và một số bước lân cận được cho phép.
- Nếu khớp, chưa từng dùng và tài khoản chưa bị rate limit, máy chủ chấp nhận yếu tố thứ hai.
Máy chủ không cần gọi điện thoại hay dịch vụ bên ngoài trong mỗi lần kiểm tra. Đó là ưu điểm về khả năng hoạt động, nhưng cũng có nghĩa máy chủ phải giữ vật liệu khóa đủ để tự tính TOTP.
3. Mã sáu chữ số không phải là secret chính
Mã hiển thị chỉ là đầu ra ngắn hạn. Secret K mới là tài sản dài hạn: ai sao chép được nó có thể tạo mã hợp lệ trong tương lai. QR kích hoạt cũng chứa hoặc dẫn tới secret, nên phải được xem như thông tin nhạy cảm.
- Sinh secret bằng bộ tạo số ngẫu nhiên mật mã; mỗi authenticator có secret riêng.
- Chỉ hiển thị QR trong phiên đã xác thực, qua HTTPS và tránh cache.
- Không ghi secret, QR URI hoặc mã OTP vào log, analytics, crash report hay ticket hỗ trợ.
- Mã hóa secret ở trạng thái lưu trữ, ưu tiên envelope encryption với KMS/HSM và phân quyền giải mã tối thiểu.
- Không băm secret như mật khẩu rồi bỏ bản gốc: verifier cần secret để tính mã kỳ vọng.
4. Cửa sổ thời gian: đủ dùng nhưng không quá rộng
Đồng hồ điện thoại và máy chủ có thể lệch, còn người dùng cần vài giây để nhập mã. Vì vậy verifier thường kiểm tra bước hiện tại cùng một phạm vi nhỏ trước/sau. Cửa sổ rộng cải thiện trải nghiệm nhưng làm tăng số mã hợp lệ tại cùng thời điểm và mở rộng bề mặt đoán mã.
Hãy bắt đầu với bước 30 giây và tolerance tối thiểu mà người dùng thực sự cần. Đồng bộ giờ máy chủ bằng dịch vụ thời gian đáng tin cậy; theo dõi clock drift. Không âm thầm mở cửa sổ lớn để che lỗi đồng hồ hoặc độ trễ bất thường.
5. Chống phát lại phải có trạng thái
Một mã TOTP còn hạn có thể bị gửi lại nhiều lần nếu verifier chỉ kiểm tra phép tính. NIST SP 800-63B yêu cầu verifier chỉ chấp nhận một OTP một lần trong thời gian hiệu lực. Cách triển khai phổ biến là lưu time-step cao nhất đã chấp nhận cho từng authenticator.
candidate_step = verify_in_allowed_window(code)
if candidate_step is null: reject
atomically:
if candidate_step <= last_accepted_step: reject
last_accepted_step = candidate_step
accept
Trong cụm nhiều server, phép so sánh và cập nhật phải nguyên tử trong datastore dùng chung. Nếu hai node cùng đọc trạng thái cũ rồi cùng ghi, một mã có thể được chấp nhận hai lần.
6. Rate limit là bắt buộc
Mã sáu chữ số chỉ có khoảng một triệu khả năng. Thời hạn ngắn không thay thế giới hạn thử. Rate limit nên kết hợp theo tài khoản, phiên đăng nhập và tín hiệu mạng; tăng delay hoặc khóa tạm thời sau nhiều lần sai, đồng thời tránh cho phép kẻ tấn công khóa vĩnh viễn tài khoản của nạn nhân.
- Giới hạn số lần thử trong một challenge và trong khoảng thời gian trượt.
- Hủy challenge sau khi thành công hoặc hết hạn.
- Không tiết lộ quá chi tiết “mật khẩu đúng nhưng OTP sai” cho luồng có nguy cơ dò tài khoản.
- Cảnh báo và quan sát spike thất bại theo tài khoản, IP, ASN hoặc thiết bị.
7. TOTP chống replay nhưng không chống phishing
Hai khái niệm này khác nhau. Mã chỉ dùng một lần có thể chống phát lại về sau, nhưng trang giả có thể lấy mã vừa nhập và chuyển tiếp ngay tới trang thật trước khi mã hết hạn. NIST SP 800-63B nêu rằng authenticator yêu cầu nhập OTP thủ công không được xem là chống phishing vì đầu ra không gắn với phiên hay tên miền đang xác thực.
TOTP là bước nâng cấp quan trọng so với chỉ dùng mật khẩu, nhưng không nên được mô tả là “phishing-proof”.
Với quản trị viên, tài chính, mã nguồn hoặc dữ liệu nhạy cảm, nên ưu tiên WebAuthn/passkey hay security key. Các phương thức này có thể ràng buộc xác thực với tên miền của verifier, khiến trang giả khó chuyển tiếp thông tin đăng nhập theo cách giống TOTP.
8. Kích hoạt MFA phải xác minh trọn vòng
Đừng đánh dấu MFA đã bật ngay sau khi render QR. Máy chủ nên giữ enrollment ở trạng thái chờ, yêu cầu người dùng nhập một mã hợp lệ, rồi mới kích hoạt. Điều này phát hiện QR chưa được quét, đồng hồ sai và cấu hình thuật toán không tương thích.
Khi thay authenticator, yêu cầu xác thực lại bằng yếu tố mạnh; thông báo qua kênh độc lập; thu hồi secret cũ sau khi chuyển đổi hoàn tất. Với thao tác nhạy cảm, không tin vô thời hạn vào phiên vừa đăng nhập từ lâu: hãy dùng step-up authentication.
9. Recovery thường là mắt xích yếu nhất
Nếu bộ phận hỗ trợ có thể tắt MFA chỉ bằng vài thông tin dễ đoán, kẻ tấn công sẽ bỏ qua thuật toán và tấn công quy trình. OWASP MFA Cheat Sheet khuyến nghị xây dựng quy trình reset MFA an toàn và xem recovery như một đường xác thực thực sự.
- Cấp recovery code ngẫu nhiên, dùng một lần; chỉ lưu dạng băm có salt.
- Hiển thị code một lần, cho phép tải/in an toàn và cho phép tạo lại sau khi xác thực mạnh.
- Thu hồi bộ code cũ khi tạo bộ mới; hiển thị lịch sử lần dùng và thời điểm đổi MFA.
- Áp dụng thời gian chờ hoặc phê duyệt bổ sung cho tài khoản đặc quyền.
- Gửi cảnh báo khi MFA bị thay đổi, recovery được dùng hoặc thiết bị mới được thêm.
10. Mô hình dữ liệu tối thiểu
| Trường | Mục đích | Lưu ý |
|---|---|---|
secret_ciphertext | Secret đã mã hóa | Không log; key mã hóa tách khỏi database |
algorithm, digits, period | Tham số tương thích | Không tự đổi sau enrollment |
last_accepted_step | Chống dùng lại mã | Cập nhật nguyên tử |
enabled_at | Trạng thái vòng đời | Chỉ đặt sau lần xác minh đầu |
recovery_codes | Khôi phục tài khoản | Băm riêng từng code, đánh dấu đã dùng |
key_version | Xoay khóa mã hóa | Cho phép rewrap có kiểm soát |
11. Những lỗi triển khai thường gặp
- Tự viết HOTP/TOTP thay vì dùng thư viện đã được kiểm thử và test vector RFC.
- Lưu secret dạng plaintext hoặc đưa secret vào log để debug.
- Chấp nhận cùng mã nhiều lần trong một time-step.
- Mở tolerance quá rộng và không rate limit.
- Cho đổi/tắt MFA chỉ với một phiên cũ hoặc email đang bị chiếm quyền.
- Không có recovery code, hoặc recovery dễ hơn đăng nhập bình thường.
- Gọi TOTP là chống phishing và bỏ qua phương thức cryptographic mạnh hơn.
- Không chuẩn hóa thời gian UTC, kiểu integer đủ lớn và kiểm thử mốc sau năm 2038.
12. Checklist kiểm thử và vận hành
- Chạy các test vector SHA-1, SHA-256 và SHA-512 trong RFC 6238.
- Kiểm thử trước/sau biên 30 giây và các mức clock drift được cho phép.
- Gửi đồng thời một mã tới nhiều node để xác nhận chỉ một request thành công.
- Kiểm thử rate limit, hết hạn challenge và đường đi khi datastore lỗi.
- Kiểm tra log, tracing, analytics và backup không làm lộ secret hay OTP.
- Diễn tập mất điện thoại, dùng recovery code, thay thiết bị và khóa tài khoản.
- Ghi audit event cho enrollment, disable, recovery và thay đổi secret, nhưng không ghi dữ liệu bí mật.
- Theo dõi tỷ lệ lỗi theo time-step để phát hiện clock drift hoặc rollout hỏng.
Khi nào nên chọn TOTP?
| Nhu cầu | Lựa chọn phù hợp |
|---|---|
| Cần MFA chuẩn mở, dễ triển khai, hoạt động ngoại tuyến | TOTP là lựa chọn thực dụng |
| Cần chống phishing cho tài khoản giá trị cao | Ưu tiên passkey/WebAuthn hoặc security key |
| Người dùng không có smartphone | Cân nhắc hardware token và quy trình cấp phát |
| Khôi phục tài khoản | Recovery code dùng một lần và quy trình xác minh mạnh |
Kết luận
TOTP đơn giản ở bề mặt nhưng đòi hỏi thiết kế vòng đời đầy đủ. Một triển khai tốt dùng secret ngẫu nhiên và mã hóa, cửa sổ thời gian hẹp, chống phát lại nguyên tử, rate limit, enrollment được xác minh và recovery không yếu hơn luồng chính. Quan trọng hơn, đội ngũ phải nói đúng giới hạn: TOTP nâng đáng kể chi phí tấn công so với mật khẩu đơn lẻ, nhưng mã nhập thủ công vẫn có thể bị phishing thời gian thực. Hãy coi TOTP là một bậc trong chiến lược MFA và ưu tiên WebAuthn khi threat model đòi hỏi khả năng chống phishing.




Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.