Better Auditing in macos

What can be improved in logging events in macos? The default approach and settings are actually superb for collecting a broad scope of stuff for general troubleshooting. Anyone curious enough can use to look at logfiles created by the ASL (short for the Apple System Log) and gain insight into how the hidden machinery works.

However, if we want deeper insight into user actions and behaviors, it’s necessary to enable more granular auditing in order to get more value from logs.

Patrick Wardle‘s talk at ShmooCon in 2018 is an inspiration, where he discussed auditing in cool way –>

Meanwhile, as Apple continues to iterate and improve their unified logging strategy, ASL still generates only simple logs by default, fine for home users and maybe small biz but in regulated industry environments subject to compliance, actual auditing is required.

Auditing is worthwhile for a few reasons:

  • In environments requiring security compliance of any kind, logs aren’t enough – auditing is required
  • Regular analysis of audit logs can help us identity suspicious activity that may otherwise be elusive
  • Audit logs are excellent sources of truth in a breach scenario and can make Digital Forensics and Incident Response (DFIR) a lot quicker and easier
  • Pure insight that can be shared during post mortem analysis of security incidents
  • Valuable for use by intrusion detection on critical systems
  • It’s not uncommon to find previously undiscovered vulnerabilities using this info and report them to Apple
  • Audit analysis provides insight into tuning security for hardware and helps refine our security model
  • Auditing is a great addition to every defense-in-depth strategy

Apple is still iterating on the OpenBSM implementation in place from the early days (remember when we called it OS X?) thanks to their integration of GNU-licensed, open source tools. Apple introduced OpenBSM to macos specifically to provide audit capabilities though there are some pros and cons to be aware of:

  • Strengths: Offers insights into security-related events, like user logins, changes to system configurations, file open/read/write, and network activities and access.
  • Limits: Not every type of security-related event is auditable (such as third-party agents/tools), and the more detail we audit for in logs takes up more space, which means we have to balance sheer volume/capacity/performance against granularity/visibility (this is why tuning is important).

I’m going to reiterate this, again and again, because it is a mistake everyone makes the first time they head down this path (I’ve made it, too!). We need to be careful with our security audit configurations because audit data can accumulate quickly when configured for a lot of details, which rapidly increases the size of logfiles. Always be sure to consider requirements associated with the systems being audited, such as performance, disk space, and availability.

How Can We Improve Auditing?

We can audit all kinds of events but – what kinds of events? Well, while it’s not practical in the wild to audit everything, we have to tread carefully, as mentioned above.

  • Even if stored in binary format the sheer amount of audit data generated can be massive – be mindful that logfiles can grow rapidly in size
  • Collection and increased reporting has a measurable impact on device performance as auditing is written to the filesystem and doing so requires resources from the system

On a typical macos user host we need to be cautious and intentional about configuring the audit policy to balance security and availability requirements. No one wants to solve a situation where client machines are misconfigured and seize up for running out of space on the filesystem (i.e. hard drive).

So we start incrementally.

In macos (past and present) auditing is configured at /etc/security/audit_control

The default config looks like this:


For our purposes here, we’re going to discuss a good starting point for changes that won’t bork anything. For much detail about this file, please refer to the BSM Service Tasks documentation.

Here’s a quick breakdown of this config file:

dir:/var/audit [where audit data is written to]
flags:lo,aa [specified classes of events to be audited for all users]
minfree:5 [minimum free-disk-space available to the filesystem before auditing stops]
naflags:lo,aa [defines what's audited when actions aren't attributable to a user]
policy:cnt,argv [these set audit policy flag based on specific behavior]
filesz:2M [maximum size for logs before they're rotated]
expire-after:10M [log will expire and be removed when it hits 10MB in size]

flagsSpecifies one of the many classes that can be audited for all users
naflagsDefines classes audited when actions can’t be attributed to a specific user
policyGlobal audit policy across users and behaviors

Here are a couple basic things to keep in mind, especially if you’re new to all this:

  • The default location log data is being sent to on the local filesystem is fine: /var/audit
  • There’s no need to change that initially but keep in mind the size of that directory is going to grow in direct proportion to the amount of additional auditing and granularity to the auditing you configure.
  • minfree means that at least 5% of the filesystem’s total space must be available otherwise all audit activities will halt but keep in mind other services and tools aren’t aware of this, which means the filesystem will still fill up because other stuff is still running, generating logs, and taking up space still, too. PLEASE BE MINDFUL OF THIS.

Okay, so that’s a basic understanding of the configuration. Here’s a great way to get started enabling more auditing:

  • A great starting set of classes to config things for is: lo, ad, na.
    • login/out events is (lo)
    • admin events is (ad) and this looks for things like filesystem mounts, creation of users, etc.
    • non-attributable events is (na), which is meant to log actions that are more elusive – careful with this one, though, because a LOT of na events happen on a system and this can lead you down some verrry deeeep rabbit holes.

In our first iteration, we can set flags for logins and stuff but want to maintain cnt and argv so as to be not super-aggressive and not halt any auditing (because then what’s the point beside not shutting the system down? lol) but we should be prepared to address tuning as this config evolves – this can get deep and this post is only scratching the surface.

Here’s the complete set of flags for those looking to bend it to their will:

Policy FlagDescription
cntAllow processes to continue running even though events are not being audited. If not set, processes will be suspended when the audit store space is exhausted. Currently, this is not a recoverable state.
ahltFail stop the system if unable to audit an event – this consists of first draining pending records to disk, and then halting the operating system.
argvAudit command line arguments to execve(2).
argeAudit environmental variable arguments to execve(2).

I recommend starting small, increment everything slowly, intentionally, collect a bit more and a bit more as quantifiable chunks of time pass (a day or three or week or two at-a-time), then review, tweak, repeat.

Typically, after 2 or 3 iterations we can find the right balance for each unique environment. Good luck in your audit quest.

Big love for inspiration: