Log & Monitoring: Phát hiện đăng nhập đáng ngờ trước khi quá muộn
Hướng dẫn security logging và monitoring để phát hiện brute force, credential stuffing và đăng nhập đáng ngờ bằng structured logs, Redis, SIEM và alerting.
ShanverseCập nhật 10 phút đọc— lượt xemĐang tải lượt xem
Monitoring
Authentication
Web Security
Bài toán: 5 lần nhập sai mật khẩu có ý nghĩa gì?
Một lần đăng nhập thất bại thường chỉ là người dùng gõ nhầm. Năm lần thất bại trong 10 phút có thể là password guessing. Một IP thử một mật khẩu trên 100 tài khoản lại giống password spraying. Hàng trăm IP cùng nhắm vào một tài khoản có thể là brute force phân tán. Đặc biệt, chuỗi nhiều lần thất bại rồi đăng nhập thành công cần được ưu tiên vì có thể là account takeover.
Vì vậy, “log đăng nhập sai” chưa đủ. Hệ thống phải trả lời được:
Ai hoặc tài khoản nào bị nhắm tới?
Nguồn nào tạo ra hành vi?
Hành vi xảy ra trong cửa sổ thời gian nào?
Đây là một lỗi đơn lẻ hay một pattern?
Sau các lần thất bại có thành công, đổi mật khẩu hay nâng quyền không?
Ai nhận cảnh báo và hành động gì tiếp theo?
Logging, monitoring và alerting khác nhau
Bình luận
Logging: ghi lại sự kiện có cấu trúc.
Collection: chuyển log từ app, proxy, identity provider và cloud về nơi tập trung.
Monitoring: liên tục đo, truy vấn và tương quan sự kiện.
Detection: áp dụng rule hoặc mô hình để nhận diện pattern đáng ngờ.
Alerting: chuyển detection đủ độ tin cậy thành thông báo có owner.
Response: xác minh, chặn, yêu cầu MFA, revoke session hoặc điều tra.
Nếu chỉ có file log trên server, cuộc tấn công có thể đã kết thúc trước khi có người mở file.
Những sự kiện bảo mật nên ghi lại
Tối thiểu hãy ghi:
Đăng nhập thành công và thất bại.
Account lock, unlock, password reset và account recovery.
MFA challenge, thành công, thất bại và thay đổi phương thức MFA.
Logout, revoke session, token validation failure và session bất thường.
Authorization failure, đặc biệt với admin API và dữ liệu nhạy cảm.
Input validation failure, request bị rate limit và webhook signature failure.
Thay đổi role, permission, secret, cấu hình bảo mật và thao tác quản trị.
Tạo/xóa API key, export dữ liệu lớn và thay đổi email/số điện thoại.
Hệ thống log khởi động, dừng hoặc ngừng gửi sự kiện.
Không phải mọi sự kiện đều cần alert. Nhưng thiếu event gốc thì không thể xây detection về sau.
Thiết kế structured security event
Dùng JSON với schema ổn định thay vì chuỗi như Login failed for user X. Một event hữu ích cần có:
timestamp: thời điểm UTC từ clock đã đồng bộ.
event_name và event_version: tên chuẩn và version schema.
outcome: success, failure hoặc blocked.
severity: mức kỹ thuật ban đầu, không phải kết luận cuối.
request_id, trace_id: tương quan xuyên dịch vụ.
service, environment, region, release: nguồn phát sinh.
account_key: định danh ổn định đã pseudonymize.
source_ip hoặc phiên bản đã giảm độ chính xác theo chính sách riêng tư.
user_agent, device_id, network/asn, country: nếu hợp pháp và cần thiết.
reason_code: mã hữu hạn như INVALID_CREDENTIALS, không ghi password.
account_key nên được tạo bằng HMAC với key riêng của hệ thống log. Hash thường của email có thể bị dò bằng dictionary. Detector thời gian thực có thể cần IP đầy đủ trong kho truy cập hạn chế, trong khi kho analytics dài hạn chỉ giữ prefix hoặc token hóa.
Tuyệt đối không log những gì?
Không ghi trực tiếp:
Password, OTP, recovery code hoặc câu trả lời bảo mật.
Access token, refresh token, API key, session ID hoặc cookie.
Private key, encryption key, database URL và connection string.
Toàn bộ request/response body theo mặc định.
Dữ liệu thanh toán, hồ sơ sức khỏe hoặc PII không cần cho detection.
Nếu cần tương quan session, dùng fingerprint/HMAC không thể đảo ngược. Sanitize CR/LF và dữ liệu không tin cậy trước khi ghi để tránh log injection. Giới hạn độ dài mọi field.
Rule cốt lõi: 5 lần thất bại trong 10 phút
Threshold 5/10 phút chỉ là điểm khởi đầu, không phải con số đúng cho mọi hệ thống. Rule nên theo dõi nhiều chiều:
1. Theo tài khoản
Rule này bắt password guessing nhưng có thể bị lợi dụng để khóa tài khoản nạn nhân.
2. Theo IP hoặc network
Không nên chỉ chặn IP: NAT làm nhiều người dùng chung IP, còn attacker có proxy/botnet để thay IP.
3. Password spraying
Password spraying cố tình tránh threshold theo từng tài khoản bằng cách thử ít lần trên nhiều tài khoản.
4. Brute force phân tán
5. Failures rồi success
Đây thường là alert ưu tiên cao. Hãy tăng risk score nếu login thành công từ thiết bị, ASN, quốc gia hoặc region chưa từng thấy, sau đó có hành vi đổi MFA, tạo API key hoặc export dữ liệu.
Triển khai bộ đếm phân tán với Redis
Không giữ counter trong memory của một instance: autoscaling và nhiều replica sẽ làm mỗi máy chỉ nhìn thấy một phần sự kiện. Redis sorted set có thể duy trì sliding window dùng chung.
Lua giúp thêm, dọn và đếm atomically. Trong production cần:
Dedupe alert bằng key SET NX EX để không gửi một alert cho mỗi lần thử sau ngưỡng.
Theo dõi thêm chiều IP và số tài khoản khác nhau.
Đặt TTL để tránh Redis tăng vô hạn.
Không dùng Redis counter thay cho audit log bền vững.
Xác định hành vi khi Redis lỗi: login không nên mặc định sập toàn bộ, nhưng phải có metric/alert cho detector degraded.
Ghi event trong NestJS mà không lộ dữ liệu
Tách security logger khỏi câu chữ hiển thị cho người dùng. Client luôn nhận lỗi chung để tránh account enumeration; log nội bộ dùng reason_code chính xác.
Cấu hình logger phải redact các key như password, authorization, cookie, token, secret kể cả khi developer vô tình truyền cả object request.
Từ log đến alert có thể hành động
Pipeline thực tế:
Alert tốt nên chứa:
Rule ID và lý do kích hoạt.
Cửa sổ thời gian, số event và số nguồn/tài khoản khác nhau.
Account key, IP/network, ASN/region và device signals phù hợp.
Những sự kiện ngay trước/sau, đặc biệt là login thành công.
Link đến truy vấn điều tra và runbook.
Severity, confidence, owner và trạng thái suppression/dedupe.
Không gửi password, token hoặc PII nhạy cảm vào Slack/email. Link người trực đến hệ thống có access control và audit trail.
Phản ứng sau khi phát hiện
Response nên tăng dần theo risk:
Ghi event và tăng metric.
Áp dụng delay/rate limit theo account + IP + device.
Yêu cầu CAPTCHA hoặc MFA khi risk cao.
Tạm chặn nguồn hoặc account với thời hạn ngắn nếu có đủ tín hiệu.
Revoke session nếu có chuỗi fail rồi success đáng ngờ.
Thông báo người dùng qua kênh đáng tin cậy.
Mở incident và điều tra các hành vi sau đăng nhập.
Không khóa vĩnh viễn tài khoản chỉ dựa vào IP hoặc năm lần sai. Attacker có thể dùng chính cơ chế lockout để gây denial of service. Ưu tiên progressive delay, step-up authentication và risk-based controls.
Chống false positive và alert fatigue
Baseline theo loại người dùng, tenant, endpoint và giờ hoạt động.
Tách scanner nội bộ, pentest và health check bằng classification, không xóa event.
Dùng nhiều tín hiệu thay vì threshold đơn: velocity, distinct accounts, device novelty và success-after-failure.
Alert một incident đã gộp thay vì hàng nghìn event.
Đặt severity theo impact và confidence.
Mọi suppression phải có owner, lý do và ngày hết hạn.
Review rule sau incident và định kỳ; attacker thay đổi hành vi.
Bảo vệ chính hệ thống log
Log là bằng chứng và cũng là dữ liệu nhạy cảm:
Truyền qua authenticated TLS; buffer khi mạng gián đoạn.
Dùng storage append-only/immutable khi rủi ro yêu cầu.
Tách quyền ghi, đọc, xóa và quản trị rule.
Cảnh báo khi log volume tụt bất thường, shipper ngừng hoặc clock lệch.
Mã hóa at rest, backup, retention và xóa theo chính sách.
Audit mọi truy cập và thay đổi detection rule.
Không để attacker xóa log chỉ vì chiếm được app instance.
Kiểm thử trước production
Tạo đúng 4 lần login fail: chưa có alert mức 5.
Tạo lần thứ 5 trong cửa sổ: có đúng một alert.
Chờ hết window: counter giảm/reset như thiết kế.
Thử nhiều tài khoản từ một IP để kích hoạt spraying rule.
Thử nhiều IP vào một account để kích hoạt distributed rule.
Tạo fail rồi success: alert được nâng ưu tiên.
Xác nhận log không chứa password, token, cookie hoặc raw body.
Tắt log shipper giả lập: detector-degraded alert phải hoạt động.
Kiểm tra on-call nhận được alert và chạy được runbook.
Checklist triển khai
Có schema và version cho security events
Clock đồng bộ và timestamp UTC
Redaction được test tự động
Rule account, IP, spraying, distributed và fail-then-success
Alert có dedupe, owner và runbook
Redis/SIEM failure có telemetry
Log store có access control và tamper protection
Retention phù hợp pháp lý và nhu cầu điều tra
Response không tạo account-lockout DoS
Rule được diễn tập và tuning định kỳ
Kết luận
Phát hiện sớm không đến từ việc “log thật nhiều”, mà từ đúng sự kiện, đúng context và đúng vòng phản hồi. Hãy bắt đầu với auth.login, triển khai nhiều chiều thay vì chỉ đếm theo IP, ưu tiên chuỗi thất bại rồi thành công và bảo vệ log như một tài sản bảo mật. Khi alert có owner, runbook và response đã thử, năm lần nhập sai mới trở thành tín hiệu phòng thủ thay vì chỉ là năm dòng text.
JWT trong SPA nên lưu ở đâu? Phân tích LocalStorage, sessionStorage, memory, HttpOnly Cookies và BFF, kèm kiến trúc khuyến nghị, code Next.js và checklist production.