Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
auditd-based file integrity monitoring #3492
I have implemented file integrity monitoring using the auditd service. This can come in handy as inotify can only subscribe for a limited amount of entities, and can’t be easily changed at runtime by osquery without risking invalidation of the existing watchers.
Using auditd for file integrity monitoring offers the following advantages:
In general, our implementation can be easily expanded in the future to support more event publishers, since the audit netlink can now be shared. This should also empower subscribers, allowing them to use a more lightweight filtering logic suitable for the task they needs to perform. In order to make auditd suitable for file integrity monitoring, we overcame several performance issues when receiving and processing events from the audit netlink. Additionally, subscribers are no longer blocking each other and/or the netlink reader when processing the event records.
How auditd-based file integrity monitoring works
The new implementation works by tracking process/handle creation and destruction by monitoring the execve/exit/exit_group and open/close/dup syscalls.
The file descriptors are saved inside a handle table (one for each process) in the auditd_file_events subscriber. The tables are then used to solve the file descriptors when the following system calls are executed: read/write/mmap.
Rows are only inserted inside the table when a file changes state. Valid state changes are: Open -> Read -> Write -> Close.
Configuration is not yet supported but I plan on adding it, in a way similar to the existing file_events table.
Issues found and fixed in the original code
While I was separating the netlink reader and the AuditAssembler logic, I encountered and fixed the following issues:
Modified or added components:
This is needed because the existing AuditAssembler component is not capable of sharing the audit handle and it doesn’t support complex filtering logic (which makes it unsuitable for certain use-cases). Another issue is that it does not allow the consumers to subscribe for syscalls that receive different types (and amount) of records (i.e.: open() and mmap()).
Two threads are used, one for receiving the records, and another one for parsing them. Subscribers are given a handle to request new updates.
Configuration options have been all moved here, as having all settings here is better than implementing conflict-resolution logic to merge all the (possibly) different rules requested by each subscriber.
Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need the corporate CLA signed.
If you have received this in error or have any questions, please contact us at email@example.com. Thanks!
The way I'm going to test this will be a little disorganized. Trying to move fast and include nitpick/style/approach/direction questions together, just want to apologize before hand. :P
I've created a squashed version of all the commits and will be using that to track changes locally as I learn the new implementation and tweak/performance-monitor on my test hosts.
How does the publisher shutdown?
Seems like I need to
I can't get the
I used to be able to do:
From reading the code I'm guessing you now need:
But that's not working either?
So if I try to initialize:
Are there two audit-related publishers? Ideally there should be just one publisher that publishes to multiple subscribers.
First past comments, nothing crazy. Some of my previous thread comments are more high-pri.
The process_events table is working fine for me using the following flags:
The reason that it may not work for you is that I have added a new flag to control whether it is enabled or not the same way socket_events works. The default setting is disabled.
I have also successfully tried with
There is one AuditNetlink class fetching the events from the audit netlink and two publishers. The AuditNetlink class is generic and supports more than one consumer.
The first publisher (audit.cpp, used by socket_events and process_events) was not suitable for my use case for the following reasons:
In order to avoid refactoring all the existing tables, a second publisher has been implemented.
The AuditdFim component is a lot simpler, as it doesn't need to specifically keep track of which records the subscriber expects to receive (the syscall number is enough) because it makes use of the AUDIT_EOE terminator. This should also be faster than completing them manually.