macos

Analysis of Apple Unified Logs: Quarantine Edition [Entry 3] – Playing in the Sandbox, Enumerating Files and Directories

While I’ve been researching various queries with these unified logs, I’ve noticed some peculiar but forensically useful entries. I have found many of these entries to be created when I’m browsing directories via Finder. However, they don’t appear to be logged on every directory I browse. Many of these entries also appear to be associated with particular applications/services.

This query is searching for the ‘kernel’ in the process path and ‘Sandbox’ in the sender path. To filter even further, I’ve added a keyword search for ‘file-read-xattr’ in the event message area. 

This query limits the search to the last 10 minutes and during my testing these are directories I specifically browsed to within Finder. Again, I’ll note that I was able to browse to other directories using Finder but these were not logged for whatever reason.

log show --last 10m --predicate 'processImagePath contains "kernel" and senderImagePath contains "Sandbox" and eventMessage contains "file-read-xattr"'

This first example shows entries associated with the ‘garcon’ process which is associated with DropBox. I’m using TaskExplorer here from Objective-See to review information about this process.

These entries are not specific to Dropbox. Looking at my own logs, I also have entries for other applications and system services:

  • App Store

  • Microsoft Excel

  • Microsoft Word

  • MusicCacheExtens[ion] (Long process names get truncated)

  • TVCacheExtension

  • TextEdit

  • com.apple.CloudP[hotosConfiguration?]

  • mediaanalysisd

To look for the Microsoft specific entries, I added another keyword to the query to search the message area for ‘Microsoft’. This should cover all Microsoft products. While the listed directories were directories I recall browsing to, some of these documents I did not specifically open (over and over again) at these times. The application may somehow cache some of these document paths. I did in fact open these documents, just not during these particular times.

log show --predicate 'processImagePath contains "kernel" and senderImagePath contains "Sandbox" and eventMessage contains "file-read-xattr" and eventMessage contains "Microsoft"'

The last example shows TextEdit entries. This may look like I opened or accessed this Zoom chat transcript three times today (4/23/2020), but I sure didn’t. I did however open it up in the past. Again, this appears to be cached somewhere to make it appear that it has been opened.

log show --last 10h --predicate 'processImagePath contains "kernel" and senderImagePath contains "Sandbox" and eventMessage contains "file-read-xattr" and eventMessage contains "TextEdit"'

These entries certainly need to be researched further. Some entries appear to be associated with specific user interactions while others seem to be logged at random due to how an application may work. It is worth noting these entries are a log type of ‘Error’. They may not always be available. (Some are of type ‘Default’ as well).

While the timestamps may not quite match up to specific usage, these entries may still be useful in investigations to show directory contents or documents previously opened.

Analysis of Apple Unified Logs: Quarantine Edition [Entry 2] – sudo make me a sandwich

sandwich.png

The first item in the Unified Logs we will take a look at is a relatively simple one – evidence of the ‘sudo’ command.

In this example I’m attempting to view all the log types (including default and info) for the last day (--last 1d). The search/filter (--predicate) I’m using is looking for the ‘sudo’ process. This column highlighted in pink text.

log show --info --debug --last 1d --predicate 'process == "sudo"'

This has many entries not immediately useful to me, I can create a more specific query to filter the noise out. I’ve removed the arguments for debug and info messages as they do not appear to be needed for this query (they may for others so don’t forget about them!). To get just the entries of interest, I added a keyword search for ‘TTY=’ in the message column (eventMessage).

log show --last 1d --predicate 'process == "sudo" and eventMessage contains "TTY="'

Another technique to look at just the entries associated with a specific use of ‘sudo’ can be to filter by the Process ID (PID) by using ‘processID’. (I replaced info/debug message in the query not because its necessary but purely because its muscle memory for me to do so!)

log show --info --debug --last 1d --predicate 'processID == 26220

I tried to get a bit creative with ‘sudo’, so I incorrectly put a password in (twice) while trying to use ‘sudo -s’. I then put in the correct password. Note, I’m using the ‘last’ argument to only look at events in the last 20 minutes. Very useful if you are trying to research a certain scenario without having to scroll through millions of log entries!

log show --last 20m --info --debug --predicate 'process == "sudo" and eventMessage contains "TTY="'

While we’re here, it would be a shame not to take a quick look at ‘su’ as well. Oops, looks like I got the password wrong while doing a ‘su janedoe’ three times before finally getting it right.

I’ve changed this query a tiny bit. The process was changed to ‘su’ instead of ‘sudo’ and the keyword in the message from changed from ‘TTY=’ to ‘tty’ to capture these entries.

log show --last 20m --info --debug --predicate 'process == "su" and eventMessage contains "tty"'

Finally let’s get a query to find all the relevant ‘sudo’ and ‘su’ commands. I created a slightly more complex query that combines searching for two different processes (sudo and su) while still filtering for ‘tty’ in the message.

log show --last 20m --info --debug --predicate '(process == "su" or process == "sudo") and eventMessage contains "tty"'

To make query slicker , we can use ‘beginswith’ to just look for ‘su’ in the two processes.

log show --last 30m --info --debug --predicate 'process beginswith "su" and eventMessage contains "tty"'

And one last one, because I know you NEED to know!

incident.png

Big thanks to one of my favorite comics for the classic content, these never get old! XKCD by Randall Munroe

Analysis of Apple Unified Logs: Quarantine Edition [Entry 1] – Converting Log Archive Files on 10.15 (Catalina)

Please review this post first as it contains an update to this post. Keeping the contents of this blog intact for reference purposes only.


Apple introduce Unified Logging many years ago in 10.12 and has constantly been changing it since its introduction. My main problem is usually using the ‘log’ utility. It has changed over time and those changes are not documented nor is the current documentation adequate in many cases.

My most recent adventure using ‘log’ came when I was running through my course image to create a logarchive bundle from a dead system image. This particular system was running 10.13.1 and will have to be read from whatever macOS the student is running at the time. Silly me for thinking that ‘log’ would always “just work”™️. 

When students upgraded to 10.14.x, they could still create the log archive via the manual process of doing a recursive copy of the /private/var/db/diagnostics and /private/var/db/uuidtext directories into a *.logarchive directory bundle. Works great! Even works (worked?) on iOS devices! On 10.14.x systems we have “force” it into the proper format but it was readable by ‘log’ and the timestamps appeared correct.

When 10.15 came out, this changed. Attempting to create and read the same data produces a corruption error. There is no option to “force” it.

I have been racking my brain and researching this on and off since Catalina was introduced. How the heck can I make this older logarchive readable using a newer versions of macOS?

Comparing the older and newer logarchive formats, they are nearly the same except for a few items. One difference I focused on was the key OSArchiveVersion in the Info.plist. On 10.14 and 10.15 they are on version 4, while on 10.13 they were on version 3. (Note: Doing a recursive copy from a dead image does not create this Info.plist file in the root of the logarchive bundle.)

In my first test, I simply added an Info.plist file to the root of the logarchive bundle with one key, OSArchiveVersion. For the value I tried 4 – why not just give it what it wants. (This testing was done on 10.15.3). 

Great, it parses! However the timestamps are not quite right. I’m lucky to have a dataset that I’m familiar with and have a course labs with specific log entries and their timestamps to validate the conversion. This particular entry I’ve blogged about before – this entry should have the timestamp 2018-02-26 01:49:08.719840+0000. You can see it is only off by a smidge, what gives? These things bother me, so I decided to dive deeper.

Something else is part of this conversion. (I knew it would have been too easy to just change a plist value!)

Next, I changed the value of OSArchiveVersion to a 3. In theory, I hoped to upgrade it to version 4 but still got the same wrong timestamp. I was also not even offered the “force” option. (I really should have known it would have been too easy to just change a plist value!)

In a moment of ‘why not, let me just try this for fun’, I changed the value to 2. …and it actually WORKED! It freaking worked! I had to force it and the timestamps matched up with my original values.

I would love to know why this worked. It makes no logical sense to me.

What happens if I just go straight to version 2 for OSArchiveVersion? It also worked!

A quick command to get this done:

/usr/libexec/PlistBuddy -c "Add :OSArchiveVersion integer 2" galaga.logarchive/Info.plist

What changes in this “forced” conversion? 

I created a new copy of the logarchive bundle and put the Info.plist with OSArchiveVersion = 2. Using one of my favorite file system monitoring tools, fsmon [https://github.com/nowsecure/fsmon]. I was able to monitor what the --force flag changed in the logarchive bundle.

It deletes the timesync directory (and the *.timesync file within) then creates it again with a different timesync file. Also as expected the Info.plist changes from 2 to 4.

What the heck are these timesync files? Not entirely sure, they are binary files that obviously has some sort of time syncing purpose which is why the timestamps now match up. Perhaps I will dig into these another time.

Afterthoughts 

I’m not sure why 10.15 refuses to convert log archives as 10.14 did. Perhaps it is a bug, maybe it is intentional but it sure does make doing forensics difficult. I’m sure this will cause problems with newer versions of macOS as well as other platforms. I’ve heard the same problem exists with iOS, which again will likely be another blog entry when I get to testing iOS specifically.

It does however bring up a good lesson…do not implicitly trust timestamps. I’ll state this over and over until I can get people to test these things. I had it easy with this one because I had known test data – but that doesn’t work so well with random case data.

Below is the mapping of macOS version to Unified Logs Archiver versions (found in the Info.plist files while doing a ‘log collect’ command on a live system.) There are many empty spots – I have no idea if it will help or not but I tried to document it here. If you can help fill it in, I would be grateful please contact me. (Seems most folks update to the latest!)

Log Archive Mapping Table