Ngừng đoán mò: Sử dụng Auditd để ứng phó sự cố trên Linux

Security tutorial - IT technology blog
Security tutorial - IT technology blog

Cơn ác mộng lúc 2 giờ sáng: Ai đã làm hỏng file cấu hình?

2:15 sáng. Máy báo tin nhắn của tôi kêu vang. Server Nginx production đang báo lỗi 500, và trang web bị sập đối với hơn 10.000 người dùng đang hoạt động. Tôi đăng nhập, kiểm tra trạng thái dịch vụ và thấy rằng file nginx.conf đã bị sửa đổi chỉ vài phút trước đó. Chỉ số mtime không nói dối, nhưng lịch sử shell của người dùng root hoàn toàn trống trơn. Ai đó — hoặc script nào đó — đã sửa đổi một file quan trọng và xóa sạch .bash_history để xóa dấu vết.

Các bản log tiêu chuẩn như /var/log/auth.log hay syslog đều đi vào ngõ cụt. Chúng xác nhận có một lần đăng nhập đã diễn ra nhưng không cung cấp thông tin gì về những gì đã xảy ra sau đó. Đây chính là thời điểm mà nhiều quản trị hệ thống bắt đầu mất ngủ. Nếu bạn chỉ dựa vào log ứng dụng cơ bản, bạn đang “mù tịt” khi có sự cố xâm nhập. Để khắc phục điều này, tôi cần một cách để ghi lại hoạt động trực tiếp ở cấp độ kernel trước khi chúng bị che giấu.

Điểm mù: Tại sao log tiêu chuẩn lại thất bại

Logging tiêu chuẩn trên Linux chủ yếu dựa trên “sự kiện” ở tầng ứng dụng. SSH log lại kết nối; Nginx log lại yêu cầu (request). Tuy nhiên, các hệ thống này không hiểu được ý đồ của việc thao tác file. Nếu một kẻ tấn công sử dụng vim, sed, hoặc một dòng lệnh Python để ghi đè lên /etc/shadow, kernel sẽ xử lý lời gọi hệ thống (system call), nhưng các bản log của bạn thường sẽ bỏ qua nó.

So sánh các giải pháp

Khi tìm kiếm cách để lấp đầy lỗ hổng quan sát này, tôi đã cân nhắc ba lựa chọn chính:

  • Shell History (HISTFILE): Cách này chỉ để cho tiện, không phải để bảo mật. Bất kỳ ai cũng có thể vượt qua nó trong vài giây bằng cách chạy unset HISTFILE hoặc kill -9 $$.
  • EDR (Endpoint Detection and Response): Các công cụ như CrowdStrike hoặc Wazuh rất mạnh mẽ. Tuy nhiên, chúng thường chiếm dụng nhiều tài nguyên và có chi phí bản quyền cao, không phù hợp cho mọi server chuyên biệt.
  • Auditd (The Linux Audit Framework): Đây là lựa chọn bản địa (native) và nhẹ nhàng. Nó được tích hợp sẵn trong hầu hết các bản phân phối lớn và nằm giữa không gian người dùng (user space) và kernel. Gần như không thể để một người dùng thông thường vượt qua được nó.

Auditd là người chiến thắng rõ ràng về độ sâu điều tra số (forensic). Nó không chỉ báo cáo rằng một file đã thay đổi; nó còn cung cấp PID, UID, đường dẫn thực thi và dấu thời gian chính xác của syscall. Trên hầu hết các hệ thống, nó chỉ chiếm chưa đến 3% tài nguyên CPU, khiến nó trở thành lựa chọn hiển nhiên cho môi trường production.

Cách tốt hơn: Triển khai Auditd

Cài đặt là phần dễ dàng nhất. Trên Ubuntu hoặc Debian, bạn có thể chạy nó chỉ với một câu lệnh:

sudo apt update && sudo apt install auditd audispd-plugins -y

Trước khi đi sâu vào cấu hình, tôi đã đảm bảo quyền truy cập của mình được khóa chặt. Tôi đã sử dụng trình tạo mật khẩu tại toolcraft.app/vi/tools/security/password-generator để thay đổi thông tin đăng nhập server. Nó tạo ra các chuỗi có độ hỗn loạn cao (high-entropy) ngay tại trình duyệt, một cách đơn giản để ngăn chặn rò rỉ thông tin đăng nhập ngay từ đầu.

1. Theo dõi các file nhạy cảm

Để ngăn chặn một cuộc “diễn tập chữa cháy” lúc 2 giờ sáng khác, tôi đã thiết lập các “watch” (theo dõi) trên các file quan trọng. Bạn xác định một đường dẫn, các quyền cần theo dõi (đọc, ghi, thực thi hoặc thay đổi thuộc tính) và một “key” để dễ dàng lọc log.

Thêm các quy tắc này vào /etc/audit/rules.d/audit.rules:

# Theo dõi các thay đổi đối với chính các quy tắc audit
-w /etc/audit/ -p wa -k auditconfig

# Theo dõi thay đổi đối với cấu hình Nginx
-w /etc/nginx/nginx.conf -p wa -k nginx_change

# Theo dõi truy cập vào các file thông tin đăng nhập nhạy cảm
-w /etc/shadow -p wa -k password_mod
-w /etc/passwd -p wa -k user_mod

Flag -p wa sẽ kích hoạt log khi có thay đổi về ghi (write)thuộc tính (attribute). -k (key) đóng vai trò như một thẻ (tag) tùy chỉnh để bạn không phải sàng lọc qua hàng ngàn dòng log nhiễu sau này.

2. Theo dõi mọi câu lệnh được thực thi

Theo dõi file chỉ là một nửa cuộc chiến. Để xem mọi lệnh được chạy trên hệ thống, bạn phải theo dõi lời gọi hệ thống execve. Đây là cách kernel bắt đầu một tiến trình mới. Nếu ai đó chạy một script, Auditd sẽ bắt được nó tại đây.

# Theo dõi thực thi 64-bit
-a exit,always -F arch=b64 -S execve -k cmd_track

# Theo dõi thực thi 32-bit
-a exit,always -F arch=b32 -S execve -k cmd_track

Áp dụng các thay đổi này bằng cách khởi động lại dịch vụ:

sudo service auditd restart

Điều tra các bản log

Log của Auditd nằm ở /var/log/audit/audit.log. Theo mặc định, chúng trông như một bức tường văn bản dày đặc. Đừng lãng phí thời gian với grep. Hãy sử dụng ausearch thay thế.

Để xác định ai đã chạm vào cấu hình Nginx, hãy chạy:

sudo ausearch -k nginx_change -i

Flag -i rất quan trọng. Nó chuyển đổi các ID dạng số thành tên dễ đọc cho con người, chẳng hạn như biến UID 0 thành “root”.

Nếu bạn cần một cái nhìn tổng quan cấp cao về tất cả các lệnh đã chạy trong giờ qua, hãy sử dụng aureport:

sudo aureport -x --summary

Một mục log thực tế

Khi người dùng chạy sudo vi /etc/nginx/nginx.conf, Auditd sẽ tạo ra một mục như sau:

type=SYSCALL msg=audit(1692812400.123:456): arch=c000003e syscall=59 success=yes exit=0 a0=55d... 
items=2 ppid=1234 pid=5678 auid=1001 uid=0 gid=0 euid=0 exe="/usr/bin/vi" key="nginx_change"

Hãy chú ý đến auid=1001. Đây là Audit User ID. Ngay cả khi người dùng chạy sudo để trở thành root, Auditd vẫn ghi nhớ ID ban đầu họ đã sử dụng để đăng nhập. Sẽ không còn phải đoán mò ai là người đứng sau bàn phím nữa.

Lời kết cho những ca trực đêm

Auditd không chỉ là công cụ để bắt kẻ xấu. Nó là về trách nhiệm giải trình. Khi một cấu hình bị sai lệch hoặc một cron job chạy sai hướng, bạn cần một dấu vết bằng chứng có thể xác minh để khắc phục nhanh chóng.

Đừng đợi đến khi xảy ra sự cố tiếp theo mới bắt đầu ghi log. Hãy cài đặt Auditd ngay hôm nay, thiết lập theo dõi thư mục /etc/ của bạn và bắt đầu theo dõi các lời gọi execve. Bản thân bạn trong tương lai, khi được nghỉ ngơi đầy đủ, sẽ cảm ơn bạn.

Share: