Occasionally, we come across interesting scenarios that require thinking outside the box. For example: What if you’ve obtained a target user’s credentials (via responder.py, brute-forcing, sniffing, keylogging, etc.), but don’t have access to their workstation? This raises the question of whether a domain username and password could be useful without a workstation to authenticate against. Most organizations use Exchange for email, and make it externally accessible (via OWA or RPC over HTTPS). The AutoDiscover DNS record simplifies most of this process requiring a user to simply input his or her domain credentials into Outlook to setup the remote connection. Hopefully you can see where we’re going with this. If not, read on!
Anyone familiar enough with Outlook will know it has a “Rules and Alerts” section that allows the user to automate certain actions based on message criteria. This feature is particularly interesting because the rules sync between all Outlook installs via Exchange. Most of the available rules actions pertain to modifying the mailbox, moving messages, categorizing items, etc. However, a few more devious actions immediately stand out, namely “Start Application”.
This seems too easy! Sure enough, playing with the rule in the Outlook client highlights some pretty serious drawbacks. First, the target file needs to be locally accessible before it will save the rule. Second, it doesn’t appear to support arguments when starting the application. Poking around a bit more, we find the ability to import or export rules under the “Options” menu. Here is where we can have some fun! Let’s export a simple rule file and throw it into a hex editor.
Through the hex editor, we can find the data we’re interested in. We have the name of our rule, the text that our subject trigger is using, and the path of the file to execute. Experienced reverse engineers may notice that each text sequence is preceded by the length of the string, and the string itself is encoded with UTF-16LE. After spending some time reversing the file format, we built a python script to automate the process of modifying the rules file to execute an arbitrary malicious file instead of the one initially specified! By default, the script uses an email subject trigger rule to execute the file path specified. Like any good hacker script, it’s a little rough around the edges (e.g. no exception handling), but it’s much better than manually editing the .rwz files in a hex editor. It can be found here: https://gist.github.com/monoxgas/7fec9ec0f3ab405773fc
Note: The API Outlook uses is ShellExecute with the “open” verb when running the file, so technically any file extension with an action defined for “open” is valid. These can be found in the registry under HKEY_CLASSES_ROOT. This is also why arguments don’t work…for now.
That’s cool, but we’re always looking for ways to weaponize techniques in real-world attack scenarios. That being said, the next challenge became finding a way to remotely leverage the capability to obtain initial access, or pivot around tough network segmentation. This is where UNC paths, SMB, and WebDAV come in handy.
Assuming you already had internal network access, you could host your malicious files on an open Samba share with Kali, or simply drop them on an existing public file share on the network.
If attempting initial access, the target network would need to allow port 445 outbound (more common than you might think), in which case you just host the file on a public server.
Similar to #2, but WebDAV (port 80) is used to deliver the payload.
Again, focusing on real-world attack scenarios, we opted for method #3, using an external WebDAV server running on port 80 (because everyone lets port 80 out) to deliver the payload.
Note: Performing this attack via the internet might generate a user prompt warning of execution from an untrusted location.
So let’s put all of this theory into practice and show an example attack.
Used to connect to target user’s email account externally
Overview of the process:
Install Apache and WebDAV modules. Setup a public share with anonymous access (public server)
Run Empire and create listener/stager (public server)
Build EXE wrapper to run PowerShell one-liner silently
Build Outlook RWZ file
Connect to target users email in Outlook and sync the malicious rule file (Windows VM)
Send an email to trigger the Outlook rule
Shellz! (target workstation)
Step 1 – Install Apache and WebDAV
Installing Apache and WebDAV will depend on your distro. In this demo, we used a base Ubuntu 14.04 install with a process similar to this. Here is a snippet from the 000-default.conf site config file to allow anonymous access to a WebDAV share.
In this case, I’m using “/var/www/webdav”. Just make sure proper permissions are set on that directory.
Step 2 – Setup the RAT
Powershell Empire (https://www.powershellempire.com) can be installed with a simple “git clone https://github.com/PowerShellEmpire/Empire.git”, then run “./setup/install.sh”. For this example, I just left the listener named “test” with a connecting port of 8080. Setup our one-liner using “usestager launcher <listener name>”
Step 3 – Build the payload
Alright, now that we have a RAT listener setup, with a PowerShell one-liner to deploy, and WebDAV server to host our files, we just need the file payload to deploy. This could be done a number of ways. I like to use “BAT to EXE Converter” from https://www.f2ko.de/en/b2e.php. It allows you to make a EXE for running any command line input you want. Just copy the PowerShell one-liner from Empire into a BAT file and compile it to an EXE. Don’t forget to make the application “invisible” to avoid a command prompt window popping up. Once it’s compiled, throw this EXE onto your WebDAV file share.
Step 4 – Build the rule
Using the rulz.py script mentioned earlier, create the malicious rules file.
Step 5 – Connect to Outlook
This part is the easiest of this whole process. We won’t cover this process in detail, but it should be pretty easy as most organizations have AutoDiscover via DNS setup.
Note: Although user credentials often match between domains and exchange, it is possible that they use separate passwords (especially in the case of Office 365).
Once you have the profile loaded, hop into the “Rules and Alerts” panel, hit Options, then Import.
Feel free to edit the rule after it’s imported and modify it to your pleasure. Hit Apply when you’re done and let Outlook sync the rule to Exchange.
Important: When modifying a rule that starts an application, Outlook may set “On this computer only”. Make sure to uncheck this before applying the rule!
Step 6 – Send an email
Correction, hopefully THIS is the easiest step in the process. Go ahead and shoot your target an email, either from themselves, or the address of your choosing. I like to close Outlook immediately after the message sends to make sure the local instance doesn’t interfere with the process.
Step 7 – Shellz!
This whole process can be lengthy, and a bit finicky, but nothing satisfies like popping shells using only Outlook and some credentials.
Don’t forget to clean up their Outlook rules when you are done.
Like most good attacks, we aren’t really exploiting flaws, just abusing functionality to get reliable code execution. The biggest drawback right now is the inability to pass arguments when executing an application. This forces us to serve files over SMB or WebDAV which complicates the process a bit. While there are some caveats and prerequisites, Outlook rules still provide a promising entry point into a network, or around network segmentation.
By now, PowerShell should be in every offensive security person’s arsenal. There are a plethoraof PowerShell projects now that penetration testers and red teams can use when testing Windows networks. For privilege escalation, we have PowerUp. For Active Directory enumeration and exploitation, we have PowerView. Want to quickly run Mimkatz in memory on a remote box? Invoke-Mimikatz to the rescue. Need some creative comm channels? No problem, PowerShell can help theretoo. We even have fully-featured remote accesstools running written completely in PowerShell! And given Microsoft’s push to make everything administrablevia PowerShell, I think it’s safe to say PowerShell isn’t going anywhere anytime soon.
Weaponization of PowerShell begins by invoking a PowerShell script in some way. Traditionally, offensive people use some combination of the following commands to execute PowerShell on a host:
Execute a script directly: powershell.exe -ExecutionPolicy Bypass -File script.ps1
While these techniques work in most cases, skilled defenders can easily detect these methods through process creation monitoring. There are a few ways to get around the need to spawn powershell.exe to execute your PowerShell. At its core, powershell.exe loads the System.Management.Automation assembly and uses the functions therein to invoke PowerShell commands. Likewise, you too can create your own C# application that references the Automation assembly and then uses the Automation assembly’s functions to execute your PowerShell (see SharpPick for a great example). This, however, requires you to upload a custom application to a target’s machine (an action which is not always ideal).
To get around this, earlier this year I developed UnmanagedPowerShell. UnmanagedPowerShell is a C++ project that starts up the .NET framework and loads (in memory) a custom C# assembly that executes PowerShell. This is useful because, assuming you already have some form of code execution on the box, then you can use this code to inject PowerShell into any process you’d like, eliminating the need to spawn powershell.exe. Public examples of this can be seen in ReflectivePick and PowerShell Empire’s psinject command (which uses ReflectivePick underneath).
While UnmanagedPowerShell removed the need to initially start powershell.exe, it is not exactly ideal because it is single threaded and therefore cannot handle executing multiple PowerShell scripts at once. To get around this, you could use PowerShell jobs, but those have the unfortunate side effect of executing each job in a new instance of powershell.exe. You could load up UnmanagedPowerShell/ReflectivePick each time you want to execute PowerShell, but this has the potential downsides of excessive network traffic and process injection. You could also solve this by creating a new PowerShell runspace for each job. This may also lead to problems, however, due to PowerShell scripts in different runspaces trying to PInvoke the same functions (If you have multiple runspaces, they all execute in the same app domain. Any PInvoke’d functions are bound to the AppDomain as a whole, not just in the current runspace).
To solve these problems, I developed the library PowerShellTasking. PowerShellTasking solves these problems by executing each new PowerShell script in a new AppDomain (an isolation mechanism in the .NET framework). Each PowerShell script runs in the background in its own AppDomain until completion (solving the single-threaded only problem), upon which the main thread receives any output and then unloads the AppDomain (preventing the PInvoke-ing problems). PowerShellTasking is compiled as a class library and anyone can easily use it by referencing the library in their own project (see the “Example” program in the GitHub project for an example). While PowerShellTasking will not prevent scripts that use PowerShell jobs from spawning powershell.exe, it does provide operators a safer way (from an opsec perspective) to execute multiple PowerShell scripts simultaneously on a host.
Hopefully this gives you a better idea of how PowerShell invocation has evolved over time and gives you some insights into the challenges of PowerShell weaponization. For resources on how to detect and protect yourself from malicious PowerShell usage in your network, see Lee Holmes’s excellent blog post and DerbyCon talk.
Necessary cookies help make a website usable by enabling basic functions like page navigation and access to secure areas of the website. The website cannot function properly without these cookies.
YouTube session cookie.
Marketing cookies are used to track visitors across websites. The intention is to display ads that are relevant and engaging for the individual user and thereby more valuable for publishers and third party advertisers.
Analytics cookies help website owners to understand how visitors interact with websites by collecting and reporting information anonymously.
Preference cookies enable a website to remember information that changes the way the website behaves or looks, like your preferred language or the region that you are in.
Unclassified cookies are cookies that we are in the process of classifying, together with the providers of individual cookies.
Cookies are small text files that can be used by websites to make a user's experience more efficient. The law states that we can store cookies on your device if they are strictly necessary for the operation of this site. For all other types of cookies we need your permission. This site uses different types of cookies. Some cookies are placed by third party services that appear on our pages.