Tiny Deathstars of Foulness

There are a number of solutions on the market for scanning a Mac for files that have become infected with a virus or macro-virus. Many of these have a negative return on investment. So customers can instead go the open source route to scan files and quarantine them. And customers can use Jamf Pro to enable doing so. This page is meant to provide a quick and dirty guide to doing so, along with how this might be packaged and potentially tracked with Jamf Pro. First, we’ll install and configure a free tool called clamav.

There are a number of ways to install clam. For this example, just to get it done quickly, we’ll use homebrew which is simply brew with the install verb and clamav as the recipe to be brewed:

brew install clamav

This is going to place your configuration files in /usr/local/etc/clamav and these cannot be used as those supplied by default are simply sample configurations. Because the .sample files have a line that indicates they are an “Example” they cannot be used. So we’ll copy the sample configuration files for freshclam.conf and clamd.conf (the demonized version) and then remove the Example line using the following two lines:

cp /usr/local/etc/clamav/freshclam.conf.sample /usr/local/etc/clamav/freshclam.conf; sed -ie 's/^Example/#Example/g' /usr/local/etc/clamav/freshclam.conf
cp /usr/local/etc/clamav/clamd.conf.sample /usr/local/etc/clamav/clamd.conf; sed -ie 's/^Example/#Example/g' /usr/local/etc/clamav/clamd.conf

Next, we’ll need to update the virus definitions for clamav. This can be run without the fully qualified file path but we are going to go ahead and include it as some computers might have another version installed (e.g. via macOS Server):

freshclam -v

The initial scan should cover the full hard drive and can be run as clamscan

sudo /usr/local/bin/clamscan -r — bell -i /

Your routinely run jobs should be setup to a quarantine location. Because all users should be able to see their data that was quarantined we would write this to /Users/Shared/Quarantine. We can then use a standard clamscan to scan the system and then “move” quarantined items to that location and log those transactions to /Users/Shared/Quarantine/Quarantine.txt.

sudo mkdir /Users/Shared/Quarantine
sudo clamscan -r — scan-pdf=yes -l /Users/Shared/Quarantine/Quarantine.txt — move=/Users/Shared/Quarantine/ /

You can then use an Extension Attribute to read the Quarantine.txt file:

#Read Quarantine
result = `cat /Users/Shared/Quarantine/Quarantine.txt`
#Echo Quarantine into EA
echo "<result>$result</result>"

Every environment is different. When combined with standard mrt scans using the built-in malware removal tool for macOS, clamAV can provide a routine added protection to isolate and help you remediate infections. 

Finally, it seems like I have yet to discuss antivirus and malware without getting into the conversation about whether you need it or not. In this post I am in no way taking a side on that argument, and it’s worth mentioning that I’m also not using “antivirus” to exclusively reference viruses but instead including all forms of malware. Rather, I’m exploring options for scanning systems routinely.You can easily run this nightly and parse the quarantine.txt file prior to picking it up with the Extension Attribute routinely in order to provided an additional layer of defense against potential threats to the Mac. Putting all of this into a software package would be rudimentary, and could benefit many organizations without putting our coworkers through the performance hit that many a commercial antivirus solution brings with it.

September 26th, 2018

Posted In: Mac OS X, Mac Security

Tags: , , , ,

September 25th, 2018

Posted In: JAMF, Mac OS X

Tags: , , , ,

September 14th, 2018

Posted In: JAMF

Tags: , , ,

September 7th, 2018

Posted In: JAMF

Tags: , , , ,

September 5th, 2018

Posted In: JAMF, MacAdmins Podcast

Tags: , , , ,

June 29th, 2018

Posted In: MacAdmins Podcast

Tags: , , ,

Been working on a new plugin to embed device details from Jamf Pro into Jira Service Desk. It looks a little like this:

To access the plugin, see the links below.

February 13th, 2018

Posted In: JAMF

Tags: , , , , ,

Tomcat logs events into the system log. You can use the get-wmiobject commandlet to see events. Here, we’ll look at a JSS and view only system events: Get-WmiObject Win32_NTLogEvent -ComputerName $jss -Filter "LogFile='system' We can then use AND to further constrain to specific messages, in this case those containing Tomcat: Get-WmiObject Win32_NTLogEvent -ComputerName $jss -Filter "LogFile='system' AND (Message like '%Tomcat%') We can then further constrain output to those with a specific EventCode with another compound statement: Get-WmiObject Win32_NTLogEvent -ComputerName $jss -Filter "LogFile='system' AND (Message like '%Tomcat%') AND (EventCode=1024) For a comprehensive list of Windows event codes, see You could instead use get-eventlog to see system logs. For example, the following will list the latest 100 entries in the system log: Get-Eventlog -LogName system -Newest 1000 And the following lists the number of unique entries in descending order using Sort-Object, along with the -Property option set to count: Get-Eventlog -LogName system -Newest 1000 | Sort-Object -Property count -Descending And the following would additionally constrain the output to entries with the word Tomcat using the -Message option: Get-Eventlog -LogName system -Newest 1000 -Message "*Tomcat*" | Sort-Object -Property count -Descending And to focus on a server called jss, use the -ComputerName option: Get-Eventlog -LogName system -Newest 1000 -Message "*Tomcat*" -ComputerName "localhost" | Sort-Object -Property count -Descending

July 11th, 2017

Posted In: JAMF, Windows Server

Tags: , , , , , , ,

July 3rd, 2017

Posted In: MacAdmins Podcast

Tags: , , , , , ,

I mentioned mdmclient when I gave the talk on the inner workings of Mobile Device Management, or MDM. There, I spent a lot of time on APNs and profiles, but just kinda’ spoke about mdmclient in terms of it being the agent that runs on macOS to provide mdm parity for the Mac. The mdmclient binary is located at /usr/libexec/mdmclient and provides pretty limited access to see how the Mac reacts to and interprets information coming from a device management provider. I had been meaning to do a write-up on mdmclient and document what it can do since it first shipped. But as luck would have it, @Mosen on the Slacks beat me to the punch with a fantastic resource at So here I’d like to focus on just 3 examples of using mdmclient. The first is to see what insight an MDM has to the applications installed (whether that information is actually committed to a database somewhere or not) using QueryInstalledApps: /usr/libexec/mdmclient QueryInstalledApps Here, we can see an array output of each bundle installed:
{BundleSize = 27457223; Identifier = “com.hipchat.HipChat”; Name = HipChat; ShortVersion = “3.1.6”; Version = “3.1.6”;}
Now, we can end up with duplicates, and so focus on just the unique Identifier keys, as follows: /usr/libexec/mdmclient QueryInstalledApps | grep Identifier | uniq The second iteration is to see installed profiles. The most basic of these, is to see user profiles, which can be obtained using QueryInstalledProfiles, as follows: /usr/libexec/mdmclient QueryInstalledProfiles Now, I could see using the profiles command with the -L option that I have a profile to configure office365 on my machine: profiles -L charlesedge[1] attribute: profileIdentifier: com.jamfsw.office365.a5f0e328-ea86-11e3-a26c-6476bab5f328 There are 1 user configuration profiles installed for ‘charlesedge’ So to see what that same information looks like, when queried from an MDM solution: /usr/libexec/mdmclient QueryInstalledProfiles QueryInstalledProfiles then returns:
({HasRemovalPasscode = 0; IsEncrypted = 0; PayloadContent = ( {PayloadDisplayName = “Charles Edge’s Office 365”; PayloadIdentifier = “”; PayloadType = “”; PayloadUUID = “a5f2ccd9-ea86-11e3-b1e0-6476bab5f328”; PayloadVersion = 1;}); PayloadDescription = “This will configure your Office 365 account for your Mac.”; PayloadDisplayName = “Charles Edge’s Office 365”; PayloadIdentifier = “com.jamfsw.office365.a5f0e328-ea86-11e3-a26c-6476bab5f328”; PayloadOrganization = “JAMF Software”; PayloadRemovalDisallowed = 0; PayloadUUID = “a5f0e328-ea86-11e3-a26c-6476bab5f328”; PayloadVersion = 1; SignerCertificates = ();})
You can then take action based on this type of information, allow you to either fill a database for agent-based management, or simply take action if something is missing, etc. QueryInstalledProfiles covers user profiles. To see system, you’ll need installedProfiles: /usr/libexec/mdmclient installedProfiles | grep "Profile Name" Run without the grep for a considerably more verbose amount of information. Finally, let’s look at one more piece of information, which is the hash for the iTunes Store. That’s a point I’ve made a number of times, that the iTunes account email address is never provided to an MDM, once associated to a device or user on a device. Instead, there’s a hash of the account. These are important with VPP, as it allows for reversing (according to the MDM) which users have claimed which apps, or which users are using a given app, as well as how many devices they’re accessing those from. To see a hash, as an MDM sees it: /usr/libexec/mdmclient QueryAppInstallation | grep iTunesStoreAccountHash There’s a lot more you can do here, and I’m sure we’ll see a lot more over time. However, the work from @mosen combined with the opening up of the documentation on profiles and the mdm protocol helps to shed some light on how things work under the hood, and how we can use these features to provide greater programatic management for the Mac. For example, to grab that iTuneshash from earlier, as a Jamf extension attribute you could use the following:

April 28th, 2017

Posted In: Mac OS X, Mac OS X Server, Mac Security

Tags: , , , , , , ,

Next Page »