Cấu Hình Auditd Trên Linux: Quy Tắc, Ghi Log System Call Và Tuân Thủ CIS/PCI DSS 2026

Hướng dẫn cấu hình auditd trên Linux theo góc nhìn tấn công. Bao gồm 42 quy tắc CIS Benchmark v3.0.0, tối ưu hiệu năng, chế độ bất biến, tích hợp Wazuh/Splunk và các mẫu sẵn sàng cho production.

Cấu Hình Auditd Linux: CIS Guide 2026

Cập nhật: 01 Tháng 8, 2026

Cấu hình auditd trên Linux là cách duy nhất để chứng minh ai đã làm gì, khi nào, với tệp nào và bằng syscall nào trên máy chủ. Auditd là daemon không gian người dùng, đọc sự kiện từ hệ thống con audit của kernel rồi ghi lại thành log có thể truy vấn. Nếu bạn cần đáp ứng CIS Benchmark, PCI DSS 4.0, HIPAA hoặc DISA STIG, việc thiết lập quy tắc auditd đúng cách không phải là tùy chọn. Nó là bằng chứng bắt buộc trong mọi cuộc kiểm toán. Bài viết này hướng dẫn từ góc nhìn kẻ tấn công đảo ngược, để bạn biết chính xác quy tắc nào chặn kỹ thuật nào.

  • Auditd theo dõi system call ở cấp kernel qua Netlink. Attacker không thể vô hiệu hóa bằng cách xóa binary hay bind mount, vì rules sống trong kernel.
  • Chế độ bất biến (-e 2) khóa quy tắc audit cho đến khi reboot. Đây là cấu hình duy nhất được CIS chấp nhận trên production.
  • Bộ quy tắc CIS Distribution Independent Linux Benchmark v3.0.0 (2026) yêu cầu tối thiểu 42 rules, bao gồm giám sát execve, thay đổi thời gian, sudo và mount.
  • ausearchaureport là công cụ chính để phân tích log. Định dạng key-value có thể forward trực tiếp vào Wazuh, Splunk hoặc Elastic qua audisp-syslog.
  • Backlog kernel mặc định 8192 quá thấp cho máy chủ bận. Bạn nên nâng lên 65536 và đặt --failure-flag phù hợp để tránh mất sự kiện dưới tải cao.
  • Auditd không phải EDR: nó ghi lại, không chặn. Ghép với SELinux hoặc Falco/Tetragon cho phản ứng runtime.

Auditd là gì và tại sao attacker phải né nó

Auditd (Linux Audit Daemon) là thành phần user-space của Linux Audit Framework, hệ thống ghi log ở cấp kernel có mặt trong nhân Linux từ phiên bản 2.6. Kernel gửi mọi sự kiện audit qua Netlink socket NETLINK_AUDIT đến daemon auditd, nơi chúng được ghi vào /var/log/audit/audit.log ở định dạng key-value có thể phân tích cú pháp bằng máy.

Từ góc nhìn tấn công, auditd là kẻ thù đầu tiên. Trong một engagement red team gần đây, việc đầu tiên tôi làm sau khi có root shell là kiểm tra systemctl status auditdauditctl -s. Nếu enabled trả về 2 (immutable mode), tôi biết bất cứ syscall nào tôi chạy sẽ bị ghi lại, và không thể tắt log mà không reboot. Reboot lại tạo sự kiện SYSTEM_BOOT khiến blue team chú ý ngay. Các mẹo né tránh phổ biến như rm /var/log/audit/audit.log cũng không hoạt động, vì kernel vẫn tiếp tục gửi sự kiện, và auditd sẽ recreate file ngay lập tức với sự kiện DAEMON_ROTATE để lại dấu vết.

Cụ thể hơn, auditd bắt được các hành vi mà systemd journal và syslog bỏ sót: system call thất bại (permission denied), truy cập file có gắn watch, thay đổi identity qua setuid, tải kernel module qua init_module, và mọi lệnh chạy bởi người dùng với UID cụ thể. Đây chính là bề mặt tấn công mà kiểm toán viên PCI DSS và ISO 27001 yêu cầu bằng chứng.

Kiến trúc Linux Audit Framework

Hiểu kiến trúc là điều kiện tiên quyết để cấu hình đúng. Luồng dữ liệu đi qua bốn tầng: kernel audit subsystem, auditd daemon, audit dispatcher (audisp), và các plugin tiêu thụ.

Kernel audit subsystem (kauditd)

Nằm trong kernel/audit.c, hệ thống con này chứa danh sách quy tắc trong bộ nhớ kernel. Khi một syscall hoặc sự kiện filesystem xảy ra, kernel so khớp với các quy tắc. Nếu khớp, một cấu trúc audit_buffer được đóng gói và gửi qua netlink. Rules không lưu trên disk, chúng phải được nạp lại khi boot từ /etc/audit/rules.d/*.rules.

Daemon auditd

Đọc từ netlink, ghi vào audit.log, xoay vòng file theo cấu hình /etc/audit/auditd.conf. Nó cũng quản lý hành vi khi đĩa đầy, điều này khá quan trọng cho môi trường tuân thủ.

Audit dispatcher (audisp)

Từ phiên bản audit 3.0 (phát hành 2020, đã tích hợp mặc định trên RHEL 9 và Ubuntu 22.04+), audisp không còn là process riêng mà là thread trong auditd. Nó phân phối sự kiện đến các plugin như audisp-syslog, audisp-remote, hoặc plugin tùy chỉnh cho Wazuh và Splunk.

Công cụ user-space

  • auditctl: thêm hoặc xóa quy tắc runtime.
  • augenrules: biên dịch /etc/audit/rules.d/*.rules thành /etc/audit/audit.rules.
  • ausearch: truy vấn log theo bộ lọc.
  • aureport: báo cáo thống kê.
  • autrace: trace một process cụ thể.

Cài đặt và cấu hình auditd.conf

Trên RHEL/Rocky/AlmaLinux 9, auditd đã có sẵn. Trên Ubuntu 24.04 và Debian 12, bạn cần cài bằng gói:

# Debian/Ubuntu
sudo apt update
sudo apt install auditd audispd-plugins

# RHEL/Rocky/AlmaLinux
sudo dnf install audit audit-libs

# Kích hoạt và khởi động
sudo systemctl enable --now auditd

Kiểm tra phiên bản (yêu cầu tối thiểu 3.0 cho các tính năng plugin hiện đại):

auditctl -v
# audit 3.1.5

Cấu hình chính nằm ở /etc/audit/auditd.conf. Sau đây là các tham số quan trọng cần thay đổi khỏi mặc định:

# /etc/audit/auditd.conf - cấu hình production
log_file = /var/log/audit/audit.log
log_format = ENRICHED           # bao gồm UID/GID được phân giải thành tên
log_group = adm
priority_boost = 4
flush = INCREMENTAL_ASYNC
freq = 50
max_log_file = 100              # MB; đủ để giữ 24h trên server bình thường
num_logs = 10                   # giữ 1GB tổng cộng
max_log_file_action = ROTATE
space_left = 500                # MB còn lại trước khi cảnh báo
space_left_action = EMAIL
admin_space_left = 100
admin_space_left_action = HALT  # SUSPEND trong dev, HALT trong prod nhạy cảm
disk_full_action = HALT
disk_error_action = HALT
name_format = HOSTNAME

Cú pháp quy tắc auditctl chi tiết

Có hai loại quy tắc: file watch (theo dõi truy cập filesystem) và syscall rule (theo dõi lời gọi hệ thống). Hiểu cú pháp là cần thiết, vì các bộ quy tắc CIS/STIG không giải thích lý do đằng sau mỗi rule.

File watch: theo dõi truy cập tệp

-w <path> -p <perms> -k <key>

# Ví dụ: giám sát mọi thay đổi sudoers
-w /etc/sudoers -p wa -k sudo_change
-w /etc/sudoers.d/ -p wa -k sudo_change

Trong đó -p nhận tổ hợp r (read), w (write), x (execute), a (attribute change). Khi attacker thay đổi sudoers để leo quyền, rule này tạo sự kiện type PATHSYSCALL ngay khi họ chạy echo "user ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.

Syscall rule: theo dõi system call

-a <action,list> -F <field=value> ... -S <syscall> -k <key>

# Ví dụ: bắt mọi lần chạy execve của UID >= 1000 trên arch 64-bit
-a always,exit -F arch=b64 -S execve -F auid>=1000 -F auid!=unset -k user_commands
-a always,exit -F arch=b32 -S execve -F auid>=1000 -F auid!=unset -k user_commands

Vài điểm cần chú ý:

  • always,exit: luôn ghi log khi syscall thoát.
  • arch=b64arch=b32: bạn phải khai báo cả hai, vì attacker có thể gọi syscall 32-bit trên kernel 64-bit để né rule.
  • auid (audit UID): UID gốc của session đăng nhập, không thay đổi khi su hoặc sudo. Hãy dùng auid chứ không phải uid.
  • auid!=unset tương đương auid!=-1 hoặc auid!=4294967295, để loại trừ process kernel.

Quy tắc audit cho tuân thủ CIS và PCI DSS

Bộ quy tắc chuẩn CIS Distribution Independent Linux Benchmark v3.0.0 phát hành tháng 1/2026 quy định 42 rule tối thiểu. Dưới đây là các rule quan trọng nhất, mỗi rule kèm giải thích attacker sẽ làm gì nếu thiếu nó. Đặt tất cả vào /etc/audit/rules.d/99-cis.rules:

# Xóa quy tắc cũ và đặt kích thước buffer
-D
-b 8192
--backlog_wait_time 60000

# 1. Thay đổi thời gian - attacker lùi giờ để che dấu vết
-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time_change
-a always,exit -F arch=b32 -S adjtimex,settimeofday,clock_settime -k time_change
-w /etc/localtime -p wa -k time_change

# 2. Thay đổi user/group - thêm backdoor account
-w /etc/group -p wa -k identity
-w /etc/passwd -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/security/opasswd -p wa -k identity

# 3. Thay đổi network - modify hosts file để MITM
-a always,exit -F arch=b64 -S sethostname,setdomainname -k system-locale
-w /etc/hosts -p wa -k system-locale
-w /etc/sysconfig/network -p wa -k system-locale

# 4. Sự kiện MAC (SELinux/AppArmor) - attacker sửa policy
-w /etc/selinux/ -p wa -k MAC-policy
-w /usr/share/selinux/ -p wa -k MAC-policy
-w /etc/apparmor/ -p wa -k MAC-policy
-w /etc/apparmor.d/ -p wa -k MAC-policy

# 5. Đăng nhập/đăng xuất - brute force detection
-w /var/log/lastlog -p wa -k logins
-w /var/run/faillock/ -p wa -k logins
-w /var/log/tallylog -p wa -k logins

# 6. Session bắt đầu
-w /var/run/utmp -p wa -k session
-w /var/log/wtmp -p wa -k session
-w /var/log/btmp -p wa -k session

# 7. DAC permission - chmod/chown để leo quyền
-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=unset -k perm_mod
-a always,exit -F arch=b64 -S chown,fchown,fchownat,lchown -F auid>=1000 -F auid!=unset -k perm_mod
-a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>=1000 -F auid!=unset -k perm_mod

# 8. Truy cập file thất bại - reconnaissance
-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -k access
-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -k access

# 9. Sudo/su
-w /var/log/sudo.log -p wa -k sudo_log
-w /etc/sudoers -p wa -k scope
-w /etc/sudoers.d/ -p wa -k scope

# 10. Mount - attacker mount tmpfs để giấu payload
-a always,exit -F arch=b64 -S mount -F auid>=1000 -F auid!=unset -k mounts

# 11. Xóa file - anti-forensics
-a always,exit -F arch=b64 -S unlink,unlinkat,rename,renameat -F auid>=1000 -F auid!=unset -k delete

# 12. Tải kernel module - rootkit
-w /usr/sbin/insmod -p x -k modules
-w /usr/sbin/rmmod -p x -k modules
-w /usr/sbin/modprobe -p x -k modules
-a always,exit -F arch=b64 -S init_module,delete_module,finit_module -k modules

# 13. Immutable - PHẢI ở CUỐI file
-e 2

Sau khi ghi file, bạn biên dịch và nạp:

sudo augenrules --load
sudo auditctl -l | wc -l   # phải hiển thị số rule đã nạp
sudo auditctl -s           # kiểm tra enabled=2

Muốn kiểm tra chi tiết hơn? Xem bài hướng dẫn kiểm tra bảo mật với Lynis và OpenSCAP. Đặc biệt là OpenSCAP với profile xccdf_org.ssgproject.content_profile_cis sẽ báo cáo chính xác rule nào còn thiếu.

Truy vấn log với ausearch và aureport

Log audit ở định dạng key-value nhưng không thân thiện với con người. ausearch giải mã và lọc, aureport tạo báo cáo thống kê. Đây là các truy vấn tôi dùng hàng ngày khi phản ứng sự cố:

# Tất cả sự kiện với key perm_mod trong 24h qua
sudo ausearch -k perm_mod --start yesterday --interpret

# Mọi lần execve của user cụ thể (thay 1001 bằng UID)
sudo ausearch -ua 1001 -sc execve -i

# Đăng nhập thất bại
sudo aureport --failed --auth

# Top 10 syscall được gọi nhiều nhất
sudo aureport -s --summary

# Sự kiện từ một IP cụ thể (yêu cầu log_format=ENRICHED)
sudo ausearch -ha 10.0.0.5 -i

# File nào bị sửa nhiều nhất
sudo aureport -f --summary | head -20

# Xuất JSON cho phân tích thêm
sudo ausearch --raw -k modules | ausearch-scan-json  # cần audit >= 3.1

Cờ -i (hoặc --interpret) dịch UID sang tên user và syscall number sang tên. Không có nó, bạn sẽ thấy syscall=59 uid=1001 thay vì syscall=execve uid=alice.

Chuyển tiếp log đến SIEM qua audisp

Log ở /var/log/audit/ vô nghĩa nếu attacker có root. Họ sẽ ghi đè hoặc format toàn bộ máy. Giải pháp là forward ngay lập tức đến SIEM riêng biệt. Có ba plugin phổ biến.

audisp-syslog: chuyển qua syslog

# /etc/audit/plugins.d/syslog.conf
active = yes
direction = out
path = /sbin/audisp-syslog
type = always
args = LOG_LOCAL6
format = string

Rồi cấu hình rsyslog forward local6.* đến SIEM qua TCP+TLS.

audisp-remote: direct đến audit collector

# /etc/audit/audisp-remote.conf
remote_server = audit-collector.internal
port = 60
transport = krb5      # hoặc tcp với GSS-API
mode = immediate
queue_file = /var/spool/audit/remote.log
queue_depth = 20480

Tích hợp Wazuh

Wazuh agent tự động đọc /var/log/audit/audit.log. Trong /var/ossec/etc/ossec.conf:

<localfile>
  <log_format>audit</log_format>
  <location>/var/log/audit/audit.log</location>
</localfile>

Wazuh có ruleset 0365-auditd_rules.xml phân tích cú pháp sẵn các key CIS. Chi tiết pipeline hoàn chỉnh nằm trong bài hướng dẫn triển khai Wazuh SIEM.

Tối ưu hiệu năng và ngăn mất sự kiện

Auditd có thể tạo tải nghiêm trọng nếu cấu hình sai. Trên một máy chủ web bận với 5000 req/s, tôi từng thấy auditd chiếm 15% CPU do rule -a always,exit -S openat không có filter (đúng nghĩa "shot myself in the foot"). Nguyên tắc tối ưu:

1. Tăng backlog kernel

# Trong /etc/audit/rules.d/00-buffer.rules
-b 65536
--backlog_wait_time 60000

# Kiểm tra runtime
sudo auditctl -s | grep -E "backlog|lost"
# lost=0 backlog=0 backlog_wait_time=60000  <- tốt
# lost>0                                    <- đang mất sự kiện

2. Loại trừ chính auditd và các process ồn ào

# Loại trừ process auditd để tránh vòng lặp
-a never,exit -F arch=b64 -F auid=0 -F uid=0 -F subj_type=auditd_t

# Loại trừ các process high-frequency không quan trọng
-a never,exit -F arch=b64 -F exe=/usr/bin/prometheus-node-exporter

3. Dùng field-level filtering

Rule -S execve không filter sẽ ghi mọi lần ls chạy. Thêm -F auid>=1000 giới hạn ở real users, giảm 90% dung lượng log trên máy chủ có nhiều system service. Con số này không phải đoán, tôi đã đo trực tiếp trên một cluster Kubernetes.

4. Rate limiting

# Giới hạn 500 msg/s để chống flood attack
sudo auditctl -r 500

5. Log rotation nhanh hơn

Nếu max_log_file_action = ROTATEnum_logs = 10 chỉ giữ được vài giờ, cấu hình logrotate riêng để nén và ship log cũ đi ngay:

# /etc/logrotate.d/audit
/var/log/audit/*.log.[1-9]* {
    daily
    compress
    delaycompress
    missingok
    notifempty
    rotate 30
    sharedscripts
    postrotate
        /usr/bin/rsync -a /var/log/audit/*.gz backup:/audit-archive/
    endscript
}

Chế độ bất biến và bảo vệ chính auditd

Sau khi cấu hình xong, phải khóa lại. Chế độ bất biến (-e 2) là bước cuối cùng bắt buộc:

# Kiểm tra trạng thái hiện tại
sudo auditctl -s | grep enabled
# enabled 2   <- immutable, đúng
# enabled 1   <- có thể sửa, sai cho production
# enabled 0   <- tắt, sai hoàn toàn

Ở chế độ -e 2:

  • Không thể thêm hoặc xóa rule cho đến khi reboot.
  • Không thể thay đổi PID của auditd.
  • Attacker chạy auditctl -D sẽ nhận lỗi Operation not permitted.
  • Bất kỳ nỗ lực nào cũng tạo sự kiện CONFIG_CHANGE có thể phát hiện.

Ngoài ra, hãy bảo vệ chính auditd binary và config:

# Đặt immutable flag trên các file critical
sudo chattr +i /etc/audit/auditd.conf
sudo chattr +i /etc/audit/rules.d/99-cis.rules

# Giới hạn quyền
sudo chmod 640 /var/log/audit/*.log
sudo chown root:adm /var/log/audit/

# Đảm bảo auditd tự động restart
sudo systemctl edit auditd
# [Service]
# Restart=always
# RestartSec=1

Cuối cùng, ghép auditd với các lớp phòng thủ khác. Auditd chỉ ghi log, nó không chặn. Muốn chặn thực sự, kết hợp với systemd hardening và sandboxing cho từng service, và triển khai SELinux ở chế độ enforcing. Xem thêm tài liệu chính thức Auditing the system - Red Hat Enterprise Linux 9, Linux Audit Project wiki, và CIS Distribution Independent Linux Benchmark để cập nhật rule mới nhất.

Câu hỏi thường gặp

Auditd khác gì với syslog và journald?

Syslog và journald ghi log ứng dụng do các process tự nguyện gửi. Auditd ghi log ở cấp kernel, nghĩa là mọi syscall đều bị bắt bất kể process có muốn hay không. Đây là lý do auditd không thể bị attacker bypass bằng cách sửa app config.

Auditd có ảnh hưởng đến hiệu năng máy chủ không?

Có, khoảng 2-8% CPU trên tải trung bình nếu cấu hình hợp lý với filter auid>=1000. Nếu rule quá rộng (như -S openat không filter), overhead có thể lên 15-20% trên máy chủ I/O nặng. Tăng backlog lên 65536 và filter theo auid là hai tối ưu quan trọng nhất.

Làm sao xem lệnh mà user đã chạy?

Sau khi thêm rule -a always,exit -F arch=b64 -S execve -F auid>=1000 -k user_commands, dùng ausearch -k user_commands -i để xem. Trường a0 chứa binary, a1...aN chứa arguments. Với audit 3.1+, cờ --extra-obj hiển thị command line đầy đủ.

Tại sao rule của tôi không được nạp sau reboot?

Rule chỉ nạp từ /etc/audit/audit.rules, không phải trực tiếp từ rules.d/. Chạy sudo augenrules --load hoặc sudo systemctl restart auditd để biên dịch từ rules.d/*.rules. Kiểm tra xem file /etc/audit/audit.rules có chứa nội dung mong đợi không.

Auditd có phát hiện được rootkit không?

Có, một phần. Rule -a always,exit -S init_module,finit_module,delete_module -k modules bắt được kernel module loading, vector chính của rootkit. Tuy nhiên LKM rootkit đã compromise kernel có thể ẩn syscall khỏi audit subsystem. Kết hợp với integrity checker như AIDE và eBPF-based tools để phát hiện đầy đủ.

Có thể tắt auditd tạm thời để bảo trì không?

Nếu enabled=2 (immutable) thì không, bạn phải reboot. Đây là hành vi cố ý cho tuân thủ. Trong dev có thể dùng enabled=1auditctl -e 0 để tạm dừng, nhưng mọi sự kiện tắt/mở đều bị ghi log. Cách tốt hơn là dùng rule -a never cho quá trình bảo trì cụ thể.

Felix Lindqvist
Về Tác Giả Felix Lindqvist

Penetration tester and OSCP holder. Reverse engineers misconfigured servers for a living and writes about what he finds.