Wednesday, November 26, 2025

Auditing File Changes in Linux: A DBA’s Quick Guide (auditctl vs strace)

 Auditing File Changes in Linux: A DBA’s Quick Guide (auditctl vs strace)


Intro:
As database administrators, we’re sometimes asked not for deep forensics, but simply: “Who changed that file, using what command, and when?” After a recent incident, I set out to compare two popular Linux tools—auditctl and strace—to see which delivers a straightforward audit trail with minimal fuss.

Main Content:
Objectives:

  • Audit changes to a Linux file

  • Identify the command/user/time of change

  • Minimal setup, easy rollback

Options Explored:

  1. auditctl (the Linux audit framework)

  2. strace (versatile process tracing tool)

Quick Summary of Both Methods:

  • auditctl — Minimal overhead, decent info for investigations, but needs root access.

  • strace — Great for process-level tracing, accessible to non-root users (if you own the process), but can create overwhelming output.

Sample Commands from My Lab:

text

auditctl -w /home/oracle/dba/testaudit/file.out -p rwa -k file_change_watch1

strace -o /tmp/stracefilechng2.out -fftttTyy -p <pid>

Pros & Cons Table:

Tool

Pros

Cons

auditctl

Lightweight, easy, time-bounded, easy rollback

Needs root

strace

User-accessible, customizable output

Too verbose, not explicitly file-centric


Raw Output:


Explore Auditctl: /var/log/audit/audit.log auditctl -l auditctl -w /home/oracle/dba/testaudit/file.out -p rwa -k file_change_watch1 list the audit rules: auditctl -l ausearch -k file_change_watch historical commands: syscalls: aureport -s user executables: aureport -x user activities: aureport -u rollback: auditctl -W /home/oracle/dba/testaudit/file.out -p rwa -k file_change_watch

Auditctl:

time->Tue Nov 25 23:16:08 2025

type=CONFIG_CHANGE msg=audit(1764112568.801:1139): auid=54321 ses=6 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 op=add_rule key="file_change_watch" list=4 res=1

----

time->Tue Nov 25 23:16:30 2025

type=PROCTITLE msg=audit(1764112590.315:1140): proctitle=7669002F686F6D652F6F7261636C652F6462612F7465737461756469742F66696C652E6F7574

type=PATH msg=audit(1764112590.315:1140): item=0 name="/home/oracle/dba/testaudit/file.out" inode=34093864 dev=fd:00 mode=0100644 ouid=54321 ogid=54321 rdev=00:00 obj=unconfined_u:object_r:user_home_t:s0 objtype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0

type=CWD msg=audit(1764112590.315:1140):  cwd="/home/oracle/dba/testaudit"

type=SYSCALL msg=audit(1764112590.315:1140): arch=c000003e syscall=2 success=yes exit=3 a0=1e0a7a0 a1=0 a2=0 a3=7ffc94f41590 items=1 ppid=5273 pid=9021 auid=54321 uid=54321 gid=54321 euid=54321 suid=54321 fsuid=54321 egid=54321 sgid=54321 fsgid=54321 tty=pts1 ses=7 comm="vi" exe="/usr/bin/vi" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="file_change_watch"

----


Strace (after post processing using a parser):

strace -o /tmp/stracefilechng2.out -fftttTyy -p <pid>

[hostname]$ ./straceprocess_v3.bash /tmp/stracefilechng2.out.9360

Processing file: /tmp/stracefilechng2.out.9360


Timestamp: [2025-11-25 23:22:15.914404], Executed: /usr/bin/vi

    File operated: /etc/ld.so.cache | Mode: O_RDONLY|O_CLOEXEC (at 2025-11-25 23:22:15.922599)

    File operated: /lib64/libselinux.so.1 | Mode: O_RDONLY|O_CLOEXEC (at 2025-11-25 23:22:15.922812)

    File operated: /lib64/libtinfo.so.5 | Mode: O_RDONLY|O_CLOEXEC (at 2025-11-25 23:22:15.923483)

    File operated: /lib64/libacl.so.1 | Mode: O_RDONLY|O_CLOEXEC (at 2025-11-25 23:22:15.923810)

    File operated: /lib64/libc.so.6 | Mode: O_RDONLY|O_CLOEXEC (at 2025-11-25 23:22:15.924325)

    File operated: /lib64/libpcre.so.1 | Mode: O_RDONLY|O_CLOEXEC (at 2025-11-25 23:22:15.924707)

    File operated: /lib64/libdl.so.2 | Mode: O_RDONLY|O_CLOEXEC (at 2025-11-25 23:22:15.925105)

    File operated: /lib64/libattr.so.1 | Mode: O_RDONLY|O_CLOEXEC (at 2025-11-25 23:22:15.925598)

    File operated: /lib64/libpthread.so.0 | Mode: O_RDONLY|O_CLOEXEC (at 2025-11-25 23:22:15.926035)

    File operated: /usr/lib/locale/locale-archive | Mode: O_RDONLY|O_CLOEXEC (at 2025-11-25 23:22:15.934372)

    File operated: . | Mode: O_RDONLY (at 2025-11-25 23:22:15.937359)

    File operated: /usr/share/terminfo/x/xterm | Mode: O_RDONLY (at 2025-11-25 23:22:15.941108)

    File operated: . | Mode: O_RDONLY (at 2025-11-25 23:22:15.942247)

    File operated: /etc/virc | Mode: O_RDONLY (at 2025-11-25 23:22:15.942614)

    File operated: . | Mode: O_RDONLY (at 2025-11-25 23:22:15.943293)

    File operated: /home/oracle/.vimrc | Mode: O_RDONLY (at 2025-11-25 23:22:15.943822)

    File operated: /home/oracle/_vimrc | Mode: O_RDONLY (at 2025-11-25 23:22:15.943870)

    File operated: . | Mode: O_RDONLY (at 2025-11-25 23:22:15.943917)

    File operated: /home/oracle/.vim/vimrc | Mode: O_RDONLY (at 2025-11-25 23:22:15.944241)

    File operated: . | Mode: O_RDONLY (at 2025-11-25 23:22:15.944287)

    File operated: /home/oracle/.exrc | Mode: O_RDONLY (at 2025-11-25 23:22:15.944831)

    File operated: /etc/nsswitch.conf | Mode: O_RDONLY|O_CLOEXEC (at 2025-11-25 23:22:15.957681)

    File operated: /etc/ld.so.cache | Mode: O_RDONLY|O_CLOEXEC (at 2025-11-25 23:22:15.958052)

    File operated: /lib64/libnss_files.so.2 | Mode: O_RDONLY|O_CLOEXEC (at 2025-11-25 23:22:15.958334)

    File operated: /etc/passwd | Mode: O_RDONLY|O_CLOEXEC (at 2025-11-25 23:22:15.958948)

    File operated: /home/oracle/dba/testaudit/file.out | Mode: O_RDONLY (at 2025-11-25 23:22:15.961930)

    File operated: /home/oracle/dba/testaudit/.file.out.swp | Mode: O_RDONLY (at 2025-11-25 23:22:15.962117)

    File operated: /home/oracle/dba/testaudit/.file.out.swp | Mode: O_RDWR|O_CREAT|O_EXCL (at 2025-11-25 23:22:15.962194)

    File operated: /home/oracle/dba/testaudit/.file.out.swx | Mode: O_RDONLY (at 2025-11-25 23:22:15.962369)

    File operated: /home/oracle/dba/testaudit/.file.out.swx | Mode: O_RDWR|O_CREAT|O_EXCL (at 2025-11-25 23:22:15.962411)

    File operated: /home/oracle/dba/testaudit/.file.out.swp | Mode: O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW (at 2025-11-25 23:22:15.962939)

    File operated: 4913 | Mode: O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW (at 2025-11-25 23:22:21.357528)

    File operated: file.out | Mode: O_WRONLY|O_CREAT|O_TRUNC (at 2025-11-25 23:22:21.358269)


Code for straceprocess_v3.bash

#!/bin/bash

# Usage: ./strace_human_summary.sh strace_output_file(s)


for file in "$@"; do

    echo "Processing file: $file"

    awk '

    function humantime(ts) {

        # Split timestamp into seconds and microseconds

        split(ts, parts, ".")

        cmd = "date -d \"@" parts[1] "\" \"+%Y-%m-%d %H:%M:%S\""

        cmd | getline out

        close(cmd)

        if (length(parts) > 1) {

            out = out "." parts[2]

        }

        return out

    }

    /execve\(/ {

        ts = $1

        ht = humantime(ts)

        match($0, /execve\("([^"]+)"/, arr)

        bin = arr[1]

        if (bin != "") {

            printf("\nTimestamp: [%s], Executed: %s\n", ht, bin)

        }

    }

    /(open|openat|creat)\(/ {

        ts = $1

        ht = humantime(ts)

        if (match($0, /(open|openat|creat)\("([^"]+)", ([^,)]*)/, arr)) {

            fileop = arr[2]

            mode = arr[3]

            if (fileop != "") {

                printf("    File operated: %s | Mode: %s (at %s)\n", fileop, mode, ht)

            }

        }

    }

    ' "$file"

    echo ""

done



No comments:

Post a Comment

MSSQL 2016+ Auto seeding feature on AG

  Fixing broken AG.. Without auto seeding: You will need to .. Ensure endpoints in AG properly configured Suspend HADR (primary) ALTER DATAB...