### The Challenge of Tracking SSH Connections Without System Logs About three weeks ago, during my study of the SSH login and logout events for the **FOR518 course by Sara Edwards**, I became curious about how to view SSH connection records using macOS's unified logs. It’s easy to access connection details using the traditional system.log file, but I started wondering: What if this file is deleted? It’s well-known that attackers may delete logs in the `/var/log/` directory to cover their tracks. So, I set out to explore how I could accurately track SSH connection times without relying on the system log. My first attempt involved using macOS’s log show utility tool `log show` , after collecting my unified logs. While the tool provides a wealth of information, it was overwhelming due to the sheer volume of records. Without narrowing the scope to the correct process, it became difficult to pinpoint the exact connection times amidst the **"noise"** from other system activities. On the flip side, I found it easier to determine when SSH sessions ended (logoffs) since these events are typically recorded with the phrase "**Disconnected from User <username>...**", which is easier to filter for. To delve deeper into this, I conducted a research test in collaboration with **[Mr. Derek Eiri](https://www.linkedin.com/in/dc80/)** and my friends, **[Khaled Allam](https://www.linkedin.com/in/a1l4m/)**, **[Islam Mostafa](https://www.linkedin.com/in/islam-mostafa-62b161b4/)** and [**Mahmoud Swelam**](https://www.linkedin.com/in/mahmoud-swelam/). Together, we tested how to use unified logs to track SSH connection activities effectively, even in the absence of traditional system log files. This blog documents our findings and the tools we used to make the process more straightforward. ### Machines ###### 1. macOS High Sierra (10.13) ###### 2. macOS Mojave (10.14) ###### 3. macOS Big Sur (11.7.1) ###### 4. macOS Monterey (12.5) ###### 5. macOS Sonoma (14.6.1) ### Tools ###### 1. log show (mac native Utility tool) ###### 2. [unifiedlog_parser](https://github.com/mandiant/macos-UnifiedLogs) (MANDIANT Tool) ### Unified Logs History Beginning with macOS 10.12 (Sierra), Apple introduced a key change to how logging was done on their systems. This new logging system replaced common Unix logs with macOS Unified Logs. These logs can provide forensic investigators a valuable artifacts (process execution, browser history, Logons to the macOS system, command execution,....) to aid in investigating macOS systems or other Apple devices. When you **restart** or **shut down** your Mac, the system temporarily halts logging. While the macOS logging system is designed to flush data to disk regularly, some logs may still reside in memory and may not be fully written to disk before the shutdown. However, once the system reboots, the unified logs resume, and any previous log entries are preserved, as long as they fall within the system's log retention settings. The continuity of the logs is maintained across restarts, provided the logs have not been overwritten. > if you shut down the system abruptly (e.g., forced shutdown, or a system crash), it's possible that some logs that were still in memory haven’t been written to disk. The Unified Logs are composed of three components: 1. tracev3 files – Binary files containing the log entries `/private/var/db/diagnostics/` 2. UUID files – Binary files containing metadata for a log entry `/private/var/db/uuidtext/{00-FF,dsc}` 3. timesync files – Binary files containing timestamp metadata associated with a log entry `/private/var/db/diagnostics/Timesync The Unified Logs contain a large amount of valuable information for forensic investigations such as: ``` - Process path associated with log entry - Library path associated with log entry - PID - EUID - Timestamp for the log entry in Unix Epoch - Log Type – Ex: Default, Error, Debug, Info, Fault - Event Type – Ex: Log, Signpost, Activity, Statedump, or Simpledump - Subsystem – Typically the bundle ID associated with log entry, ex: com.apple.news - Category – An optional addition to the subsystem that can be used to associate log entries with specific categories. Ex: com.apple.news has the categories NewsToday and Network. - Log Message ``` --- 🚩 It's preferred to parse Unified-Logs using mac native tool `log show` and the mac should be with same version as the format of the logs changes with each version. **Mandient tool** `unifiedlog_parser` overrides some log records, so there will be missing reords in the output file. ![image](https://hackmd.io/_uploads/Sk2L8pH81l.png) --- ## Machine 1 High Sierra (10.13) - This is **my mac machine** And I will explore each step till the final test that will get us easy-cleaner records matches all times needed in Investigation. - This test has been applied multiple times, but I focused on obtaining a specific number of log-on and log-off events to make the process easier for you. | Log on | Log off | processID| | -------- | -------- |----- | | 2024-12-16 15:20:08 | 2024-12-16 15:25:20 |368 | | 2024-12-16 15:31:25 |2024-12-16 15:34:04 |441 | Firstly, We will consider `/var/log/system.log` artifact to make our results clear and lastly we will show you how you can depend on **Unified Logs** only. In macOS system, When user login into system through **ssh**, **GUI** and **Terminal Program**, The `system.log` file will record a `USER_PROCESS` event for **logins** and a `DEAD_PROCESS` event for **logoffs**. ![image](https://hackmd.io/_uploads/r1FZ3ApEkg.png) ![image](https://hackmd.io/_uploads/HySNhRaEyx.png) Those are the exact time for ssh connections. If you noticed the processID is also recorded. Now, we will retrieve this information from the Unified logs using two approaches. ### 1- Using system.log file As seen in the `system.log` file, the timestamps and process IDs are present. So, we will search with processID and timestamp ``` log show macOS-High-Sierra.logarchive/ --info --style compact --predicate 'processID==368' --start "2024-12-16 15:20:08" log show macOS-High-Sierra.logarchive/ --info --style compact --predicate 'processID==441' --start "2024-12-16 15:20:08" ``` We will obtain useful results at only two key moments: when the connection starts and when the connection ends. ![image](https://hackmd.io/_uploads/BJQ90RTNke.png) And for the **2nd ssh connection**.. ![image](https://hackmd.io/_uploads/Sk_xyJR4Jx.png) This approach is **highly effective** and directly targets the information we need **(ip, port, time)**, without any noise. **However**, it relies solely on the **process ID** and **timestamp** from the `system.log` file. **Mr Derek**, also used **only process IDs** on **Sonoma version** to get the start and end time easly. ![image](https://hackmd.io/_uploads/HkLqZkCNkx.png) **However**, this approach ultimately requires you to know the time or the process ID, both of which are available in the **system.log** file. ### 2- Without system.log file This approach aims to use a highly refined and tested filter to obtain the exact log-on and log-off times **in sequence**, without relying on the process ID or even the timestamp (and without using the system.log file). #### Filter : ``` log show macOS-High-Sierra.logarchive/ --info --style compact --predicate 'eventMessage contains "sshd" And eventMessage contains "session"' ``` - **3 records with same time (log on)** - **2 records with same time (log off)** ![image](https://hackmd.io/_uploads/SkEkHk0Eye.png) **Green** : log on records **Red** : log off records Now that we know the log-on and log-off timestamps, there are multiple process IDs, and one of them should match the one in the system.log file. However, in this approach, we assume we don't know which process ID is the correct one. Instead, we have the timestamps and a few process IDs that we can filter through to retrieve the IP address and port of the SSH connection. ![image](https://hackmd.io/_uploads/BJ69LJAN1e.png) #### Verifying using unifiedlog_parser Tool Based on the small number of process IDs, we identified the process ID that matches the `"Disconnected from user <username>"` event. ``` ./unifiedlog_parser.exe -i D:\dfir\macOS-High-Sierra.logarchive\ -o output-High-Sierra/out.csv ``` ![image](https://hackmd.io/_uploads/rybhteCNJx.png) ![image](https://hackmd.io/_uploads/rJryqeAEyg.png) #### Findings - 🚩 **Log ON** event will have `Activity` as **Event Type** but, **Log OFF** event will have `Log` - 🚩 **Log ON** event also will have `Create` as **Log Type** but, **Log OFF** will be `Info`. - 🚩 If the Attacker request to connect through ssh, that will be recorded in Unified-Logs even if the connection didn't succeed. However, our theory is working and all is good, We can get our resutls clear. ![image](https://hackmd.io/_uploads/BybaeSLUkx.png) Now let's see if this works on Mojave, Monterey, Big Sur and Sonoma.... ## Machine 2 macOS Mojave (10.14) Based on the test conducted by **Islam Mostafa**, here are the results: | Log on |Log off | processID | | -------- | -------- | -------- | | 2025-01-03 22:29:43 | 2025-01-03 22:31:58 | 916 | |2025-01-03 22:32:25|2025-01-03 22:33:40|942| |2025-01-03 22:33:49|2025-01-03 22:34:59|984| ![WhatsApp Image 2025-01-04 at 00.40.10_027e8431](https://hackmd.io/_uploads/BynXIVIL1e.jpg) ![WhatsApp Image 2025-01-04 at 00.40.45_ad0ba858](https://hackmd.io/_uploads/SJZVINIUkg.jpg) #### Filter : ``` log show mylogs.logarchive/ --info --style compact --predicate 'eventMessage contains "sshd" And eventMessage contains "session"' ``` ![image](https://hackmd.io/_uploads/HJOWu4IIye.png) > There is only one record that doesn't belong to any actual ssh connection, it's is a request to connect but the connection didn't succeed. - **3** records **Log ON** - **2** records **Log OFF** #### Verifying using unifiedlog_parser Tool Based on the small number of process IDs, we identified the process ID that matches the `"Disconnected from user <username>"` event. ``` ./unifiedlog_parser.exe -i D:\dfir\Mojave.logarchive -o output-Mojave/out.csv ``` ![image](https://hackmd.io/_uploads/ByOFKNI8Jl.png) ![image](https://hackmd.io/_uploads/SyF6YNUU1e.png) ![image](https://hackmd.io/_uploads/SJfW9488ke.png) ## Machine 3 macOS Big Sur (11.7.1) Based on the test conducted by **Khaled Allam**, here are the results: | Log on | Log off | processID| | -------- | -------- |----- | | 2024-12-16 07:33:10 | 2024-12-16 07:35:07 |523 | | 2024-12-16 07:39:2548 |2024-12-16 07:41:04 |610 | ![image](https://hackmd.io/_uploads/HJ7RvJC4kx.png) #### Filter : ``` log show system_logs.logarchive/ --info --style compact --predicate 'eventMessage contains "sshd" And eventMessage contains "session"' ``` ![image](https://hackmd.io/_uploads/rkh0OJA4ke.png) #### Verifying using unifiedlog_parser Tool Based on the small number of process IDs, we identified the process ID that matches the `"Disconnected from user <username>"` event. ``` ./unifiedlog_parser.exe -i D:\dfir\Big-Sur\system_logs.logarchive\ -o output-Big-Sur/out.csv ``` ![image](https://hackmd.io/_uploads/BJQ_VgCVJx.png) ![image](https://hackmd.io/_uploads/B1cQNlC4Jg.png) ## Machine 3 macOS Monterey (12.5) Based on the test conducted by **Mahmoud Swelam**, here are the results: | Log on | Log off | processID | | -------- | -------- | -------- | | 2025-01-03 14:03:01 | 2025-01-03 14:06:44 | 24771 | ![image](https://hackmd.io/_uploads/BJgs59BLyg.png) #### Filter : ``` log show mylogs.logarchive/ --info --style compact --predicate 'eventMessage contains "sshd" ``` ![image](https://hackmd.io/_uploads/S17gK5H8kl.png) #### Verifying using unifiedlog_parser Tool ``` ./unifiedlog_parser.exe -i D:\dfir\Monterey\system_logs.logarchive\ -o output-Monterey/out.csv ``` The output file out.csv was too damn big (11G) XD; so, I used `grep` for our needs (process id, user, ip, port) ``` strings out.csv | grep "/usr/sbin/sshd" | grep "Disconnected" # this will be enough to get the user, ip, port and processID ``` ![image](https://hackmd.io/_uploads/HJXkzjHUJg.png) ![image](https://hackmd.io/_uploads/BkpTyiSI1x.png) ## Machine 4 macOS Sonoma (14.6.1) Based on the test conducted by **Mr Derek Eiri**, here are the results: | Log on | Log off | processID| | -------- | -------- |----- | | 2024-12-15 23:00:07 | 2024-12-15 23:00:23 |6350 | #### Filter : ``` log show system_logs.logarchive/ --info --style compact --predicate 'eventMessage contains "sshd" ``` ![image](https://hackmd.io/_uploads/rkwcYkRVkl.png) #### Verifying using unifiedlog_parser Tool Based on the small number of process IDs, we identified the process ID that matches the `"Disconnected from user <username>"` event. ``` ./unifiedlog_parser.exe -i D:\dfir\Sonoma\system_logs.logarchive\ -o output-Sonoma/out.csv ``` ![image](https://hackmd.io/_uploads/B14KZgRE1x.png) ## Summary of Steps 1. Use filter ``` log show system_logs.logarchive/ --info --style compact --predicate 'eventMessage contains "sshd" ``` 2. `3 records` with same timestamp `[log on]` 3. `2 records` with same timestamp `[log off]` 4. Run `unifiedlog_parser` tool. ``` ./unifiedlog_parser.exe -i system_logs.logarchive\ -o output/out.csv ``` 5. filter with processIDs you got from filter. 6. Once you find `"Disconnected from user <username>"`, This is the process ID found in the system.log file. You will then see two timestamps that match the times obtained from the filter, along with the corresponding IP address and port. ### Additional Filters 1. For **Log OFF** Events ``` log show mylog.logarchive --predicate 'processImagePath contains[cd] "/usr/sbin/sshd" And eventMessage contains "Disconnected"' log show mylog.logarchive --predicate 'processImagePath contains[cd] "/usr/sbin/sshd" And eventMessage contains "Received disconnect from"'' ``` ## Conclusion: In this blog, we explored an alternative and effective method for tracking SSH logins and logoffs using macOS Unified Logs, without relying on the traditional system.log file. Through the combination of precise filters and timestamps, we demonstrated how to capture key SSH connection events, even when process IDs are not directly available. By narrowing our search to specific times and process IDs, we were able to extract valuable details, such as the IP address and port of the SSH connection, with minimal noise. Our approach, tested and refined through collaboration with colleagues, highlights a robust way of monitoring SSH activity in a way that circumvents potential log deletion by attackers, offering a more reliable and secure method for auditing SSH connections. While it requires some effort to fine-tune the process, the results speak for themselves, proving that even without traditional system logs, Unified Logs can serve as a powerful tool for tracking system events in macOS.