Linux Audit – Usable, Robust, Easy Logging

Logs produced by the Linux Audit subsystem and auditd(8) contain information that can be very useful in a SIEM context (if a useful ruleset has...

Linux Audit – Usable, Robust, Easy Logging

Logs produced by the Linux Audit subsystem and auditd(8) contain information that can be very useful in a SIEM context (if a useful ruleset has been configured). However, the format is not well-suited for at-scale analysis: Events are usually split across different lines that have to be merged using a message identifier. Files and program executions are logged via PATH and EXECVE elements, but a limited character set for strings causes many of those entries to be hex-encoded. For a more detailed discussion, see Practical auditd(8) problems

LAUREL solves these problems by consuming audit events, parsing and transforming them into more data and writing them out as a JSON-based log format, while keeping all information intact that was part of the original audit log. It does not replace auditd(8) as the consumer of audit messages from the kernel. Instead, it uses the audisp ("audit dispatch") interface to receive messages via auditd(8). Therefore, it can peacefully coexist with other consumers of audit events (e.g. some EDR products).

Refer to JSON-based log format for a description of the log format.

We developed this tool because we were not content with feature sets and performance characteristics of existing projects and products. Please refer to Performacne for details.

Build from source

LAUREL is written in Rust. To build it, a reasonably recent Rust compiler (we currently use 1.48), cargo, and the libacl library and its header files (Debian: libacl1-dev, RedHat: libacl-devel) are required.

$ cargo build --release
$ sudo install -m755 target/release/laurel /usr/local/sbin/laurel

Configure, use

  • Create a dedicated user, e.g.:
     sudo useradd --system --home-dir /var/lib/laurel --create-home _laurel
    ``
    
  • Configure LAUREL, write to /etc/laurel/config.toml:
    directory = "/var/log/laurel"
    user = "_laurel"
    
    [auditlog]
    file = "audit.log"
    size = 1000000
    generations = 10
    read-users = [ "splunk" ]
    ``
    
  • Register LAUREL as an audisp plugin, write to (depending on your auditd version) /etc/audisp/plugins.d/laurel.conf or /etc/audit/plugins.d/laurel.conf:
    active = yes
    direction = out
    type = always
    format = string
    path = /usr/local/sbin/laurel
    args = --config /etc/laurel/config.toml
    ``
    
    
  • Tell auditd(8) to re-evaluate its configuration
    $ sudo pkill -HUP auditd
    

License

GNU General Public License, version 3

Authors

Issues

Collection of the latest Issues

ZRAMTEST

ZRAMTEST

0

I am getting various errors when trying to build Laurel and have tried the following to resolve them yet to no avail. Am I doing something wrong or is this not supported for CentOS/RedHat 7? Would anyone kindly also provide details concerning the "…or use the provided binary" section aswell? I am by no means an expert in Rust and have recently started working with auditd logs, all and any help is greatly appreciated.

1st Error:

1st Error resolved by the following commands:

2nd Error which I got stuck in:

disasmwinnie

disasmwinnie

0

The suggestion is to provide a commandline-field, filled from /proc, for every kind of syscall event. At the moment Laurel provides the PPID-commandline via PARENT_INFO.ARGV for every syscall, while SYSCALL.ARGV only contains the PID-commandline for EXECVE-syscalls.

Considering queries/detections that use any other type of syscall, including open() for file access watches from auditd.rules, a particular Laurel event provides the PPID- but not the PID-commandline (except execve() of course). This calls for a join-operation by PID, only to get the commandline args.


We want to add another SYSCALL.ARGV, but there's already one there :)

At the moment there is

  • SYSCALL.ARGV, which uses decoded and concatenated a0, a1, ... values from Auditd's type=SYSCALL records and PARENT_INFO.ARGV, which uses /proc/$PPID/cmdline

The latter looks the same for execve-syscalls, but the sources of information differ, although "ARGV" suggests something different. This becomes more obvious for other syscalls like socket, where SYSCALL.ARGV contains hex values. I think this would be a good chance to eliminate this inconsistency.


I suggest renaming PARENT_INFO.ARGV ---> PARENT_INFO.CMD. For the implementation of the PID-commandline we can add SYSCALL.CMD (or whatever). Reasoning:

  • ARGV still makes sense for syscalls of any kind and should be always enriched to a list. It still has added value whether it's execve() or any other syscall.
  • Messing with PARENT_INFO, instead of SYSCALL breaks less existing detection rules. The biggest pain has been EXECVE params and their encoding. Imho, people rely more on the latter than on PARENT_INFO.

I am a little unsure whether the encoding/concat stuff for EXECVE still makes sense. It's basically the same info, twice. Should this still remain? I think it would make sense to let SYSCALL.ARGV live, but only as a concatenated list. Save the encoding-part in EXECVE for performance reasons. The downside: we should make commandline-field from /proc entirely optional. This makes sense for uses cases like https://github.com/threathunters-io/laurel/issues/33 and "I just don't need it"-scenarios. Than current Laurel-processing of type=EXECVE records becomes necessary.


The summary for discussion

  1. Add commandline from /proc/$PID/cmdline for every syscall.
  2. Rename PARENT_INFO.ARGV ---> PARENT_INFO.CMD instead of messing with SYSCALL.ARGV
  3. CMD, COMMANDLINE or something else? CommandLine would help for Sysmon-compat, but it doesn't fit into Laurel's ALLCAPS-field for added respectively enriched fields. Imho, CMD.
  4. Should ARGV encoding/enrichment stay alive in the original form?
  5. Make all of the discussed points configurable, including execve-argv = [ "array", "string", "none" ]
hillu

hillu

enhancement
0

For more complex event filtering where something along the lines of #24 is not enough, the administrator should be able to provide a script that contains the logic on what events or parts of events should be dropped.

I think that the onlyviable language/implementation for this is LuaJIT.

hillu

hillu

enhancement
0

If the SYSCALL message contains a specific key (from the -k option in audit rules), there should at least the following options:

  • filter out specific messages from the event (e.g. PATH or PROCTITLE)
  • drop the entire message
hillu

hillu

enhancement
0

Reproducible performance measurements are important. So far, decisions about how to implement features have been based on the experiences taken from two prototypes and on gut feelings ("allocations are bad, even in systems without garbage-collected memory management").

We can do better than that.

juju4

juju4

6

as best practice, laurel executable should have a test/dry-run/foreground option to test configuration (syntax and working execution)

juju4

juju4

16

with laurel 0.1.1 on Ubuntu 18.04 and base laurel configuration

while

SYSCALL is the ones where I would expect process activity Even if merging some of the different msgtype, same data should be found

Versions

Find the latest versions by id

v0.3.0 - Feb 01, 2022

  • Feature: Process label feature
  • Add fields (comm, exe, ID) to PROCESS_INFO
  • Periodic status reports to syslog
  • Parser bugfixes
  • Add logo provided by Birgit Meyer

v0.2.2 - Dec 22, 2021

Various fixes to parser and coalesce logic

v0.2.1 - Dec 21, 2021

  • Fix for wrong Syslog for error messages

v0.2.0 - Dec 20, 2021

  • Impement translation of numeric/binary values equivalent to auditd log_format=ENRICHED
  • Deal with input streams without EOE messages
  • Provide a library crate
  • Reimplement audit message parser using nom

v0.1.5 - Nov 01, 2021

Fix bug in process tracking implementation that could lead to an infinite loop and break logging

v0.1.4 - Oct 25, 2021

  • Log selected environment variables on execve
  • SELinux policy
  • Workarounds for irregularly formatted kernel/apparmor messages

v0.1.3 - Sep 25, 2021

  • Option to output EXECVE arguments as single string
  • Valid UTF-8 sequences in strings are no longer percent-encoded
  • Add --dry-run switch to only check the configuration file
  • Documentation imprrovements

v0.1.2 - Sep 20, 2021

  • parser: Properly recognize SELINUX AVC and netlabel messages
  • parser: Process partially parseable lines
  • Small error message and documentation improvements

v0.1.1 - Sep 10, 2021

  • Fix musl-libc-specific bug where syslog messages carried an empty name
  • Documentation updates

Information - Updated Feb 12, 2022

Stars: 273
Forks: 24
Issues: 11

pancurses is a curses library for Rust that supports both Linux and Windows

by abstracting away the backend that it uses

pancurses is a curses library for Rust that supports both Linux and Windows

Native Rust library for managing Linux Control Groups (cgroups)

This crate, curently, only supports the original, V1 hierarchy

Native Rust library for managing Linux Control Groups (cgroups)

The Rust spidev seeks to provide full access to the Linux spidev

The following is not an exhaustive demonstration of the Spidev

The Rust spidev seeks to provide full access to the Linux spidev

a minimal Linux kernel module written in rust

A recent build of Rust (latest nightly)

a minimal Linux kernel module written in rust

Rust Linux Worker

The Service executes arbitrary Linux commands on behalf of clients

Rust Linux Worker

Direct, unsafe Rust bindings for Linux's perf_event_open system call

This crate exports unsafe Rust wrappers for Linux system calls for accessing

Direct, unsafe Rust bindings for Linux's perf_event_open system call

A safe, sane Rust interface to libseccomp on Linux

Note: This is not a high-level interface; most functions/methods in this library directly correspond to a libseccomp function

A safe, sane Rust interface to libseccomp on Linux

A transparent TCP to SOCKSv5/HTTP proxy on Linux written in Rust

Transparent TCP proxy with iptables -j REDIRECT or nft redirect to

A transparent TCP to SOCKSv5/HTTP proxy on Linux written in Rust

Linux-Device-Driver-Rust

This is a twain Repo of Linux-Device-Driver is a long time work in which I rewrite all examples in

Linux-Device-Driver-Rust

Simple, performant hot-reloading for Rust

Requires Rust nightly and only works on Linux and Windows for now

Simple, performant hot-reloading for Rust
Facebook Instagram Twitter GitHub Dribbble
Privacy