Share
Embed
MacOS security, hardening and forensics 101 workshop
Workshop slides for #DevSecCon 2017 in London
Bea Hughes
October 19, 2017
Transcript
59 slides
-
Who's this clown? ̣ — Security Engineer at Stripe —
Infrastructure security at Etsy — Operations monkey at Puppet Labs — Was once retweeted by William Gibson! — basically, kind of a big deal ̣ https://twitter.com/skullmandible/status/411281851131523072 @benjammingh for DevSecCon 2017 2 -
Agenda — Intro (we're crushing this already) — Mac OS
history and sadness — Malware reversing and how — 5 minute break — Discovering problems in the first place — Hardening? — Fin @benjammingh for DevSecCon 2017 3 -
Intro This is workshop, not an amzing slide deck, please
throw any and all questions my way. PLEASE experiment, as hard as you can. This is not exhaustive, thankfully. @benjammingh for DevSecCon 2017 4 -
The VM It's nasty. It has no network adaptor on
it, so can only harm itself. Requires VMware Fusion on a Mac, due to licensing (the trial is on the drive too) @benjammingh for DevSecCon 2017 5 -
Once upon a time, macs looked like this @benjammingh for
DevSecCon 2017 7 -
This is actually the grandparent of your mac @benjammingh for
DevSecCon 2017 10 -
So what Ben? — NeXTSTEP originally released in 1989. —
The Mach Kernel project ran from 1985 to 1994. (somewhat hyperbolic, but you see what I'm saying) @benjammingh for DevSecCon 2017 12 -
How scary? /* XXX this is _not_ designed to be
fast */ /* wordexp is also rife with security "challenges", unless you pass it WRDE_NOCMD it *must* support subshell expansion, and even if you don't beause it has to support so much of the standard shell (all the odd little variable expansion options for example) it is hard to do without a subshell). It is probbably just plan a Bad Idea to call in anything setuid, or executing remotely. */ int wordexp(const char *__restrict__ words, wordexp_t *__restrict__ pwe, int flags) { /* cbuf_l's inital value needs to be big enough for 'cmd' plus about 20 chars */ size_t cbuf_l = 1024; char *cbuf = NULL; /* Put a NUL byte between each word, and at the end */ char *cmd = "/usr/bin/perl -e 'print join(chr(0), @ARGV), chr(0)' -- "; libc/gen/wordexp.c from the Apple FOSS mirror on github @benjammingh for DevSecCon 2017 13 -
So macs are not as secure as their marketing makes
out. @benjammingh for DevSecCon 2017 14 -
[durazac:malware]% hdiutil attach -readonly -noautoopen MacKeeper.dmg /dev/disk2 /Volumes/MacKeeper Installer [durazac:malware]%
cd /Volumes/MacKeeper\ Installer [durazac:MacKeeper Installer]% ls MacKeeper.pkg @benjammingh for DevSecCon 2017 18 -
[durazac:malware]% mkdir mc ; cd mc [durazac:malware]% file /Volumes/MacKeeper\ Installer/MacKeeper.pkg
/Volumes/MacKeeper Installer/MacKeeper.pkg: xar archive version 1, SHA-1 checksum [durazac:mc]% xar -x -f /Volumes/MacKeeper\ Installer/MacKeeper.pkg xar - eXtensible ARchiver @benjammingh for DevSecCon 2017 19 -
Moar packages! [durazac:mc]% ls -l total 16 -rw-r--r-- 1 ben
staff 6344 Oct 4 20:43 Distribution drwxr-xr-x 6 ben staff 192 Oct 4 20:43 LaunchOffer.pkg drwxr-xr-x 7 ben staff 224 Oct 4 20:43 MacKeeper.pkg drwxr-xr-x 23 ben staff 736 Oct 4 20:43 Resources drwxr-xr-x 7 ben staff 224 Oct 4 20:43 comzeobitmackeeper.pkg @benjammingh for DevSecCon 2017 20 -
Extract the pre/post install scripts [durazac:comzeobitmackeeper.pkg]% mkdir installscripts [durazac:comzeobitmackeeper.pkg]% cd
installscripts [durazac:installscripts]% tar zxvf ../Scripts x postinstall @benjammingh for DevSecCon 2017 22 -
Extract the payload [durazac:comzeobitmackeeper.pkg]% mkdir paidload [durazac:comzeobitmackeeper.pkg]% cd paidload [durazac:paidload]%
tar zxvf ../Payload x . [durazac:paidload]% ls -la ../Payload -rw-r--r-- 1 ben staff 82 Oct 5 04:43 ../Payload Wait, there's no payload? @benjammingh for DevSecCon 2017 23 -
[durazac:~]% for ((i=0; i<=4; i++)) { echo \ 'LkdrJsYk22BjaHVOE3GOnE1VLCrnV/sTam3BaGjNOJp8O4fjMrBjekTT 94idx4n5A3EtUzi/lRtLoJvx2zhu3HG7PP/HsJnExsrj6UK4/CVsCCi/4
l0JcFGW1RPAzyHmqIEpi3cQ5RbYt3qXv8XVGtHvLNFCTYJk4z3F4J+2qf wZSS9mYVMkz9RgADO6WT4pQlqQoyHFXi5guCzIuZEYn5IHDLANtlqqnzD 7z1Nvl328SDp9nT9ZfQPd5EGt5veFncPM8qObrXqdUr1Ib8zIWt4FjYjH N6rtIk+S3QXluOMA8v8/SaUxj8zFZNjJy/3dKNzByl70ePGKKnJ16JIZo 1BOFG5Ate3x/87ECj7fTgVjR1TRuPHbvUtgeSMdmVNtmI+rOKFehPUSjb HXQiw/RNyCIE7WlcSczl/0P04HOZmeTaFdxetWvKwI8kIiD0dQbFQBalN cS8qgtG1gAllMqKFnjYD6wWXeQTBaWuBBo8FfCEuXKiFvrBoBiZlFxeQK' \ | base64 -D \ | dd bs=128 count=1 skip=$i 2>/dev/null \ | openssl rsautl -verify -pubin -inkey somekey 2>/dev/null \ } | python -mjson.tool @benjammingh for DevSecCon 2017 25 -
Which outputs { "affid": "358.20580063.1507174981.32.mzb", "arePopupsAggressive": false, "bundleId": "29_317511156", "enableAnalytics":
true, "extendedStatisticIntervalInDays": 30, "ga_cid": "805354281.1507174983", "systemScanHasSignupStep": true, "trialDays": 0, "trtId": "FF2B241D-9456-4D5E-A4D5-50B67C3F0715", "trtVersion": 11 } @benjammingh for DevSecCon 2017 26 -
38 MAC_ADDRESS=$(networksetup -getmacaddress en0 | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}') 39
if [ -z "$MAC_ADDRESS" ]; then 40 ▸ MAC_ADDRESS=$(networksetup -getmacaddress en1 | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}') 41 fi 42 43 SERIAL_NUMBER=$(ioreg -c IOPlatformExpertDevice -d 2 | awk -F\" '/IOPlatformSerialNumber/{print $(NF-1)}') 44 45 DEVICE_ID=$(echo "${SERIAL_NUMBER}|${MAC_ADDRESS}" | sed -e 's/:/%3A/g;s/|/%7C/g') ... 53 ▸ ▸ REINSTALL_DATA="step=MKInstallEvents&affid=${AFFID}&bundleId=${BUNDLEID}&prodID=${MK_PRODUCT_ID}&version=${SOURCE_VERSION}&device_id=${DEVICE_ID}.... ... 57 ▸ ▸ curl -q -f --silent --data "$REINSTALL_DATA" "http://event.mackeeper.com/event.php" it's sending my MAC address where now!? @benjammingh for DevSecCon 2017 27 -
[durazac:comzeobitmackeeper.pkg]% <Payload gunzip -cd| tar vtf - drwxrwxr-t 2 0
80 0 May 12 02:42 . [durazac:comzeobitmackeeper.pkg]% lsbom Bom . 41775 0/80 Wait, so there is no payload, it just runs that super sketch script!?!? @benjammingh for DevSecCon 2017 28 -
MacKeeperOffers.pkg Now we just do the same for MacKeeperOffers until
we find something interesting [durazac:MacKeeperOffers]% strings -a checkinstall | tail -12 JustCloud MegaBackup YahooSearch Appswell YoutubeConverter /Applications/MegaBackup.app /Applications/JustCloud.app com.apple.Safari HomePage hspart=iry /Applications/Appswell.app /Applications/Softorino YouTube Converter X.app @benjammingh for DevSecCon 2017 29 -
Looking at the Offers.pkg/Scripts/MegaBackup line 55 [durazac:~]% TID=1 [durazac:~]% URL='http://land.megabackup.com/'
[durazac:~]% URL+='paramss=phexafefced9b4b5c9ac9297a0af999' [durazac:~]% URL+='cd2e8cb90b1b5cecfc1e2c8cad5cdd9ddcec49d' [durazac:~]% URL+='aadcd2d5a9a490e3e5c0d1c3ded5cdd0cfdbce9' [durazac:~]% URL+="496dfded99c&trt=51_72&tid_ext=${TID}" [durazac:~]% [durazac:~]% curl -q -f -L --max-redirs 150 \ --output some.file "$URL" % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 100 40238 100 40238 0 0 29387 0 0:00:01 0:00:01 --:--:-- 51455 [durazac:~]% file some.file some.file: xar archive - version 1 @benjammingh for DevSecCon 2017 31 -
go all the way back to the first dir [durazac:mc]%
egrep -Riha -o 'https?://[-\.a-z0-9_]+/' . | sort -u http://cdn.mackeeper.com/ http://event.mackeeper.com/ http://land.megabackup.com/ http://ldrapi1.megabackup.com/ http://mackeeperapp.mackeeper.com/ http://www.apple.com/ @benjammingh for DevSecCon 2017 32 -
Blocking domains — If you run your own resolvers, then
my talk on sinkholing from 2014 — If you use OpenDNS * and you should! read here — on the cheap * obviously doesn't scale cat <<EOF | sudo tee -a /etc/hosts && pkill -HUP mDNSResponder 127.0.0.1 cdn.mackeeper.com event.mackeeper.com mackeeperapp.mackeeper.com EOF @benjammingh for DevSecCon 2017 33 -
xa!r Extended attributes! [durazac:Downloads]% ls -l Hopper-4.1.4-demo.dmg -rw-r--r--@ 1 barn
staff 28746615 Apr 28 14:51 Hopper-4.1.4-demo.dmg [durazac:Downloads]% ls -l@ Hopper-4.1.4-demo.dmg -rw-r--r--@ 1 barn staff 28746615 Apr 28 14:51 Hopper-4.1.4-demo.dmg com.apple.diskimages.fsck 20 com.apple.diskimages.recentcksum 80 com.apple.metadata:kMDItemWhereFroms 151 com.apple.quarantine 71 @benjammingh for DevSecCon 2017 34 -
Xprotect from /System/Library/CoreServices/XProtect.bundle/Contents/Resources/XProtect.plist <plist version="1.0"> <array> <dict> <key>Description</key> <string>OSX.AceInstaller.B.2</string> <key>LaunchServices</key>
<dict> <key>LSItemContentType</key> <string>com.apple.application-bundle</string> </dict> <key>Matches</key> <array> <dict> <key>MatchFile</key> <dict> <key>NSURLTypeIdentifierKey</key> <string>public.unix-executable</string> </dict> <key>MatchType</key> <string>Match</string> <key>Pattern</key> <string>7365744F66666572734C6162656C</string> </dict> @benjammingh for DevSecCon 2017 36 -
and com.apple.metadata:kMDItemWhereFroms bash-3.2# mdls -name kMDItemWhereFroms Hopper-4.2.21-demo.dmg kMDItemWhereFroms = (
"https://d2ap6ypl1xbe4k.cloudfront.net/Hopper-4.2.21-demo.dmg", "https://www.hopperapp.com/download.html" ) @benjammingh for DevSecCon 2017 37 -
Host based IDS — MIDAS - Intrusion Detection for Macs(super
dead now) — OSSEC - Open Source HIDS SECurity Threaty threats paid things — Carbon Black Response — Clown Strike - Falcon — Red Canary @benjammingh for DevSecCon 2017 40 -
Gui version of knock knock By the same author, Patrick
Wardle. objective-see.com/products/knockknock.html @benjammingh for DevSecCon 2017 42 -
OSXcollector Written in python by Yelp More of a forensics
tool. Little more invasive say, my default dumps browser history. /usr/bin/python osxcollector.py spits out a tarball, inside that are system logs and a JSON report. @benjammingh for DevSecCon 2017 43 -
bash-3.2# cat osxcollect-2017_10_18-09_23_37.json \ | while read line ; \
do echo "$line" | python -mjson.tool || break ; \ done \ | less -R { "osxcollector_incident_id": "osxcollect-2017_10_18-09_23_37", "osxcollector_section": "version", "osxcollector_version": "1.9" } { "fde": false, "machine": "x86_64", "nodename": "dsc.local", "osxcollector_incident_id": "osxcollect-2017_10_18-09_23_37", "osxcollector_section": "system_info", "release": "17.0.0", "sysname": "Darwin", "version": "Darwin Kernel Version 17.0.0: Thu Aug 24 21:48:19 PDT 2017; root:xnu-4570.1.46~2/RELEASE_X86_64" } @benjammingh for DevSecCon 2017 44 -
OSquery — built at Facebook (it scales) — cross platform
(plan9, TOS, Xenix) — open source https://github.com/facebook/osquery/ — has a logo that makes you think of Gravatar @benjammingh for DevSecCon 2017 45 -
OSquery cont. — Kolide - Beautiful osquery management tool. —
Doorman - Doorman, OSS tool for doing the same. — Envdb - Looks pretty nice (but I've not used it yet) These are for fleet deployments, as osquery is just a SQL REPL for your system. @benjammingh for DevSecCon 2017 46 -
But let's play with it! [durazac:~]% osqueryi Using a virtual
database. Need help, type '.help' osquery> .mode line osquery> select * from osquery_info; pid = 1068 uuid = 564D335B-A20C-A42B-AB3B-9FCFCA4C07E7 instance_id = 9e14be42-d47a-4f88-b226-26366c20c67c version = 2.9.0 config_hash = df8743dd7fe17219a15ac0860d61c26d868ebc73 config_valid = 1 extensions = active build_platform = darwin build_distro = 10.12 start_time = 1508341272 watcher = -1 @benjammingh for DevSecCon 2017 47 -
osquery> .tables => acpi_tables => ad_config => alf => alf_exceptions
=> alf_explicit_auths => alf_services => app_schemes => apps => arp_cache => asl or, more readably, osquery table schema docs @benjammingh for DevSecCon 2017 48 -
fun osquery examples osquery> SELECT * From file ...> where
path like "/Users/%/Library/LaunchAgents/com.%.MacKeeper.Helper.plist" ...> OR path like "/Users/%/Documents/MacKeeper Backups" ...> OR path = "/Applications/MacKeeper.app" ; osquery> select distinct( user ) from logged_in_users; more fun on a server osquery> select * from kernel_extensions where name not like 'com.apple.%'; not amaze on the VM, but good on my laptop @benjammingh for DevSecCon 2017 49 -
Step 1 Manage your macs! — Fleetsmith - Fantastic new
MaaS offering — Chef/Puppet - needs no introduction — Munki - manage software installs, rather than just have them — Simian - Simian is an enterprise-class Mac OS X software deployment solution, buuuut it's Google — JSS Jamf - Is another alternative, I guess @benjammingh for DevSecCon 2017 51 -
Step 2 Just use Chrome — Pwn 2 Own's pricing
scale — BrowserScope says so — Zerodium will pay you $150k for an exploit for Chrome, vs $80k for FreedomFox @benjammingh for DevSecCon 2017 52 -
Step 3 — Make sure Gatekeeper is set to "app
store" or "app store & signed" only (now the default) @benjammingh for DevSecCon 2017 53 -
Step 3.5 — this doesn't solve homebrew, where you can
just install whatever you wish [durazac~]% brew install sqlmap 1 ==> Downloading https://github.com/sqlmapproject/sqlmap/archive/1.1.10.tar.gz ==> Downloading from https://codeload.github.com/sqlmapproject/sqlmap/tar.gz/1.1.10 ######################################################################## 100.0% ! /usr/local/Cellar/sqlmap/1.1.10: 543 files, 10.3MB, built in 17 seconds @benjammingh for DevSecCon 2017 54 -
Step 4 More restrictions — Santa! - Santa is a
binary whitelisting/blacklisting system for macOS @benjammingh for DevSecCon 2017 55 -
Hardening vs. reality You could make everyone in your company
run OpenBSD on their laptop. You would go out of business very quickly. There's no good easy answer. ): @benjammingh for DevSecCon 2017 56 -
Would you like to know more? — Reverse Engineering Mac
Malware - Sarah Edwards — When Macs Get Hacked -Sarah Edwards — Hipster DFIR on OSX - Scott J. Roberts — Syscall Auditing at scale - Ryan Huber — Tracking a stolen code-signing certificate with osquery - Mike Myers — Methods of Malware Persistence - Patrick Wardle @benjammingh for DevSecCon 2017 57