Audit - hpaluch/hpaluch.github.io GitHub Wiki
Audit basics
Here are few very basic examples on Linux Audit. I used these pages as start:
- https://www.redhat.com/en/blog/configure-linux-auditing-auditd
- https://izyknows.medium.com/linux-auditd-for-threat-hunting-part-2-c75500f591e8
- https://documentation.suse.com/en-us/sles/15-SP6/html/SLES-all/cha-audit-comp.html
Tested OS: Debian 12
and Fedora 42
[!WARNING] This stuff is experimental - wrong audit rules may overload your machine and/or fill-up disk! Use these examples on disposable VM!
Note: all commands below have to be run as root
.
Playing with existing rules
NOTE: Under Fedora ensure that following package is installed:
# creates /etc/audit/rules.d/audit.rules:
dnf install audit-rules
One easy way to get overview is to use aureport
command:
- to see Login report (
-l
), interpret (decode) values (-i
) from last boot (-ts boot
):$ aureport -l -i -ts boot Login Report ============================================ # date time auid host term exe success event ============================================ 1. 04/22/2025 16:50:45 lxi 192.168.122.1 /dev/pts/0 /usr/sbin/sshd yes 368 2. 04/22/2025 17:01:45 (invalid user) 192.168.122.1 sshd /usr/sbin/sshd no 441
- to see only failed logins - add
--failed
$ aureport -l -i -ts boot --failed Login Report ============================================ # date time auid host term exe success event ============================================ 1. 04/22/2025 17:01:45 (invalid user) 192.168.122.1 sshd /usr/sbin/sshd no 441
- to see authentication reports (but seeing only failed):
$ aureport -au -i -ts boot Authentication Report ============================================ # date time acct host term exe success event ============================================ 1. 04/22/2025 17:01:46 hacker 192.168.122.1 ssh /usr/sbin/sshd no 444
Define own audit rules
- please invoke
man audir.rules
for details. - WARNING! Under Fedora all audit of all syscalls is disabled
by default. To enable below syscall rules (those with
-S syscall_name
) you need to comment out this line in/etc/audit/rules.d/audit.rules
# must comment out: -a task,never
- rules tip: on Fedora you can find example rules under
/usr/share/audit-rules/
To setup own rules:
- create file
/etc/audit/rules.d/zz_custom.rules
with content:# audit all connect(2) calls with exception of Unix socket family -a always,exit -F arch=b64 -S connect -F saddr_fam!=1 -k hp_sock1 -a always,exit -F arch=b32 -S connect -F saddr_fam!=1 -k hp_sock1 # watch (w)rite and (a)ttribute changes # partially based on: https://documentation.suse.com/en-us/sles/15-SP6/html/SLES-all/cha-audit-comp.html # watch /etc/ directory write access or attr modification: # old format: -w /etc -p wa -k hp_etc3 -a always,exit -F arch=b64 -F path=/etc -F perm=wa -F key=hp_etc3 -a always,exit -F arch=b32 -F path=/etc -F perm=wa -F key=hp_etc3 # old format: -w /etc/passwd -k hp_passwd3 -p wxa -a always,exit -F arch=b64 -F path=/etc/passwd -F perm=wxa -F key=hp_passwd3 -a always,exit -F arch=b32 -F path=/etc/passwd -F perm=wxa -F key=hp_passwd3 # old format: -w /etc/group -k hp_group3 -p wxa -a always,exit -F arch=b64 -F path=/etc/group -F perm=wxa -F key=hp_group3 -a always,exit -F arch=b32 -F path=/etc/group -F perm=wxa -F key=hp_group3 # old format: -w /etc/shadow -k hp_shadow3 -p wxa -a always,exit -F arch=b64 -F path=/etc/shadow -F perm=wxa -F key=hp_shadow3 -a always,exit -F arch=b32 -F path=/etc/shadow -F perm=wxa -F key=hp_shadow3
- regenerate and reload main configuration file
/etc/audit/audit.rules
fromrules.d/*
:$ augenrules --load $ auditctl -l # dump current rules
To see connect
kernel syscalls you can try filter like this:
- where are these new params
-m
message typesyscall
,-sc
syscall name is connect$ ausearch -ts boot -m syscall -sc connect -i # example of IPv6 socket (saddr_fam=inet6) ---- type=PROCTITLE msg=audit(04/22/2025 16:50:42.360:111) : proctitle=(sshd) type=SOCKADDR msg=audit(04/22/2025 16:50:42.360:111) : saddr={ saddr_fam=inet6 laddr=:: lport=22 } type=SYSCALL msg=audit(04/22/2025 16:50:42.360:111) : arch=x86_64 syscall=connect \ success=yes exit=0 a0=0x3 a1=0x556c17b17260 a2=0x1c a3=0x7ffd0dc45710 items=0 \ ppid=1 pid=540 auid=unset uid=root gid=root euid=root suid=root fsuid=root \ egid=root sgid=root fsgid=root tty=(none) ses=unset \ comm=sshd exe=/usr/sbin/sshd subj=unconfined key=(null) # example of Unix (local file) socket: type=PROCTITLE msg=audit(04/22/2025 16:50:42.364:116) : proctitle=(sshd) type=PATH msg=audit(04/22/2025 16:50:42.364:116) : item=0 name=/var/run/nscd/socket \ nametype=UNKNOWN cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0 type=CWD msg=audit(04/22/2025 16:50:42.364:116) : cwd=/ type=SOCKADDR msg=audit(04/22/2025 16:50:42.364:116) : saddr={ saddr_fam=local path=/var/run/nscd/socket } type=SYSCALL msg=audit(04/22/2025 16:50:42.364:116) : arch=x86_64 \ syscall=connect success=no exit=ENOENT(No such file or directory) a0=0x3 \ a1=0x7ffd0dc45e40 a2=0x6e a3=0xffffffff items=1 ppid=1 pid=540 auid=unset \ uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root \ fsgid=root tty=(none) ses=unset comm=sshd exe=/usr/sbin/sshd subj=unconfined key=(null)
- or you can filter by key adding
-k hp_sock
(key can be also substring as in this case)
We can also nicely filter rules with our keys (defined with -k key_name
keywords
in /etc/audit/rules.d/zz_custom.rules
:
# show keys containing "hp_"
ausearch -ts boot -i -k hp_
----
type=PROCTITLE msg=audit(04/22/2025 16:50:45.384:317) : \
proctitle=rm -f /etc/resolv.conf.dhclient-new.827
type=PATH msg=audit(04/22/2025 16:50:45.384:317) : item=1 \
name=/etc/resolv.conf.dhclient-new.827 inode=262172 dev=fe:01 \
mode=file,644 ouid=root ogid=root rdev=00:00 nametype=DELETE \
cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=PATH msg=audit(04/22/2025 16:50:45.384:317) : item=0 \
name=/etc/ inode=261121 dev=fe:01 mode=dir,755 ouid=root \
ogid=root rdev=00:00 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=CWD msg=audit(04/22/2025 16:50:45.384:317) : cwd=/
type=SYSCALL msg=audit(04/22/2025 16:50:45.384:317) : arch=x86_64 \
syscall=unlinkat success=yes exit=0 a0=AT_FDCWD a1=0x5585c78bf380 \
a2=0x0 a3=0x7f4e52c37f80 items=2 ppid=827 pid=838 auid=unset uid=root \
gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root \
tty=(none) ses=unset comm=rm exe=/usr/bin/rm subj=unconfined key=hp_etc3
Hmm, really nice - I forgot that DHCP client has to update /etc/resolv.conf
...
Note: mysterious a0=... a1=...
are simply arguments to kernel syscalls.
There is even nice output by key from aureport
:
$ aureport -ts boot -i -k
Key Report
===============================================
# date time key success exe auid event
===============================================
1. 04/22/2025 16:50:42 hp_etc3 yes /usr/sbin/auditctl unset 22
2. 04/22/2025 16:50:42 hp_passwd3 yes /usr/sbin/auditctl unset 23
3. 04/22/2025 16:50:42 hp_group3 yes /usr/sbin/auditctl unset 24
4. 04/22/2025 16:50:42 hp_shadow3 yes /usr/sbin/auditctl unset 25
5. 04/22/2025 16:50:42 hp_etc3 no /usr/lib/systemd/systemd-user-sessions unset 106
6. 04/22/2025 16:50:45 hp_etc3 yes /usr/bin/dash unset 305
7. 04/22/2025 16:50:45 hp_etc3 yes /usr/bin/rm unset 306
8. 04/22/2025 16:50:45 hp_etc3 yes /usr/bin/dash unset 307
9. 04/22/2025 16:50:45 hp_etc3 yes /usr/bin/dash unset 308
10. 04/22/2025 16:50:45 hp_etc3 yes /usr/bin/dash unset 309
11. 04/22/2025 16:50:45 hp_etc3 yes /usr/bin/chown unset 314
...
Limitations: I don't know how to print also path that was accessed.
To quickly see, how many syscall were audited try:
$ aureport -s -ts boot -i --summary
Syscall Summary Report
==========================
total syscall
==========================
45 sendto
40 openat
39 unlink
16 bpf
16 close
13 connect
10 setxattr
8 chmod
6 sendmsg
5 fchown
5 rename
5 fchmod
4 write
3 fchmodat
Interesting - report of calls by command filtered to just curl
using regular
grep with word (-w) filter:
$ aureport -ts boot --comm -i | grep -w curl
91. 04/25/2025 19:39:03 curl pts1 91.213.160.188 aa 188
92. 04/25/2025 19:39:03 curl pts1 2001:67c:68::76 aa 189
...
Auditing privileged operations
I was thinking how to audit privileged operations for non-privileged invoker:
- running
su
to become root - running
sudo
to become root - running suid program that will execute as root
I found exactly these rules in /usr/share/audit/sample-rules/30-pci-dss-v31.rules
:
# from /usr/share/audit-rules/30-ospp-v42-1-create-failed.rules
### 10.2.5.b All elevation of privileges is logged
-a always,exit -F arch=b64 -S setuid -F a0=0 -F exe=/usr/bin/su -F key=10.2.5.b-elevated-privs-session
-a always,exit -F arch=b32 -S setuid -F a0=0 -F exe=/usr/bin/su -F key=10.2.5.b-elevated-privs-session
-a always,exit -F arch=b64 -S setresuid -F a0=0 -F exe=/usr/bin/sudo -F key=10.2.5.b-elevated-privs-session
-a always,exit -F arch=b32 -S setresuid -F a0=0 -F exe=/usr/bin/sudo -F key=10.2.5.b-elevated-privs-session
-a always,exit -F arch=b64 -S execve -C uid!=euid -F euid=0 -F key=10.2.5.b-elevated-privs-setuid
-a always,exit -F arch=b32 -S execve -C uid!=euid -F euid=0 -F key=10.2.5.b-elevated-privs-setuid
They do what I want - just load them.
Using json
Failed with mmaudit
module - although it is included with rsyslog it is broken
you can find exact error using:
- terse error:
rsyslog -N 1 -f /etc/rsyslog.conf
). - detailed error:
rsyslog -d -N 1 -f /etc/rsyslog.conf
).
modules.c: Requested to load module 'mmaudit'
modules.c: loading module '/usr/lib64/rsyslog/mmaudit.so'
modules.c: module mmaudit of type 1 being loaded (keepType=0).
mmaudit.c: entry point 'setModCnf' not present in module
mmaudit.c: entry point 'getModCnfName' not present in module
mmaudit.c: entry point 'beginCnfLoad' not present in module
mmaudit.c: entry point 'doHUP' not present in module
mmaudit.c: entry point 'doHUPWrkr' not present in module
mmaudit.c: entry point 'SetShutdownImmdtPtr' not present in module
mmaudit.c: entry point 'beginTransaction' not present in module
mmaudit.c: entry point 'commitTransaction' not present in module
mmaudit.c: entry point 'endTransaction' not present in module
mmaudit.c: entry point 'newActInst' not present in module
Alternative is using mmfield
- testing:
# /etc/rsyslog.d/mm_audit.conf - redirect audit to /var/log/test.json
# Bugs: some fields are still text-based (inside message etc).
# tested on Fedora 42, requires: dnf install rsyslog-mmfields
# based on https://www.rsyslog.com/doc/configuration/modules/mmfields.html
module(load="mmfields")
template(name="ftpl"
type="string"
string="%$!%\n")
if ( $programname == 'audit' ) then {
action(type="mmfields")
action(type="omfile"
file="/var/log/test.json"
template="ftpl")
}
There is also long discussion on https://stackoverflow.com/questions/74982676/how-to-convert-auditd-logs-to-json-format-efficiently-using-rsyslog-modules (not yet tested)