Quy tắc và cấu trúc dữ liệu cho hệ thống kiểm toán trong nhân Linux

Các concept cơ bản của hệ thống kiểm toán

Trong nhân Linux, kiểm toán (Auditing) là một cơ chế an ninh dùng để giám sát và ghi lại các sự kiện quan trọng liên quan đến an ninh hệ thống như thao tác người dùng, truy cập tập tin, hoặc các syscall. Mục tiêu chính của kiểm toán là cung cấp một cách giám sát minh bạch các hoạt động hệ thống, giúp ích cho việc giám sát sau sự cố, phát hiện xâm nhập, hoặc đảm bảo tuân thủ các quy định.

Trong khi các nhà phát triển có thể thí nghiệm trên các máy tính dành cho phát triển, các quản trị viên thường phải giám sát các máy tính đang hoạt động trong môi trường sản xuất. Điều này đặt ra hai yêu cầu chính:

  • Các quy tắc lựa chọn sự kiện cần ghi lại phải có thể thay đổi động mà không yêu cầu khởi động lại hệ thống hoặc thay đổi module nhân.
  • Việc sử dụng cơ chế kiểm toán không nên làm suy giảm hiệu suất hệ thống đáng kể, và ngay cả khi tắt kiểm toán, hiệu suất cũng không bị ảnh hưởng.

Hệ thống kiểm toán Linux được cấu trúc như sau:

Các thành phần核심 của hệ thống kiểm toán

1. Cấu trúc kiểm toán trong nhân

  • Chức năng: thu thập và lọc các sự kiện an ninh tại mức nhân, giám sát các thao tác quan trọng thông qua các điểm neo (hooks) như syscall hoặc truy cập tập tin.
  • Quá trình kích hoạt: Khi một thao tác cụ thể xảy ra (ví dụ syscall open), nhân kiểm tra xem có phù hợp với các quy tắc kiểm toán nào không và quyết định ghi lại sự kiện.
  • Lọc hiệu quả: Sử dụng các cấu trúc dữ liệu nhân (như bảng băm) để khớp các quy tắc một cách nhanh chóng, giảm thiểu tổn thất hiệu suất.

2. Công cụ không gian người dùng

  • auditd: Là một daemon nhận các sự kiện kiểm toán từ nhân và ghi vào các tập tin nhật ký (ví dụ /var/log/audit/audit.log).
  • auditctl: Công cụ CLI để cấu hình động các quy tắc kiểm toán mà không cần khởi động lại hệ thống.
  • ausearch/aureport: Dụng cụ để tra cứu và báo cáo các sự kiện kiểm toán, cho phép lọc theo nhiều tiêu chí khác nhau.

Cấu trúc của các quy tắc kiểm toán và cơ chế khớp

1. Cấu trúc của các quy tắc

  • Filter: Xác định loại sự kiện, ví dụ:
    • entry: Khi syscall được gọi.
    • exit: Khi syscall hoàn tất.
    • task: Khi một tiến trình được tạo.
    • file: Khi một tập tin được truy cập.
  • Giá trị:
    • ALWAYS: Kích hoạt quy tắc, ghi lại sự kiện.
    • NEVER: Tắt quy tắc, bỏ qua việc ghi lại.

2. Cơ chế khớp quy tắc

  • Nguyên tắc khớp đầu tiên: Quy tắc được lưu theo thứ tự thêm vào, và chỉ quy tắc khớp đầu tiên được thực thi.
  • Ứng dụng:
    • NEVER được đặt trước ALWAYS để loại trừ một số sự kiện特定.
    • Ví dụ:
      auditctl -a never,exit -F dir=/tmp -k ignore_tmp  # Bỏ qua các sự kiện trong thư mục /tmp
      auditctl -a always,exit -S open -k global_file    # Ghi lại các thao tác open tập tin
      

Quản lý quy tắc động và tối ưu hiệu suất

1. Cập nhật quy tắc động

  • Thực thi ngay: Thêm, sửa hoặc xóa các quy tắc thông qua auditctl mà không cần khởi động lại hệ thống.
  • Ví dụ:
    # Thêm quy tắc giám sát truy cập và sửa đổi tập tin /etc/passwd
    auditctl -w /etc/passwd -p wa -k file_sensitive
    
    # Xóa quy tắc theo khóa
    auditctl -d -k file_sensitive
    

2. Các biện pháp tối ưu

  • Lọc nhẹ: Chỉ tạo các sự kiện khi có khớp với các quy tắc.
  • Viết nhật ký không chặn: Nhân gửi các sự kiện qua socket Netlink đến auditd, tránh gây tắc nghẽn.
  • Tắt kiểm toán không gây tổn thất: Khi tắt kiểm toán (auditctl -e 0), các đoạn mã trong nhân chỉ giữ lại các kiểm tra trống.

Ứng dụng cụ thể và Phân tích nhật ký

1. Giám sát việc thực thi các lệnh nhạy cảm (như sudo và su)

  • Cấu hình quy tắc:
    auditctl -a exit,always -S execve -F exe=/usr/bin/sudo -k admin_ops
    auditctl -a exit,always -S execve -F exe=/usr/bin/su -k admin_ops
    
  • Nhật ký:
    type=EXECVE msg=audit(1625145600.123:456): a0="sudo" a1="-i" a2="root"
    type=SYSCALL msg=audit(...): syscall=59 (execve) success=yes ...
    
  • Phân tích:
    ausearch -k admin_ops | aureport -i
    

2. Giám sát truy cập vào các tập tin quan trọng (như /etc/shadow)

  • Cấu hình:
    auditctl -w /etc/shadow -p rwa -k shadow_access
    
  • Nhật ký:
    type=PATH msg=audit(...): item=0 name="/etc/shadow" inode=12345 ...
    
  • Phân tích:
    ausearch -k shadow_access | aureport -f
    

3. Giám sát các sự kiện đăng nhập

  • Cấu hình:
    auditctl -a exit,always -F path=/bin/login -k user_auth
    
  • Nhật ký:
    type=USER_AUTH msg=audit(...): pid=1234 uid=0 auid=1000 res=success
    

Các yêu cầu quản trị được đáp ứng bởi hệ thống kiểm toán

Yêu cầu Cách thực hiện
Quản lý quy tắc động Thay đổi các quy tắc thông qua auditctl mà không cần khởi động lại hệ thống.
Tối ưu hiệu suất Lọc các sự kiện không cần thiết tại mức nhân và gửi nhật ký không chặn.
Giám sát chi tiết Coverage từ truy cập tập tin đến các lệnh có đặc quyền, đáp ứng các yêu cầu tuân thủ và phát hiện xâm nhập.

Thực hiện kiểm toán

Các thành phần核심 của hệ thống kiểm toán nằm trong nhân Linux, được định nghĩa trong các tập tin nguồn sau:

  • kernel/audit.c: Cung cấp các机制核심 của kiểm toán.
  • kernel/auditsc.c: Cụ thể hóa việc kiểm toán syscall.
  • kernel/auditfilter.c: Xử lý các quy tắc lọc kiểm toán.

Cấu trúc dữ liệu

Các cấu trúc dữ liệu được sử dụng trong hệ thống kiểm toán được nhóm thành ba loại:

  1. Cấu trúc#admind(Context) cho mỗi tiến trình.
  2. Cấu trúc sự kiện kiểm toán và các quy tắc.
  3. Cơ chế giao tiếp với các công cụ người dùng.

Phần mở rộng cho task_struct

Mỗi tiến trình có một#admind(Context) kiểm toán:

  • Thời kỳ sống:
    • Tạo lúc bắt đầu một tiến trình.
    • Phân bổ và điền dữ liệu khi có thao tác cần kiểm toán.
    • Xoá khi tiến trình kết thúc.

Quá trình khởi tạo

Quá trình audit_init được gọi khi khởi động nhân để:

  • Khởi tạo các mechanism giao tiếp (Netlink).
  • chuẩn bị các cấu trúc lưu trữ quy tắc (như bảng băm).
  • Đăng ký các điểm neo kiểm toán syscall.
  • Khởi động thread nhân kauditd để gửi các sự kiện đến auditd.

Ghi các sự kiện

Quy trình ghi một sự kiện kiểm toán được thực hiện qua ba bước:

  1. audit_log_start: Tạo và khởi tạo một buffer kiểm toán.
  2. audit_log_format: Định dạng thông tin sự kiện vào buffer.
  3. audit_log_end: Thêm buffer vào hàng đợi gửi đến auditd và giải phóng buffer.

Ví dụ xử lý syscall open:

// Xử lý khi syscall được gọi
void syscall_entry(struct pt_regs *regs, long syscall) {
    struct audit_context *ctx = current->audit_context;
    if (audit_match_syscall(ctx, syscall)) {
        struct audit_buffer *ab = audit_log_start(ctx, GFP_KERNEL, AUDIT_SYSCALL);
        audit_log_format(ab, " syscall=%ld", syscall);
        audit_log_end(ab);
    }
}

// Xử lý khi syscall hoàn tất
void syscall_exit(struct pt_regs *regs, long ret) {
    struct audit_context *ctx = current->audit_context;
    if (audit_match_syscall(ctx, syscall)) {
        struct audit_buffer *ab = audit_log_start(ctx, GFP_KERNEL, AUDIT_SYSCALL);
        audit_log_format(ab, " ret=%ld", ret);
        audit_log_end(ab);
    }
}

Thẻ: linux Kiểm toán hệ thống auditctl auditd syslog

Đăng vào ngày 1 tháng 7 lúc 01:06