macOS-Security-and-Privacy-Guide 0,3,7,0,9,5,5,0

A practical guide to securing macOS.

2 years after MIT

This is a collection of thoughts on securing a modern Apple Mac computer using macOS (formerly OS X) 10.12 "Sierra", as well as steps to improving online privacy.

This guide is targeted to “power users” who wish to adopt enterprise-standard security, but is also suitable for novice users with an interest in improving their privacy and security on a Mac.

A system is only as secure as its administrator is capable of making it. There is no one single technology, software, nor technique to guarantee perfect computer security; a modern operating system and computer is very complex, and requires numerous incremental changes to meaningfully improve one's security and privacy posture.

I am not responsible if you break a Mac by following any of these steps.

If you wish to make a correction or improvement, please send a pull request or open an issue.

This guide is also available in 简体中文.

Basics

The standard best security practices apply:

  • Create a threat model

    • What are you trying to protect and from whom? Is your adversary a three letter agency (if so, you may want to consider using OpenBSD instead), a nosy eavesdropper on the network, or determined apt orchestrating a campaign against you?
    • Study and recognize threats and how to reduce attack surface against them.
  • Keep the system up to date

    • Patch, patch, patch your system and software.
    • macOS system updates can be completed using the App Store application, or the softwareupdate command-line utility - neither requires registering an Apple account.
    • Subscribe to announcement mailing lists (e.g., Apple security-announce) for programs you use often.
  • Encrypt sensitive data

    • In addition to full disk encryption, create one or many encrypted containers to store passwords, keys, personal documents, and other data at rest.
    • This will mitigate damage in case of compromise and data exfiltration.
  • Frequent backups

    • Create regular backups of your data and be ready to reimage in case of compromise.
    • Always encrypt before copying backups to external media or the "cloud".
    • Verify backups work by testing them regularly, for example by accessing certain files or performing a hash based comparison.
  • Click carefully

    • Ultimately, the security of a system can be reduced to its administrator.
    • Care should be taken when installing new software. Always prefer free and open source software (which macOS is not).

Firmware

Setting a firmware password prevents your Mac from starting up from any device other than your startup disk. It may also be set to be required on each boot.

This feature can be helpful if your laptop is lost or stolen, protects against Direct Memory Access (DMA) attacks which can read your FileVault passwords and inject kernel modules such as pcileech, as the only way to reset the firmware password is through an Apple Store, or by using an SPI programmer, such as Bus Pirate or other flash IC programmer.

  1. Start up pressing Command R keys to boot to Recovery Mode mode.

  2. When the Recovery window appears, choose Firmware Password Utility from the Utilities menu.

  3. In the Firmware Utility window that appears, select Turn On Firmware Password.

  4. Enter a new password, then enter the same password in the Verify field.

  5. Select Set Password.

  6. Select Quit Firmware Utility to close the Firmware Password Utility.

  7. Select the Apple menu and choose Restart or Shutdown.

The firmware password will activate at next boot. To validate the password, hold Alt during boot - you should be prompted to enter the password.

The firmware password can also be managed with the firmwarepasswd utility while booted into the OS. For example, to prompt for the firmware password when attempting to boot from a different volume:

$ sudo firmwarepasswd -setpasswd -setmode command

Enter a password and reboot.

Using a Dediprog SF600 to dump and flash a 2013 MacBook SPI Flash chip to remove a firmware password, sans Apple

Using a Dediprog SF600 to dump and flash a 2013 MacBook SPI Flash chip to remove a firmware password, sans Apple

See HT204455, LongSoft/UEFITool and chipsec/chipsec for more information.

Preparing and Installing macOS

There are several ways to install a fresh copy of macOS.

The simplest way is to boot into Recovery Mode by holding Command R keys at boot. A system image can be downloaded and applied directly from Apple. However, this way exposes the serial number and other identifying information over the network in plaintext.

PII is transmitted to Apple in plaintext when using macOS Recovery

Packet capture of an unencrypted HTTP conversation during macOS recovery

Another way is to download macOS Sierra from the App Store or some other place and create a custom, installable system image.

The macOS Sierra installer application is code signed, which should be verified to make sure you received a legitimate copy, using the codesign command:

$ codesign -dvv /Applications/Install\ macOS\ Sierra.app
Executable=/Applications/Install macOS Sierra.app/Contents/MacOS/InstallAssistant
Identifier=com.apple.InstallAssistant.Sierra
Format=app bundle with Mach-O thin (x86_64)
CodeDirectory v=20200 size=297 flags=0x200(kill) hashes=5+5 location=embedded
Signature size=4167
Authority=Apple Mac OS Application Signing
Authority=Apple Worldwide Developer Relations Certification Authority
Authority=Apple Root CA
Info.plist entries=30
TeamIdentifier=K36BKF7T3D
Sealed Resources version=2 rules=7 files=137
Internal requirements count=1 size=124

macOS installers can be made with the createinstallmedia utility included in Install macOS Sierra.app/Contents/Resources/. See Create a bootable installer for macOS, or run the utility without arguments to see how it works.

Note Apple's installer does not appear to work across OS versions. If you want to build a 10.12 image, for example, the following steps must be run on a 10.12 machine!

To create a bootable USB macOS installer, mount a USB drive, and erase and partition it, then use the createinstallmedia utility:

$ diskutil list
[Find disk matching correct size, usually "disk2"]

$ diskutil unmountDisk /dev/disk2

$ diskutil partitionDisk /dev/disk2 1 JHFS+ Installer 100%

$ cd /Applications/Install\ macOS\ Sierra.app

$ sudo ./Contents/Resources/createinstallmedia --volume /Volumes/Installer --applicationpath /Applications/Install\ macOS\ Sierra.app --nointeraction
Erasing Disk: 0%... 10%... 20%... 30%... 100%...
Copying installer files to disk...
Copy complete.
Making disk bootable...
Copying boot files...
Copy complete.
Done.

To create a custom, installable image which can be restored to a Mac, you will need to find the file InstallESD.dmg, which is also inside Install macOS Sierra.app.

With Finder, right click on the app, select Show Package Contents and navigate to Contents > SharedSupport to find the file InstallESD.dmg.

You can verify the following cryptographic hashes to ensure you have the same copy with openssl sha1 InstallESD.dmg or shasum -a 1 InstallESD.dmg or shasum -a 256 InstallESD.dmg (in Finder, you can drag the file into a Terminal window to provide the full path).

To determine which macOS versions and builds originally shipped with or are available for your Mac, see HT204319.

See InstallESD_Hashes.csv in this repository for a list of current and previous file hashes. You can also Google the cryptographic hashes to ensure the file is genuine and has not been tampered with.

To create the image, use MagerValp/AutoDMG, or to create it manually, mount and install the operating system to a temporary image:

$ hdiutil attach -mountpoint /tmp/install_esd ./InstallESD.dmg

$ hdiutil create -size 32g -type SPARSE -fs HFS+J -volname "macOS" -uid 0 -gid 80 -mode 1775 /tmp/output.sparseimage

$ hdiutil attach -mountpoint /tmp/os -owners on /tmp/output.sparseimage

$ sudo installer -pkg /tmp/install_esd/Packages/OSInstall.mpkg -tgt /tmp/os -verbose

This part will take a while, so be patient. You can tail -F /var/log/install.log in another Terminal window to check progress.

(Optional) Install additional software, such as Wireshark:

$ hdiutil attach Wireshark\ 2.2.0\ Intel\ 64.dmg

$ sudo installer -pkg /Volumes/Wireshark/Wireshark\ 2.2.0\ Intel\ 64.pkg -tgt /tmp/os

$ hdiutil unmount /Volumes/Wireshark

See MagerValp/AutoDMG/wiki/Packages-Suitable-for-Deployment for caveats and chilcote/outset to instead processes packages and scripts at first boot.

When you're done, detach, convert and verify the image:

$ hdiutil detach /tmp/os

$ hdiutil detach /tmp/install_esd

$ hdiutil convert -format UDZO /tmp/output.sparseimage -o ~/sierra.dmg

$ asr imagescan --source ~/sierra.dmg

Now sierra.dmg is ready to be applied to one or multiple Macs. One could futher customize the image to include premade users, applications, preferences, etc.

This image can be installed using another Mac in Target Disk Mode or from a bootable USB installer.

To use Target Disk Mode, boot up the Mac you wish to image while holding the T key and connect it to another Mac using a Firewire, Thunderbolt or USB-C cable.

If you don't have another Mac, boot to a USB installer, with sierra.dmg and other required files copied to it, by holding the Option key at boot.

Run diskutil list to identify the connected Mac's disk, usually /dev/disk2

(Optional) Securely erase the disk with a single pass (if previously FileVault-encrypted, the disk must first be unlocked and mounted as /dev/disk3s2):

$ sudo diskutil secureErase freespace 1 /dev/disk3s2

Partition the disk to Journaled HFS+:

$ sudo diskutil unmountDisk /dev/disk2

$ sudo diskutil partitionDisk /dev/disk2 1 JHFS+ macOS 100%

Restore the image to the new volume:

$ sudo asr restore --source ~/sierra.dmg --target /Volumes/macOS --erase --buffersize 4m

You can also use the Disk Utility application to erase the connected Mac's disk, then restore sierra.dmg to the newly created partition.

If you've followed these steps correctly, the target Mac should now have a new install of macOS Sierra.

If you want to transfer any files, copy them to a shared folder like /Users/Shared on the mounted disk image, e.g. cp Xcode_8.0.dmg /Volumes/macOS/Users/Shared

Finished restore install from USB recovery boot

Finished restore install from USB recovery boot

We're not done yet! Unless you have built the image with AutoDMG, or installed macOS to a second partition on your Mac, you will need to create a recovery partition (in order to use full disk encryption). You can do so using MagerValp/Create-Recovery-Partition-Installer or using the following manual steps:

Download the file RecoveryHDUpdate.dmg.

RecoveryHDUpdate.dmg
SHA-256: f6a4f8ac25eaa6163aa33ac46d40f223f40e58ec0b6b9bf6ad96bdbfc771e12c
SHA-1:   1ac3b7059ae0fcb2877d22375121d4e6920ae5ba

Attach and expand the installer, then run it:

$ hdiutil attach RecoveryHDUpdate.dmg

$ pkgutil --expand /Volumes/Mac\ OS\ X\ Lion\ Recovery\ HD\ Update/RecoveryHDUpdate.pkg /tmp/recovery

$ hdiutil attach /tmp/recovery/RecoveryHDUpdate.pkg/RecoveryHDMeta.dmg

$ /tmp/recovery/RecoveryHDUpdate.pkg/Scripts/Tools/dmtest ensureRecoveryPartition /Volumes/macOS/ /Volumes/Recovery\ HD\ Update/BaseSystem.dmg 0 0 /Volumes/Recovery\ HD\ Update/BaseSystem.chunklist

Replace /Volumes/macOS with the path to the target disk mode-booted Mac as necessary.

This step will take several minutes. Run diskutil list again to make sure Recovery HD now exists on /dev/disk2 or equivalent identifier.

Once you're done, eject the disk with hdiutil unmount /Volumes/macOS and power down the target disk mode-booted Mac.

Virtualization

To install macOS as a virtual machine (vm) using VMware Fusion, follow the instructions above to create an image. You will not need to download and create a recovery partition manually.

VMware-Fusion-8.5.6-5234762.dmg
SHA-256: 57a879095c9fcce0066bea0d3c203571689fb53205915fda156c0d742f7c7ad2
SHA-1:   b7315d00a7c92dbad280d0f01f42dd8b56d96040

For the Installation Method, select Install OS X from the recovery partition. Customize any memory or CPU requirements and complete setup. The guest vm should boot into Recovery Mode by default.

In Recovery Mode, select a language, then Utilities > Terminal from the menubar.

In the guest vm, type ifconfig | grep inet - you should see a private address like 172.16.34.129

On the host Mac, type ifconfig | grep inet - you should see a private gateway address like 172.16.34.1

From the host Mac, serve the installable image to the guest vm by editing /etc/apache2/httpd.conf and adding the following line to the top (using the gateway address assigned to the host Mac and port 80):

Listen 172.16.34.1:80

On the host Mac, link the image to the default Apache Web server directory:

$ sudo ln ~/sierra.dmg /Library/WebServer/Documents

From the host Mac, start Apache in the foreground:

$ sudo httpd -X

From the guest VM, install the disk image to the volume over the local network using asr:

-bash-3.2# asr restore --source http://172.16.34.1/sierra.dmg --target /Volumes/Macintosh\ HD/ --erase --buffersize 4m
    Validating target...done
    Validating source...done
    Erase contents of /dev/disk0s2 (/Volumes/Macintosh HD)? [ny]: y
    Retrieving scan information...done
    Validating sizes...done
    Restoring  ....10....20....30....40....50....60....70....80....90....100
    Verifying  ....10....20....30....40....50....60....70....80....90....100
    Remounting target volume...done

When it's finished, stop the Apache Web server on the host Mac by pressing Control C at the sudo httpd -X window and remove the image copy with sudo rm /Library/WebServer/Documents/sierra.dmg

In the guest vm, select Startup Disk from the top-left corner Apple menu, select the hard drive and restart. You may wish to disable the Network Adapter in VMware for the initial guest vm boot.

Take and Restore from saved guest vm snapshots before and after attempting risky browsing, for example, or use a guest vm to install and operate questionable software.

First boot

Note Before setting up macOS, consider disconnecting networking and configuring a firewall(s) first. However, late 2016 MacBooks with Touch Bar hardware require online OS activation.

On first boot, hold Command Option P R keys to clear NVRAM.

When macOS first starts, you'll be greeted by Setup Assistant.

When creating your account, use a strong password without a hint.

If you enter your real name at the account setup process, be aware that your computer's name and local hostname will comprise that name (e.g., John Appleseed's MacBook) and thus will appear on local networks and in various preference files. You can change them both in System Preferences > Sharing or with the following commands:

$ sudo scutil --set ComputerName your_computer_name

$ sudo scutil --set LocalHostName your_hostname

Admin and standard user accounts

The first user account is always an admin account. Admin accounts are members of the admin group and have access to sudo, which allows them to usurp other accounts, in particular root, and gives them effective control over the system. Any program that the admin executes can potentially obtain the same access, making this a security risk. Utilities like sudo have weaknesses that can be exploited by concurrently running programs and many panes in System Preferences are unlocked by default [p. 61–62] for admin accounts. It is considered a best practice by Apple and others [p. 41–42] to use a separate standard account for day-to-day work and use the admin account for installations and system configuration.

It is not strictly required to ever log into the admin account via the macOS login screen. The system will prompt for authentication when required and Terminal can do the rest. To that end, Apple provides some recommendations for hiding the admin account and its home directory. This can be an elegant solution to avoid having a visible 'ghost' account. The admin account can also be removed from FileVault.

Caveats

  1. Only administrators can install applications in /Applications (local directory). Finder and Installer will prompt a standard user with an authentication dialog. Many applications can be installed in ~/Applications instead (the directory can be created manually). As a rule of thumb: applications that do not require admin access – or do not complain about not being installed in /Applications – should be installed in the user directory, the rest in the local directory. Mac App Store applications are still installed in /Applications and require no additional authentication.

  2. sudo is not available in shells of the standard user, which requires using su or login to enter a shell of the admin account. This can make some maneuvers trickier and requires some basic experience with command-line interfaces.

  3. System Preferences and several system utilities (e.g. Wi-Fi Diagnostics) will require root privileges for full functionality. Many panels in System Preferences are locked and need to be unlocked separately by clicking on the lock icon. Some applications will simply prompt for authentication upon opening, others must be opened by an admin account directly to get access to all functions (e.g. Console).

  4. There are third-party applications that will not work correctly because they assume that the user account is an admin. These programs may have to be executed by logging into the admin account, or by using the open utility.

Setup

Accounts can be created and managed in System Preferences. On settled systems, it is generally easier to create a second admin account and then demote the first account. This avoids data migration. Newly installed systems can also just add a standard account. Demoting an account can be done either from the the new admin account in System Preferences – the other account must be logged out – or by executing these commands (it may not be necessary to execute both, see issue #179):

$ sudo dscl . -delete /Groups/admin GroupMembership <username>

$ sudo dscl . -delete /Groups/admin GroupMembers <GeneratedUID>

You can find the “GeneratedUID” of your account with:

$ dscl . -read /Users/<username> GeneratedUID

See also this post for more information about how macOS determines group membership.

Full disk encryption

FileVault provides full disk (technically, full volume) encryption on macOS.

FileVault encryption protects data at rest and hardens (but not always prevents) someone with physical access from stealing data or tampering with your Mac.

With much of the cryptographic operations happening efficiently in hardware, the performance penalty for FileVault is not noticeable.

The security of FileVault greatly depends on the pseudo random number generator (PRNG).

The random device implements the Yarrow pseudo random number generator algorithm and maintains its entropy pool. Additional entropy is fed to the generator regularly by the SecurityServer daemon from random jitter measurements of the kernel.

SecurityServer is also responsible for periodically saving some entropy to disk and reloading it during startup to provide entropy in early system operation.

See man 4 random for more information.

The PRNG can be manually seeded with entropy by writing to /dev/random before enabling FileVault. This can be done by simply using the Mac for a little while before activating FileVault.

To manually seed entropy before enabling FileVault:

$ cat > /dev/random
[Type random letters for a long while, then press Control-D]

Enable FileVault with sudo fdesetup enable or through System Preferences > Security & Privacy and reboot.

If you can remember your password, there's no reason to save the recovery key. However, your encrypted data will be lost forever if you can't remember the password or recovery key.

If you want to know more about how FileVault works, see the paper Infiltrate the Vault: Security Analysis and Decryption of Lion Full Disk Encryption (pdf) and related presentation (pdf). Also see IEEE Std 1619-2007 “The XTS-AES Tweakable Block Cipher” (pdf).

You may wish to enforce hibernation and evict FileVault keys from memory instead of traditional sleep to memory:

$ sudo pmset -a destroyfvkeyonstandby 1
$ sudo pmset -a hibernatemode 25

All computers have firmware of some type—EFI, BIOS—to help in the discovery of hardware components and ultimately to properly bootstrap the computer using the desired OS instance. In the case of Apple hardware and the use of EFI, Apple stores relevant information within EFI to aid in the functionality of macOS. For example, the FileVault key is stored in EFI to transparently come out of standby mode.

Organizations especially sensitive to a high-attack environment, or potentially exposed to full device access when the device is in standby mode, should mitigate this risk by destroying the FileVault key in firmware. Doing so doesn’t destroy the use of FileVault, but simply requires the user to enter the password in order for the system to come out of standby mode.

If you choose to evict FileVault keys in standby mode, you should also modify your standby and power nap settings. Otherwise, your machine may wake while in standby mode and then power off due to the absence of the FileVault key. See issue #124 for more information. These settings can be changed with:

$ sudo pmset -a powernap 0
$ sudo pmset -a standby 0
$ sudo pmset -a standbydelay 0
$ sudo pmset -a autopoweroff 0

For more information, see Best Practices for Deploying FileVault 2 (pdf) and paper Lest We Remember: Cold Boot Attacks on Encryption Keys (pdf)

Firewall

Before connecting to the Internet, it's a good idea to first configure a firewall.

There are several types of firewall available for macOS.

Application layer firewall

Built-in, basic firewall which blocks incoming connections only.

Note, this firewall does not have the ability to monitor, nor block outgoing connections.

It can be controlled by the Firewall tab of Security & Privacy in System Preferences, or with the following commands.

Enable the firewall:

$ sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on

Enable logging:

$ sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setloggingmode on

You may also wish to enable stealth mode:

$ sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on

Computer hackers scan networks so they can attempt to identify computers to attack. You can prevent your computer from responding to some of these scans by using stealth mode. When stealth mode is enabled, your computer does not respond to ICMP ping requests, and does not answer to connection attempts from a closed TCP or UDP port. This makes it more difficult for attackers to find your computer.

Finally, you may wish to prevent built-in software as well as code-signed, downloaded software from being whitelisted automatically:

$ sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setallowsigned off

$ sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setallowsignedapp off

Applications that are signed by a valid certificate authority are automatically added to the list of allowed apps, rather than prompting the user to authorize them. Apps included in macOS are signed by Apple and are allowed to receive incoming connections when this setting is enabled. For example, since iTunes is already signed by Apple, it is automatically allowed to receive incoming connections through the firewall.

If you run an unsigned app that is not listed in the firewall list, a dialog appears with options to Allow or Deny connections for the app. If you choose "Allow", macOS signs the application and automatically adds it to the firewall list. If you choose "Deny", macOS adds it to the list but denies incoming connections intended for this app.

After interacting with socketfilterfw, you may want to restart (or terminate) the process:

$ sudo pkill -HUP socketfilterfw

Third party firewalls

Programs such as Little Snitch, Hands Off, Radio Silence and Security Growler provide a good balance of usability and security.

Example of Little Snitch monitored session

Example of Little Snitch-monitored session

LittleSnitch-3.7.4.dmg
SHA-256: b0ce3519d72affbc7910c24c264efa94aa91c9ad9b1a905c52baa9769156ea22
SHA-1:   868ad75623c60cb9ad428c7c1d3e5ae449a9033e

These programs are capable of monitoring and blocking incoming and outgoing network connections. However, they may require the use of a closed source kernel extension.

If the number of choices of allowing/blocking network connections is overwhelming, use Silent Mode with connections allowed, then periodically check your settings to gain understanding of what various applications are doing.

It is worth noting that these firewalls can be bypassed by programs running as root or through OS vulnerabilities (pdf), but they are still worth having - just don't expect absolute protection. However, some malware actually deletes itself and doesn't execute if Little Snitch, or other security software, is installed.

For more on how Little Snitch works, see the Network Kernel Extensions Programming Guide and Shut up snitch! – reverse engineering and exploiting a critical Little Snitch vulnerability.

Kernel level packet filtering

A highly customizable, powerful, but also most complicated firewall exists in the kernel. It can be controlled with pfctl and various configuration files.

pf can also be controlled with a GUI application such as IceFloor or Murus.

There are many books and articles on the subject of pf firewall. Here's is just one example of blocking traffic by IP address.

Add the following into a file called pf.rules:

set block-policy drop
set fingerprints "/etc/pf.os"
set ruleset-optimization basic
set skip on lo0
scrub in all no-df
table <blocklist> persist
block in log
block in log quick from no-route to any
pass out proto tcp from any to any keep state
pass out proto udp from any to any keep state
block log on en0 from {<blocklist>} to any

Use the following commands:

  • sudo pfctl -e -f pf.rules to enable the firewall
  • sudo pfctl -d to disable the firewall
  • sudo pfctl -t blocklist -T add 1.2.3.4 to add hosts to a blocklist
  • sudo pfctl -t blocklist -T show to view the blocklist
  • sudo ifconfig pflog0 create to create an interface for logging
  • sudo tcpdump -ni pflog0 to dump the packets

Unless you're already familiar with packet filtering, spending too much time configuring pf is not recommended. It is also probably unnecessary if your Mac is behind a NAT on a secured home network, for example.

For an example of using pf to audit "phone home" behavior of user and system-level processes, see fix-macosx/net-monitor.

Services

Before you connect to the Internet, you may wish to disable some system services, which use up resources or phone home to Apple.

See fix-macosx/yosemite-phone-home, l1k/osxparanoia and karek314/macOS-home-call-drop for further recommendations.

Services on macOS are managed by launchd. See launchd.info, as well as Apple's Daemons and Services Programming Guide and Technical Note TN2083

You can also run KnockKnock that shows more information about startup items.

  • Use launchctl list to view running user agents
  • Use sudo launchctl list to view running system daemons
  • Specify the service name to examine it, e.g. launchctl list com.apple.Maps.mapspushd
  • Use defaults read to examine job plists in /System/Library/LaunchDaemons and /System/Library/LaunchAgents
  • Use man, strings and Google to learn about what the agent/daemon runs

For example, to learn what a system launch daemon or agent does, start with:

$ defaults read /System/Library/LaunchDaemons/com.apple.apsd.plist

Look at the Program or ProgramArguments section to see which binary is run, in this case apsd. To find more information about that, look at the man page with man apsd

For example, if you're not interested in Apple Push Notifications, disable the service:

$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.apsd.plist

Note Unloading services may break usability of some applications. Read the manual pages and use Google to make sure you understand what you're doing first.

Be careful about disabling any system daemons you don't understand, as it may render your system unbootable. If you break your Mac, use single user mode to fix it.

Use Console and Activity Monitor applications if you notice your Mac heating up, feeling sluggish, or generally misbehaving, as it may have resulted from your tinkering.

To view currently disabled services:

$ find /var/db/com.apple.xpc.launchd/ -type f -print -exec defaults read {} \; 2>/dev/null

Annotated lists of launch daemons and agents, the respective program executed, and the programs' hash sums are included in this repository.

(Optional) Run the read_launch_plists.py script and diff output to check for any discrepancies on your system, e.g.:

$ diff <(python read_launch_plists.py) <(cat 16A323_launchd.csv)

See also cirrusj.github.io/Yosemite-Stop-Launch for descriptions of services and Provisioning OS X and Disabling Unnecessary Services for another explanation.

Spotlight Suggestions

Disable Spotlight Suggestions in both the Spotlight preferences and Safari's Search preferences to avoid your search queries being sent to Apple.

Also disable Bing Web Searches in the Spotlight preferences to avoid your search queries being sent to Microsoft.

See fix-macosx.com for detailed instructions.

If you've upgraded to OS X 10.10 "Yosemite" and you're using the default settings, each time you start typing in Spotlight (to open an application or search for a file on your computer), your local search terms and location are sent to Apple and third parties (including Microsoft).

Note This Web site and instructions may no longer work on macOS Sierra - see issue 164.

To download, view and apply their suggested fixes:

$ curl -O https://fix-macosx.com/fix-macosx.py

$ less fix-macosx.py

$ /usr/bin/python fix-macosx.py
All done. Make sure to log out (and back in) for the changes to take effect.

Speaking of Microsoft, you may want to see https://fix10.isleaked.com/ just for fun.

Homebrew

Consider using Homebrew to make software installations easier and to update userland tools (see Apple’s great GPL purge).

Note If you have not already installed Xcode or Command Line Tools, use xcode-select --install to download and install them from Apple.

To install Homebrew:

$ mkdir homebrew && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew

Edit PATH in your shell or shell rc file to use ~/homebrew/bin and ~/homebrew/sbin. For example, echo 'PATH=$PATH:~/homebrew/sbin:~/homebrew/bin' >> .zshrc, then change your login shell to Z shell with chsh -s /bin/zsh, open a new Terminal window and run brew update.

Homebrew uses SSL/TLS to talk with GitHub and verifies checksums of downloaded packages, so it's fairly secure.

Remember to periodically run brew update and brew upgrade on trusted and secure networks to download and install software updates. To get information on a package before installation, run brew info <package> and check its recipe online.

According to Homebrew's Anonymous Aggregate User Behaviour Analytics, Homebrew gathers anonymous aggregate user behaviour analytics and reporting these to Google Analytics.

To opt out of Homebrew's analytics, you can set export HOMEBREW_NO_ANALYTICS=1 in your environment or shell rc file, or use brew analytics off.

You may also wish to enable additional security options, such as HOMEBREW_NO_INSECURE_REDIRECT=1 and HOMEBREW_CASK_OPTS=--require-sha.

DNS

Hosts file

Use the hosts file to block known malware, advertising or otherwise unwanted domains.

Edit the hosts file as root, for example with sudo vi /etc/hosts. The hosts file can also be managed with the GUI app 2ndalpha/gasmask.

To block a domain, append 0 example.com or 0.0.0.0 example.com or 127.0.0.1 example.com to /etc/hosts

There are many lists of domains available online which you can paste in, just make sure each line starts with 0, 0.0.0.0, 127.0.0.1, and the line 127.0.0.1 localhost is included.

For hosts lists, see someonewhocares.org, l1k/osxparanoia/blob/master/hosts, StevenBlack/hosts and gorhill/uMatrix/hosts-files.json.

To append a raw list:

$ curl "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" | sudo tee -a /etc/hosts

$ wc -l /etc/hosts
31998

$ egrep -ve "^#|^255.255.255|^0.0.0.0|^127.0.0.0|^0 " /etc/hosts
::1 localhost
fe80::1%lo0 localhost
[should not return any other IP addresses]

See man hosts and FreeBSD Configuration Files for more information.

Dnsmasq

Among other features, dnsmasq is able to cache replies, prevent upstreaming queries for unqualified names, and block entire TLDs.

Use in combination with DNSCrypt to additionally encrypt outgoing DNS traffic.

If you don't wish to use DNSCrypt, you should at least use DNS not provided by your ISP. Two popular alternatives are Google DNS and OpenDNS.

(Optional) DNSSEC is a set of extensions to DNS which provide to DNS clients (resolvers) origin authentication of DNS data, authenticated denial of existence, and data integrity. All answers from DNSSEC protected zones are digitally signed. The signed records are authenticated via a chain of trust, starting with a set of verified public keys for the DNS root-zone. The current root-zone trust anchors may be downloaded from IANA website. There are a number of resources on DNSSEC, but probably the best one is dnssec.net website.

Install Dnsmasq (DNSSEC is optional):

$ brew install dnsmasq --with-dnssec

$ cp /usr/local/opt/dnsmasq/dnsmasq.conf.example /usr/local/etc/dnsmasq.conf

Edit the configuration:

$ vim /usr/local/etc/dnsmasq.conf

Examine all the options. Here are a few recommended settings to enable:

# Forward queries to DNSCrypt on localhost port 5355
server=127.0.0.1#5355

# Uncomment to forward queries to Google Public DNS
#server=8.8.8.8

# Never forward plain names
domain-needed

# Examples of blocking TLDs or subdomains
address=/.onion/0.0.0.0
address=/.local/0.0.0.0
address=/.mycoolnetwork/0.0.0.0
address=/.facebook.com/0.0.0.0

# Never forward addresses in the non-routed address spaces
bogus-priv

# Reject private addresses from upstream nameservers
stop-dns-rebind

# Query servers in order
strict-order

# Set the size of the cache
# The default is to keep 150 hostnames
cache-size=8192

# Optional logging directives
log-async
log-dhcp
log-facility=/var/log/dnsmasq.log

# Uncomment to log all queries
#log-queries

# Uncomment to enable DNSSEC
#dnssec
#trust-anchor=.,19036,8,2,49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
#dnssec-check-unsigned

Install and start the program (sudo is required to bind to privileged port 53):

$ sudo brew services start dnsmasq

To set Dnsmasq as your local DNS server, open System Preferences > Network and select the active interface, then the DNS tab, select + and add 127.0.0.1, or use:

$ sudo networksetup -setdnsservers "Wi-Fi" 127.0.0.1

Make sure Dnsmasq is correctly configured:

$ scutil --dns
DNS configuration

resolver #1
  search domain[0] : whatever
  nameserver[0] : 127.0.0.1
  flags    : Request A records, Request AAAA records
  reach    : Reachable, Local Address, Directly Reachable Address

$ networksetup -getdnsservers "Wi-Fi"
127.0.0.1

Note Some VPN software overrides DNS settings on connect. See issue #24 for more information.

Test DNSSEC validation

Test DNSSEC validation succeeds for signed zones:

$ dig +dnssec icann.org

Reply should have NOERROR status and contain ad flag. For instance,

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47039
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

Test DNSSEC validation fails for zones that are signed improperly:

$ dig www.dnssec-failed.org

Reply should have SERVFAIL status. For instance,

;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 15190
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

dnscrypt

Use dnscrypt to encrypt DNS traffic to the provider of choice.

If you prefer a GUI application, see alterstep/dnscrypt-osxclient.

Install DNSCrypt from Homebrew:

$ brew install dnscrypt-proxy

If using in combination with Dnsmasq, find the file homebrew.mxcl.dnscrypt-proxy.plist

$ find ~/homebrew -name homebrew.mxcl.dnscrypt-proxy.plist
/Users/drduh/homebrew/Cellar/dnscrypt-proxy/1.7.0/homebrew.mxcl.dnscrypt-proxy.plist

Edit it to have the line:

<string>--local-address=127.0.0.1:5355</string>

Below the line:

<string>/usr/local/opt/dnscrypt-proxy/sbin/dnscrypt-proxy</string>
dnscrypt

Append a local-address line to use DNScrypt on a port other than 53, like 5355

This can also be done using Homebrew, by installing gnu-sed and using the gsed command:

$ sudo gsed -i "/sbin\\/dnscrypt-proxy<\\/string>/a<string>--local-address=127.0.0.1:5355<\\/string>\n" $(find ~/homebrew -name homebrew.mxcl.dnscrypt-proxy.plist)

By default, the resolvers-list will point to the dnscrypt version specific resolvers file. When dnscrypt is updated, this version may no longer exist, and if it does, may point to an outdated file. This can be fixed by changing the resolvers file in homebrew.mxcl.dnscrypt-proxy.plist (found earlier using find) to the symlinked version in /usr/local/share:

<string>--resolvers-list=/usr/local/share/dnscrypt-proxy/dnscrypt-resolvers.csv</string>

Below the line:

<string>/usr/local/opt/dnscrypt-proxy/sbin/dnscrypt-proxy</string>

Start DNSCrypt:

$ sudo brew services start dnscrypt-proxy

Make sure DNSCrypt is running:

$ sudo lsof -Pni UDP:5355
COMMAND   PID   USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
dnscrypt-  83 nobody    7u  IPv4 0x1773f85ff9f8bbef      0t0  UDP 127.0.0.1:5355

$ ps A | grep '[d]nscrypt'
   83   ??  Ss     0:00.27 /Users/drduh/homebrew/opt/dnscrypt-proxy/sbin/dnscrypt-proxy --local-address=127.0.0.1:5355 --ephemeral-keys --resolvers-list=/Users/drduh/homebrew/opt/dnscrypt-proxy/share/dnscrypt-proxy/dnscrypt-resolvers.csv --resolver-name=dnscrypt.eu-dk --user=nobody

By default, dnscrypt-proxy runs on localhost (127.0.0.1), port 53, and under the "nobody" user using the dnscrypt.eu-dk DNSCrypt-enabled resolver. If you would like to change these settings, you will have to edit the plist file (e.g., --resolver-address, --provider-name, --provider-key, etc.)

This can be accomplished by editing homebrew.mxcl.dnscrypt-proxy.plist

You can run your own dnscrypt server (see also drduh/Debian-Privacy-Server-Guide#dnscrypt) from a trusted location or use one of many public servers instead.

Confirm outgoing DNS traffic is encrypted:

$ sudo tcpdump -qtni en0
IP 10.8.8.8.59636 > 77.66.84.233.443: UDP, length 512
IP 77.66.84.233.443 > 10.8.8.8.59636: UDP, length 368

$ dig +short -x 77.66.84.233
resolver2.dnscrypt.eu

See also What is a DNS leak, the mDNSResponder manual page and ipv6-test.com.

Captive portal

When macOS connects to new networks, it probes the network and launches a Captive Portal assistant utility if connectivity can't be determined.

An attacker could trigger the utility and direct a Mac to a site with malware without user interaction, so it's best to disable this feature and log in to captive portals using your regular Web browser, provided you have first disable any custom dns and/or proxy settings.

$ sudo defaults write /Library/Preferences/SystemConfiguration/com.apple.captive.control Active -bool false

See also Apple OS X Lion Security: Captive Portal Hijacking Attack, Apple's secret "wispr" request, How to disable the captive portal window in Mac OS Lion, and An undocumented change to Captive Network Assistant settings in OS X 10.10 Yosemite.

Certificate authorities

macOS comes with over 200 root authority certificates installed from for-profit corporations like Apple, Verisign, Thawte, Digicert and government agencies from China, Japan, Netherlands, U.S., and more! These Certificate Authorities (CAs) are capable of issuing SSL/TLS certificates for any domain, code signing certificates, etc.

For more information, see Certification Authority Trust Tracker, Analysis of the HTTPS certificate ecosystem (pdf), and You Won’t Be Needing These Any More: On Removing Unused Certificates From Trust Stores (pdf).

You can inspect system root certificates in Keychain Access, under the System Roots tab or by using the security command line tool and /System/Library/Keychains/SystemRootCertificates.keychain file.

You can disable certificate authorities through Keychain Access by marking them as Never Trust and closing the window:

A certificate authority certificate

The risk of a man in the middle attack in which a coerced or compromised certificate authority trusted by your system issues a fake/rogue SSL certificate is quite low, but still possible.

OpenSSL

The version of OpenSSL in Sierra is 0.9.8zh which is not current. It doesn't support TLS 1.1 or newer, elliptic curve ciphers, and more.

Apple declares OpenSSL deprecated in their Cryptographic Services Guide document. Their version also has patches which may surprise you.

If you're going to use OpenSSL on your Mac, download and install a recent version of OpenSSL with brew install openssl. Note, linking brew to be used in favor of /usr/bin/openssl may interfere with built-in software. See issue #39.

Compare the TLS protocol and cipher between the homebrew version and the system version of OpenSSL:

$ ~/homebrew/bin/openssl version; echo | ~/homebrew/bin/openssl s_client -connect github.com:443 2>&1 | grep -A2 SSL-Session
OpenSSL 1.0.2j  26 Sep 2016
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256

$ /usr/bin/openssl version; echo | /usr/bin/openssl s_client -connect github.com:443 2>&1 | grep -A2 SSL-Session
OpenSSL 0.9.8zh 14 Jan 2016
SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES128-SHA

See also Comparison of TLS implementations, How's My SSL, Qualys SSL Labs Tools and for detailed explanations and with latest vulnerabilities tests ssl-checker.online-domain-tools.com.

Curl

The version of Curl which comes with macOS uses Secure Transport for SSL/TLS validation.

If you prefer to use OpenSSL, install with brew install curl --with-openssl and ensure it's the default with brew link --force curl

Here are several recommended options to add to ~/.curlrc (see man curl for more):

user-agent = "Mozilla/5.0 (Windows NT 6.1; rv:45.0) Gecko/20100101 Firefox/45.0"
referer = ";auto"
connect-timeout = 10
progress-bar
max-time = 90
verbose
show-error
remote-time
ipv4

Web

Privoxy

Consider using Privoxy as a local proxy to filter Web browsing traffic.

A signed installation package for privoxy can be downloaded from silvester.org.uk or Sourceforge. The signed package is more secure than the Homebrew version, and attracts full support from the Privoxy project.

Alternatively, install and start privoxy using Homebrew:

$ brew install privoxy

$ brew services start privoxy

By default, privoxy listens on local TCP port 8118.

Set the system http proxy for your active network interface 127.0.0.1 and 8118 (This can be done through System Preferences > Network > Advanced > Proxies):

$ sudo networksetup -setwebproxy "Wi-Fi" 127.0.0.1 8118

(Optional) Set the system https proxy, which still allows for domain name filtering, with:

$ sudo networksetup -setsecurewebproxy "Wi-Fi" 127.0.0.1 8118

Confirm the proxy is set:

$ scutil --proxy
<dictionary> {
  ExceptionsList : <array> {
    0 : *.local
    1 : 169.254/16
  }
  FTPPassive : 1
  HTTPEnable : 1
  HTTPPort : 8118
  HTTPProxy : 127.0.0.1
}

Visit http://p.p/ in a browser, or with Curl:

$ ALL_PROXY=127.0.0.1:8118 curl -I http://p.p/
HTTP/1.1 200 OK
Content-Length: 2401
Content-Type: text/html
Cache-Control: no-cache

Privoxy already comes with many good rules, however you can also write your own.

Edit ~/homebrew/etc/privoxy/user.action to filter elements by domain or with regular expressions.

Here are some examples:

{ +block{social networking} }
www.facebook.com/(extern|plugins)/(login_status|like(box)?|activity|fan)\.php
.facebook.com

{ +block{unwanted images} +handle-as-image }
.com/ads/
/.*1x1.gif
/.*fb-icon.[jpg|gif|png]
/assets/social-.*
/cleardot.gif
/img/social.*
ads.*.co.*/
ads.*.com/

{ +redirect{[email protected]://@https://@} }
.google.com
.wikipedia.org
code.jquery.com
imgur.com

Verify Privoxy is blocking and redirecting:

$ ALL_PROXY=127.0.0.1:8118 curl ads.foo.com/ -IL
HTTP/1.1 403 Request blocked by Privoxy
Content-Type: image/gif
Content-Length: 64
Cache-Control: no-cache

$ ALL_PROXY=127.0.0.1:8118 curl imgur.com/ -IL
HTTP/1.1 302 Local Redirect from Privoxy
Location: https://imgur.com/
Content-Length: 0
Date: Sun, 09 Oct 2016 18:48:19 GMT

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8

You can replace ad images with pictures of kittens, for example, by starting the a local Web server and redirecting blocked requests to localhost.

Browser

The Web browser poses the largest security and privacy risk, as its fundamental job is to download and execute untrusted code from the Internet.

Use Google Chrome for most of your browsing. It offers separate profiles, good sandboxing, frequent updates (including Flash, although you should disable it - see below), and carries impressive credentials.

Chrome also comes with a great PDF viewer.

If you don't want to use Chrome, Firefox is an excellent browser as well. Or simply use both. See discussion in issues #2, #90.

If using Firefox, see TheCreeper/PrivacyFox for recommended privacy preferences. Also be sure to check out NoScript for Mozilla-based browsers, which allows whitelist-based, pre-emptive script blocking.

Create at least three profiles, one for browsing trusted Web sites (email, banking), another for mostly trusted Web sites (link aggregators, news sites), and a third for a completely cookie-less and script-less experience.

  • One profile without cookies or Javascript enabled (e.g., turned off in chrome://settings/content) which should be the preferred profile to visiting untrusted Web sites. However, many pages will not load at all without Javascript enabled.

  • One profile with uMatrix or uBlock Origin (or both). Use this profile for visiting mostly trusted Web sites. Take time to learn how these firewall extensions work. Other frequently recommended extensions are Privacy Badger, HTTPSEverywhere and CertPatrol (Firefox only).

  • One or more profile(s) for secure and trusted browsing needs, such as banking and email only.

The idea is to separate and compartmentalize data, so that an exploit or privacy violation in one "session" does not necessarily affect data in another.

In each profile, visit chrome://plugins/ and disable Adobe Flash Player. If you must use Flash, visit chrome://settings/contents to enable Let me choose when to run plugin content, under the Plugins section (also known as click-to-play).

Take some time to read through Chromium Security and Chromium Privacy.

For example you may wish to disable DNS prefetching (see also DNS Prefetching and Its Privacy Implications (pdf)).

Also be aware of WebRTC, which may reveal your local or public (if connected to VPN) IP address(es). This can be disabled with extensions such as uBlock Origin and rentamob/WebRTC-Leak-Prevent.

Many Chromium-derived browsers are not recommended. They are usually closed source, poorly maintained, have bugs, and make dubious claims to protect privacy. See The Private Life of Chromium Browsers.

Safari is not recommended. The code is a mess and security vulnerabilities are frequent, and slower to patch (see discussion on Hacker News). Security does not appear to be a priority for Safari. If you do use it, at least disable the Open "safe" files after downloading option in Preferences, and be aware of other privacy nuances.

Other miscellaneous browsers, such as Brave, are not evaluated in this guide, so are neither recommended nor actively discouraged from use.

For more information about security conscious browsing, see HowTo: Privacy & Security Conscious Browsing, browserleaks.com and EFF Panopticlick.

Plugins

Adobe Flash, Oracle Java, Adobe Reader, Microsoft Silverlight (Netflix now works with HTML5) and other plugins are security risks and should not be installed.

If they are necessary, only use them in a disposable virtual machine and subscribe to security announcements to make sure you're always patched.

See Hacking Team Flash Zero-Day, Java Trojan BackDoor.Flashback, Acrobat Reader: Security Vulnerabilities, and Angling for Silverlight Exploits, for example.

PGP/GPG

PGP is a standard for encrypting email end to end. That means only the chosen recipients can decrypt a message, unlike regular email which is read and forever archived by providers.

GPG, or GNU Privacy Guard, is a GPL licensed program compliant with the standard.

GPG is used to verify signatures of software you download and install, as well as symmetrically or asymmetrically encrypt files and text.

Install from Homebrew with brew install gnupg2.

If you prefer a graphical application, download and install GPG Suite.

Here are several recommended options to add to ~/.gnupg/gpg.conf:

auto-key-locate keyserver
keyserver hkps://hkps.pool.sks-keyservers.net
keyserver-options no-honor-keyserver-url
keyserver-options ca-cert-file=/etc/sks-keyservers.netCA.pem
keyserver-options no-honor-keyserver-url
keyserver-options debug
keyserver-options verbose
personal-cipher-preferences AES256 AES192 AES CAST5
personal-digest-preferences SHA512 SHA384 SHA256 SHA224
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
cert-digest-algo SHA512
s2k-digest-algo SHA512
s2k-cipher-algo AES256
charset utf-8
fixed-list-mode
no-comments
no-emit-version
keyid-format 0xlong
list-options show-uid-validity
verify-options show-uid-validity
with-fingerprint

Install the keyservers CA certificate:

$ curl -O https://sks-keyservers.net/sks-keyservers.netCA.pem

$ sudo mv sks-keyservers.netCA.pem /etc

These settings will configure GnuPG to use SSL when fetching ne

Related Repositories

awesome-macOS

awesome-macOS

 A curated list of awesome applications, softwares, tools and shiny things for ...

Amethyst

Amethyst

Automatic tiling window manager for macOS à la xmonad. ...

anti-adblock-killer

anti-adblock-killer

Anti-Adblock Killer helps you keep your Ad-Blocker active, when you visit a webs ...

awesome-malware-analysis

awesome-malware-analysis

A curated list of awesome malware analysis tools and resources ...

phoenix

phoenix

A lightweight macOS/OS X window and app manager scriptable with JavaScript ...


Top Contributors

drduh TraderStf PhDuck zelahi kristovatlas majr fmborghino radarhere bhicks acdha dlo VoidingWarranties martinseener aspyatkin nickpellant pirate OndroNR mdwod pra85 nvk sts10 sg-s tennysonholloway vsaw victorso mlinton