Tracking file deletion using auditd without unlink?

I'm working on creating an auditd rule that will track the deletion of files and directories. I have one that often turns up in online searches but I'm not sure it is really all that useful:

-a exit,always -F arch=b32 -S unlink -S rmdir -k deletion

There are actually two. One each for 32-bit and 64-bit.

The problem I have is that I don't know of anyone who uses unlink to delete files instead of rm. I've tested rm thinking maybe it actually called unlink but nothing shows up in the log.

Am I missing something? Is there a way to track file deletions using rm?


Solution 1:

I ran strace rm test to see if it was making any calls to unlink. It isn't calling unlink itself, but instead unlinkat. I've added that to the auditd rule:

-a exit,always -F arch=b32 -S unlink -S unlinkat -S rmdir -k deletion

This will trigger on any file deletion whether by root or a regular user.

The strace output:

execve("/bin/rm", ["rm", "test"], [/* 17 vars */]) = 0
brk(0)                                  = 0x60d000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3a8e43c000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=26788, ...}) = 0
mmap(NULL, 26788, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3a8e435000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY)      = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\356\0015;\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1926760, ...}) = 0
mmap(0x3b35000000, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3b35000000
mprotect(0x3b3518a000, 2097152, PROT_NONE) = 0
mmap(0x3b3538a000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18a000) = 0x3b3538a000
mmap(0x3b3538f000, 18696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3b3538f000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3a8e434000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3a8e433000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3a8e432000
arch_prctl(ARCH_SET_FS, 0x7f3a8e433700) = 0
mprotect(0x3b3538a000, 16384, PROT_READ) = 0
mprotect(0x3b34a1f000, 4096, PROT_READ) = 0
munmap(0x7f3a8e435000, 26788)           = 0
brk(0)                                  = 0x60d000
brk(0x62e000)                           = 0x62e000
open("/usr/lib/locale/locale-archive", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=99158576, ...}) = 0
mmap(NULL, 99158576, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3a885a1000
close(3)                                = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
newfstatat(AT_FDCWD, "test", {st_mode=S_IFREG|0640, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
geteuid()                               = 0
unlinkat(AT_FDCWD, "test", 0)           = 0
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?

Solution 2:

Sometimes it is possible for the file to be actually renamed using the mv command and it may appear like the original file has been deleted. For such scenarios (assuming you are looking out for files in the /tmp/ directory), you can add the below rule in the audit.rules file.

-a always,exit -F arch=b32 -F dir=/tmp/ -S unlink -S unlinkat -S rename -S renameat -S rmdir -k file_del

You can simply search for the removal or renaming event associated with any file under the /tmp/ path by searching using the key file_del either via a grep operation on the audit.log files or better using below command :

ausearch -k file_del