Tiny Deathstars of Foulness

Just some one-liners you may find useful… I’ve written about codesign a few times in the past. To see a detailed description of how an app was signed:

codesign -dvvvv /Applications/

This also gives you the bundleID for further inspection of an app. But there are a number of tools you can use to check out signing and go further into entitlements and sandboxing. You can check the 

asctl sandbox check --bundle

The response would be similar to 


signed with App Sandbox entitlements

In the above, we see that Outlook has entitlements to do some stuffs. But where do you see an indication of what it can do? There are a number of sandbox profiles located in /usr/share/sandbox and the more modern /System/Library/Sandbox/Profiles/ and Versions/A/Resources inside each framework should have a .sb file – but those are the Apple sandbox profiles. Additionally, you can see what each app has access to using the container_check.rb script:

/usr/libexec/AppSandbox/container_check.rb -c --for-user charles.edge --stdout

Simply strip the -c followed by the container and you’ll get a list of all apps. When you’re building and testing sandbox profiles for apps you plan to compile, you may want to test them. To do so, use sandbox

sandbox-exec -f /usr/share/sandbox/ /Applications/ 

As of 10.14, any app looking to access Location Services, Contacts, Calendars, Reminders, Photos, Camera, Microphone, Accessibility, the hard drive, Automation services, Analytics, or Advertising kit will prompt the user to accept that connection. This is TCC, or Privacy Preferences. You can programmatically remove items but not otherwise augment or view the data, via the tccutil command along with the only verb currently supported, reset: 

tccutil reset SERVICE com.smileonmymac.textexpander

October 1st, 2018

Posted In: Mac OS X, Mac Security

Tags: , , , , , ,

Reporting on application usage is an interesting topic on the Mac. This is done automatically with a number of device management solutions. But there are things built into the OS that can help as well.

mdls "/Applications/" -name kMDItemLastUsedDate | awk '{print $3}'

Now, if you happen to also need the time, simply add ,$4 to the end of your awk print so you can see the next position, which is the time. Additionally, a simple one-liner to grab the foreground app via AppleScript is:

osascript -e 'tell application "System Events"' -e 'set frontApp to name of first application process whose frontmost is true' -e 'end tell'

That’s pretty much all I had to say about that.

September 27th, 2018

Posted In: Mac OS X, Mac Security

Tags: , , ,

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: , , , ,

I’ve been making guides to macOS Server since Server 2:
And along the way, I’ve also sold plenty of books on Mac Servers and gotten a lot of opportunities I might not have gotten otherwise. So thank you to everyone for joining me on that journey. After teaching so many how to use the services that Apple made available in their server operating system, when they announced they’d no longer be making many of the services my readers have grown dependent upon, I decided to start working on a guide on moving away from macOS Server. 
And then there are tons of all-in-one small business servers solutions, including Buffalo, Qnap, NetGear’s ReadyNAS, Thecus, LaCie, Seagate BlackArmor, and Synology. Because I happen to have a Synology, let’s look at setting up the same services we had in macOS Server, but on a cheaper Synology appliance:

September 25th, 2018

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

Tags: , , , , , , , , , ,

macOS now comes with a vulnerability scanner called mrt. It’s installed within the bundle in /System/Library/CoreServices/ and while it doesn’t currently have a lot that it can do – it does protect against the various bad stuff that is actually available for the Mac. To use mrt, simply run the binary with a -a flag for agent and then a -r flag along with the path to run it against. For example, let’s say you run a launchctl command to list LaunchDaemons and LaunchAgents running:

launchctl list

And you see something that starts with Let me assure you that nothing should ever start with that. So you can scan it using the following command: 

sudo /System/Library/CoreServices/ -a -r ~/Library/LaunchAgents/

What happens next is that the bad thing you’re scanning for will be checked to see if it matches a known hash from MRT or from /System/Library/CoreServices/XProtect.bundle/Contents/Resources/XProtect.yara and the file will be removed if so. 

A clean output will look like the following:

2018-09-24 21:19:32.036 mrt[48924:4256323] Running as agent

2018-09-24 21:19:32.136 mrt[48924:4256323] Agent finished.

2018-09-24 21:19:32.136 mrt[48924:4256323] Finished MRT run

Note: Yara rules are documented at For a brief explanation of the json you see in those yara rules, see

So you might be saying “but a user would have had to a username and password for it to run.” And you would be correct. But XProtect protects against 247 file hashes that include about 90 variants of threats. Those are threats that APPLE has acknowledged. And most malware is a numbers game. Get enough people to click on that phishing email about their iTunes account or install that Safari extension or whatever and you can start sending things from their computers to further the cause. But since users have to accept things as they come in through Gatekeeper, let’s look at what was allowed.

To see a list of hashes that have been allowed:

spctl --list

When you allow an app via spctl the act of doing so is stored in a table in 

sudo sqlite3 /var/db/SystemPolicy

Then run .schema to see the structure of tables, etc. These include feature, authority, sequence, and object which contains hashes.

On the flip side, you can search for the attribute set to

xattr -d -r ~/Downloads

And to view the signature used on an app, use codesign:

codesign -dv

To sign a package:

productbuild --distribution mycoolpackage.dist --sign MYSUPERSECRETIDENTITY mycoolpackage.pkg

To sign a dmg:

codesign -s MYSUPERSECRETIDENTITY mycooldmg.dmg

However, in my tests, codesign is used to manage signatures and sign, spctl only checks things with valid developer IDs and spctl checks items downloaded from the App Store. None of these allow for validating a file that has been brought into the computer otherwise (e.g. through a file share). 

Additionally, I see people disable Gatekeeper frequently, which is done by disabling LSQuarantine directly:

defaults write LSQuarantine -bool NO

And/or via spctl:

spctl --master-disable

Likewise, mrt is running somewhat resource intensive at the moment and simply moving the binary out of the directory will effectively disable it for now if you’re one of the people impacted.

September 24th, 2018

Posted In: Mac OS X, Mac Security

Tags: , , , , ,

Firefox describes their malware posture at which heavily leverages Google SafeBrowsing, as do many a browser. Settings for SafeBrowsing are set in the browser.safebrowsing.downloads.remote.enabled pref. To lock this pref, you would need to create an autoconfig.js file in 

/Applications/ that points to a firefox.cfg file with a lock pref in it. To do so, create the autoconfig.js file and paste in these settings:

// Configure SafeBrowsing
pref("general.config.filename", "firefox.cfg");
pref("general.config.obscure_value", 0);

Then create the firefox.cfg file and paste in these settings:

// Configuring SafeBrowsing
lockPref("browser.safebrowsing.downloads.remote.enabled", TRUE)

Live Firefox preferences can be seen at /Users/charles.edge 1/Library/Application Support/Firefox/Profiles/*.default. Because SafeBrowsing is enabled by default, you shouldn’t see it listed unless it’s been disabled. But you can confirm it’s doing its thing by parsing the contents of these settings:

user_pref("browser.safebrowsing.provider.google4.lastupdatetime", "1537457871853");
user_pref("browser.safebrowsing.provider.google4.nextupdatetime", "1537459685853");
user_pref("browser.safebrowsing.provider.mozilla.lastupdatetime", "1537457872202");
user_pref("browser.safebrowsing.provider.mozilla.nextupdatetime", "1537461472202");

September 21st, 2018

Posted In: Mac OS X, Mac Security

Tags: , , ,

OpenBSM is a subsystem that has been installed on the Mac for some time. OpenBSM provides that ability to create and read audit logs based on the Common Criteria standards.

Audit Logs

The quick and easy way to see what OpenBSM is auditing is to cat the /etc/security/audit_control file:

cat /etc/security/audit_control

The output displays the directory of audit logs, as well as what is currently being audited. By default the configuration is as follows:

# $P4: //depot/projects/trustedbsd/openbsm/etc/audit_control#8 $

You can then see all of the files in your audit log, using a standard ls of those 

ls /var/audit

As you can see, the files are then stored with a date/time stamp naming convention. 

20180119012009.crash_recovery 20180407065646.20180407065716 20180407073931.20180407074018
20180119022233.crash_recovery 20180407065716.20180407065747 20180407074018.20180407074050
20180119043338.crash_recovery 20180407065747.20180407065822 20180407074050.20180511030725
20180119134354.crash_recovery 20180407065822.20180407065853 20180511030725.crash_recovery
20180208172535.crash_recovery 20180407065853.20180407065928 20180616025641.crash_recovery
20180219133137.crash_recovery 20180407065928.20180407070004 20180624022028.crash_recovery
20180312153634.crash_recovery 20180407070004.20180407070036 20180718235941.crash_recovery
20180312160131.crash_recovery 20180407070036.20180407071722 20180720031150.crash_recovery
20180322141701.crash_recovery 20180407071722.20180407072215 20180724021901.crash_recovery
20180330190040.crash_recovery 20180407072215.20180407072259 20180728173033.crash_recovery
20180330191420.20180407064622 20180407072259.20180407073747 20180907031058.crash_recovery
20180407064622.20180407065616 20180407073747.20180407073836 20180911021141.not_terminated
20180407065616.20180407065646 20180407073836.20180407073931 current

The files are binary and so cannot be read properly without the use of a tool to interpret the output. In the next section we will review how to read the logs. 

Using praudit

Binary files aren’t easy to read. Using the praudit binary, you can dump audit logs into XML using the -x flag followed by the path of the log. For example, the following command would read a given log in the above /var/audit example directory:

praudit -x 20180407065747.20180407065822

One record of the output would look as follows

<record version="11" event="session start" modifier="0" time="Sat Apr 7 01:58:22 2018" msec=" + 28 msec" >
<argument arg-num="1" value="0x0" desc="sflags" />
<argument arg-num="2" value="0x0" desc="am_success" />
<argument arg-num="3" value="0x0" desc="am_failure" />
<subject audit-uid="-1" uid="root" gid="wheel" ruid="root" rgid="wheel" pid="0" sid="100645" tid="0" />
<return errval="success" retval="0" />

In the above output, you’ll find the time that an event was logged, as well as the type of event. This could be parsed for specific events, and, as an example, just dump the time and event in a simple json or xml for tracking in another tool. For example, if you’re doing statistical analysis for how many times privileges were escalated as a means of detecting a bad actor on a system.

You can also use the auditreduce command to filter records. Once filtered, results are still in binary and must be converted using praudit.

September 18th, 2018

Posted In: Mac OS X, Mac Security

Tags: , , , ,

Most phishing sites follow a known pattern. And people like to flag bad sites. So Google and a few other organizations, such as have a collection of feeds that can be leveraged by software vendors to provide a warning or flat-out block potentially fraudulent sites. If a piece of malware is found, even if buried deep in a site, the site will likely get picked up by a robot or reported by a user. Robots can pick up a lot, as people who exploit WordPress sites and stuff like that are often after playing a numbers game. Harvesting hundreds of thousands or email address and sending phishing emails. It only takes one person to give you banking information Given that they’re just dropping a file in an open web directory, the attacker might otherwise go months before enough people complained and the web host shut them down.

Google Safe Browsing came about similar to how realtime blacklisting has worked with email for a long time. Sites are listed and then blocked as needed. But privacy works differently with web browsing and so Google added a bunch of cool stuff that is described at Basically though, there are some encrypted files on nearly every computer running Safari, Firefox, Chrome, etc that contains information about bad sites. This is updated fairly regularly, as well as some signatures of known nastiness and a little machine learning magic so that the systems are able to react to emerging threats.

In case you’re interested in writing your own tools, Google Safe Browsing has an API, which is documented at API Documentation.

So what is sent to Google? Only information from unsigned executables (or when the signature isn’t accepted) is sent to the Google SafeBrowsing service. The implementation and also how to turn that remote app reputation check are explained in

If you find that you’re managing a site that gets attacked, maybe you learn about it initially from having the site blocked. If this happens, you would need to remove the stuff that was put on your site that resulted in the site being blocked and then request removal from the list of reported phishing sites, use this form provided by Google.

Also request removal from

Safari uses Google Safe Browsing. There is a “Fraudulent sites” setting in the Security Preference pane for Safari. Here, you check a box and then you get prompted when you attempt to open a bad site. 

Safari SafeBrowsing involves having Safari pull a new version of the bad stuff from Google every now and then. You can see the date and timestamp that this occurred using the defaults command to read, as follows:

defaults read

The output contains the SafeBrowsingRemoteConfigurationLastUpdateDate key for /Users//Library/Preferences/

defaults read
SafeBrowsingRemoteConfigurationLastUpdateDate = "2018-09-19 22:43:30 +0000";

Or to wrap this into a command that just displays the last date updated:

defaults read /Users/charles.edge\ 1/Library/Preferences/ SafeBrowsingRemoteConfigurationLastUpdateDate | awk ‘{print$1}’

The actual bad stuff file is tricky. A number of temporary dynamic files are stored in /var/folders, and then inside a hierarchy generated by guids for a given system. Here, you’ll find a couple of files, including /var/folders/r1/05ns3cqs0cg5c42x38gk0c0w0000gn/C/ and /var/folders/8s/s9k75nys3rb399w4fwwtk04h0000gn/C/ 

These files are binaries and cannot be viewed. They appear to be downloaded via the service routinely. Looking at their date and time stamp though, will give you a good idea of when the last update was run if you care to find that out.

Enable SafeBrowsing via the WarnAboutFraudulentWebsites key in ~/Library/Preferences/ as can be seen below:

defaults write /Users/charles.edge/Library/Preferences/ WarnAboutFraudulentWebsites 1

September 17th, 2018

Posted In: Mac Security

Tags: , , ,

Just some little one-liners to grab the version of a few common Apple services/built-in apps you might need the version of for another project I’m working on kinda’:
  • cups: cups-config –version
  • Finder: mdls -name kMDItemVersion /System/Library/CoreServices/ | cut -d ‘”‘ -f2
  • Help Viewer: mdls -name kMDItemVersion /System/Library/CoreServices/ | cut -d ‘”‘ -f2
  • iBooks Author: mdls -name kMDItemVersion /Application/iTunes\ | cut -d ‘”‘ -f2
  • ical/Calendar: mdls -name kMDItemVersion /Applications/ | cut -d ‘”‘ -f2
  • ichat/Messages: mdls -name kMDItemVersion /Applications/ | cut -d ‘”‘ -f2
  • iMovie: mdls -name kMDItemVersion /Applications/ | cut -d ‘”‘ -f2
  • installer: /usr/sbin/installer -vers
  • Photos/iPhoto: mdls -name kMDItemVersion /Applications/ | cut -d ‘”‘ -f2 
  • iTunes: mdls -name kMDItemVersion /Applications/ | cut -d ‘”‘ -f2 
  • Java: /usr/bin/java -version
  • Keynote: mdls -name kMDItemVersion /Applications/ | cut -d ‘”‘ -f2
  • macOS: sw_vers -productVersion
  • macOS Server: mdls -name kMDItemVersion /Applications/ | cut -d ‘”‘ -f2
  • Mail: mdls -name kMDItemVersion /Applications/ | cut -d ‘”‘ -f2
  • mdnsresponder
  • Motion: mdls -name kMDItemVersion /Applications/ | cut -d ‘”‘ -f2
  • Numbers: mdls -name kMDItemVersion /Applications/ | cut -d ‘”‘ -f2
  • Pages Required mdls -name kMDItemVersion /Applications/ | cut -d ‘”‘ -f2
  • Preview: mdls -name kMDItemVersion /Applications/ | cut -d ‘”‘ -f2
  • Quicktime: mdls -name kMDItemVersion /Applications/Quicktime\ | cut -d ‘”‘ -f2 quicktime_broadcaster No (Darwin Stream Server deprecated) N/A quicktime_darwin_mp3_broadcaster No (deprecated service) N/A quicktime_pictureviewer No (for QuickTime for Windows) N/A quicktime_streaming_server No (deprecated service) N/A
  • Remote Desktop: defaults read /System/Library/CoreServices/RemoteManagement/ CFBundleShortVersionString
  • Safari: mdls -name kMDItemVersion /Applications/ | cut -d ‘”‘ -f2 server_manager No (deprecated in 2006ish) N/A software_update tcp_ip_configuration_utility No (Laserwriter vuln from 2002) N/A terminal Required mdls -name kMDItemVersion /Applications/Utilities/ | cut -d ‘”‘ -f2
  • Textedit Required mdls -name kMDItemVersion /Applications/ | cut -d ‘”‘ -f2
  • Transporter: /Applications/
  • Xcode: mdls -name kMDItemVersion /Applications/ | cut -d ‘”‘ -f2
  • Xsan: /usr/sbin/cvversions
  • openSSL: openssl -version
  • Apache: httpd -v
If you notice, a lot of the built-in apps can be scanned with the same mdls command. There are certainly better ways for some, but when it comes to runtime cost, spotlight can respond quicker than a lot of other tools (other than purpose-built open source tools of course, who already have a smaller amount of data specific to the task). 3rd party software can be checked the same way. Let’s take Microsoft Outlook as an example:

mdls -name kMDItemVersion /Applications/Microsoft\ | cut -d ‘”‘ -f2

Additionally, Frameworks work a little differently. If I wanted to get the WebKit Framework version programmatically, I will need the system_profiler command along with the SPFrameworksDataType option. This will show me the version of WebKit, but strictly piping the output into grep won’t find the WebKit version. Instead I actually need to use an option I don’t use often with grep. Note that -A will allow you to define a number of lines to output following the pattern in question, so here I’m saying constrain my output to what you find that’s WebKit + the next ten lines, then constrain further for just the version number. 

system_profiler SPFrameworksDataType | grep -A10 WebKit: | grep Version

Anyway, more on all this soon.

September 13th, 2018

Posted In: Mac OS X, Mac Security

Tags: , , , , , ,

The Mac comes with a number of tools for querying version numbers of things like apps and operating systems. First, let’s look at operating systems. The quickest way to derive the version of an operating system would be 

sw_vers -productVersion

It then becomes trivial to pipe these into other language provided you can reach them from within a script. For example, if you import os into a python script, you can use the sw_vers command:

import os
os.system('sw_vers -productVersion')

Or to grab the version of the OS you could import a function just for that:

version = platform.mac_ver()

So in the following example, we’ll 

#!/usr/bin/python import sys, urllib, json, platform
if len(sys.argv) > 1: url = '{}'.format(sys.argv[1]) print([j['id'] for j in json.loads(urllib.urlopen(url).read().decode('utf-8'))]) else: version = platform.mac_ver() url = '{}'.format(version[0]) print([j['id'] for j in json.loads(urllib.urlopen(url).read().decode('utf-8'))])

This can be found at

So what might I want to do with it next? Well, you can also read the index of an app using mdls, using the -name option and the kMDItemVersion attribute, as follows for iTunes:

mdls -name kMDItemVersion /Applications/

And then you can lookup that up in the CVE database as well:


Or to merge the version check and the cve check:

curl -s`mdls -name kMDItemVersion /Applications/ | cut -d '"' -f2`

Ultimately, Apple has a number of products that are tracked in the cve database and a library of each could easily be built and parsed to produce all cve hits encountered on a Mac. Obviously, you might not want to trust some random site from Luxembourg (those Luxembourgians are troublesome after all) and you can do this directly against the zip from NIST or create your own microservice that responds similarly to this site. 

Note: Special thanks to Yuresko for fixing my else statement.

September 12th, 2018

Posted In: Mac OS X, Mac Security

Next Page »