SecLab
Logging, Error Handling & ResponseconceptĐộ khó 2/520 phút

Ghi log gì, và tuyệt đối không ghi gì

Mục tiêu: Sau bài này bạn nói được, cho một sự kiện bất kỳ, những trường nào phải có trong log và trường nào không được có.

V16A09:2025info-disclosure
Bước 1 / 4 · read6 phút

Log tồn tại để trả lời câu hỏi lúc 2 giờ sáng

Câu hỏi để quyết định ghi log gì không phải "cái này có hữu ích không" mà "lúc 2 giờ sáng, khi có một sự cố, tôi cần trả lời câu hỏi gì?"

Ba câu hỏi đó, và chúng quyết định trường nào phải có:

Câu hỏi lúc 2 giờ sángTrường bắt buộc
Ai làm việc này?userId (định danh nội bộ, không phải email), sessionId, IP nguồn
Họ làm gì, với cái gì?Tên hành động, loại và id của đối tượng, kết quả (thành công/thất bại)
Khi nào, và trong ngữ cảnh nào?Timestamp có timezone, traceId để nối các dịch vụ

traceId là trường hay bị bỏ và là trường giá trị nhất trong một kiến trúc nhiều dịch vụ: không có nó thì "một request thất bại" là ba dòng log ở ba dịch vụ mà bạn không nối được với nhau.

Sự kiện bảo mật phải ghi log, và đây là danh sách của ASVS V16 gọn lại:

  • Đăng nhập thành công thất bại (thất bại quan trọng hơn)
  • Đổi mật khẩu, đổi email, bật/tắt MFA
  • Đổi quyền hoặc vai của bất kỳ ai
  • Truy cập bị từ chối — đây là dòng log duy nhất phát hiện được một cuộc dò
  • Đọc hoặc export dữ liệu nhạy cảm với số lượng bất thường
  • Mọi hành động của admin trên dữ liệu của người dùng khác

Dòng thứ tư đáng nhấn: log truy cập bị từ chối là log có giá trị phát hiện cao nhất. Một người dùng nhận 200 lần 403 trong một phút là một tín hiệu rõ ràng; không ghi nó thì bài m2-challenge không phát hiện được gì.

Và danh sách không bao giờ được ghi:

Không ghiVì sao

Mật khẩu, kể cả khi sai | Người dùng gõ sai mật khẩu của một site khác vào đây | Token, session id, API key, refresh token | Log là credential store nếu bạn ghi chúng | Số thẻ, CVV, dữ liệu sức khoẻ, số CMND | Nghĩa vụ pháp lý, và log lưu 90 ngày với nhiều người đọc | Toàn bộ request body | Nó chứa mọi thứ ở trên mà bạn không kiểm soát được |

Hàng cuối là hàng gây ra nhiều sự cố nhất, vì nó được thêm vào để debug và nó nhìn vô hại: _logger.LogDebug("request: {Body}", body). Nó ghi mọi mật khẩu, mọi token, mọi số thẻ đi qua endpoint đó, và nó ở lại vì LogDebug "không chạy ở production" — cho tới ngày ai đó đổi log level để điều tra một sự cố.

Xem lộ trình

Bình luận

Tham gia thảo luận
Đăng ký để bình luận

Bình luận cần tài khoản đã hoàn thành ít nhất một bài học. Điều kiện đó là thứ giữ cho luồng thảo luận này còn đáng đọc: mỗi ý kiến gắn với một người có thể bị hỏi lại, và reputation tích luỹ theo thời gian.

Đăng kýĐăng nhập

Bạn vẫn đọc được toàn bộ bình luận dưới đây mà không cần tài khoản. Đăng nhập xong bạn sẽ quay lại đúng chỗ này, không phải đầu trang.

Đang tải bình luận…