Wednesday, April 26, 2017

Consider Application Whitelisting with Device Guard



I realize that Twitter is a difficult medium to articulate full discussions, so I wanted to engage the topic with a blog post. Over the last couple years, I have focused a fair amount of time drawing attention to the use/misuse of trusted binaries to circumvent Application Whitelisting (AW) controls.  What I have not often discussed, is the actual effectiveness that I have seen of using AW. I would like to take the time to describe what I see are the strengths of AW, and encourage organizations to consider if it might work for their environments.
The genesis of this discussion came from my colleague, Matt Graeber (@mattifestation).  We’ve spent a fair amount of time looking at this technology as it applies to Microsoft’s Device Guard. And while we agree there are bypasses, we also believe that a tool like Device Guard can dramatically reduce the attack surface and tools available to an adversary.
One question you must ask yourself and your organization is this… How long will you allow the adversary to use EXE/DLL tradecraft to persist and operate in your environment? I have heard a great deal of discussion and resistance to deploying AW. However, I personally have not heard anyone who has deployed the technology say that they regret whitelisting.
When the organization I used to work for deployed AW in 2013, it freed up our team from several tasks.  It gave us time to hunt and prepare for the more sophisticated adversary.  There are many commodity attacks and targeted attacks that take various forms.  However, one commonality they all often share is to drop an EXE or DLL to disk and execute. It is this form of attack that you can mitigate with AW.  With whitelisting, you force the adversary to retool and find new tradecraft, because unapproved, unknown binaries will not execute…
How long will you continue to perform IR and hunt C2 that is emitted from an unapproved PE file?
Here are some of the common reasons I have heard for NOT implementing AW. There are probably others, but this summarizes many.


1.     Aren’t there trivial bypasses? It doesn’t stop all attacks.
2.     Too much effort.
3.     It doesn’t scale.
I’ll take each of these and express my opinion. I’m open to dialogue on this and if I’m wrong, I would like to hear it and correct course…
1.     Aren’t there trivial bypasses to AW?  It doesn’t stop all attacks.
There are indeed ways to bypass AW.  I have found a few.  However, most of the bypasses I have demonstrated require that you have already obtained access to, and have the ability to execute commands on the target system. How does the attacker gain that privilege in the first place if you deny them arbitrary PE’s?  Most likely it will be from a memory corruption exploit in the browser or other application.  How many exploit kits, macros, or tools lead to dropping a binary and executing it?  Many do…
Most of the bypasses I have used are rooted in misplaced trust.  Often administrators of AW follow a pattern of “Scan A Gold Image & Approve Everything There”.  As Matt Graeber has pointed out to me several times, this is not the best approach.  There are far too many binaries that are included by default that can be abused. A better approach here is to explicitly trust binaries or publishers of code.  I can’t think of a single bypass that I have discovered that can’t be mitigated by the whitelist itself.  For example, use the whitelist to block regsvr32.exe or InstallUtil.exe.
Don’t fall victim to the Perfect Solution Fallacy.  The fact that AW doesn’t stop all attacks, or the fact that there are bypasses, is no reason to dismiss this as a valid defense.


“Nobody made a greater mistake than he who did nothing because he could do only a little.” –Edmund Burke
AW, in my opinion, can help you get control of software executing in your environment. It actually gives teeth to those Software Installation Policies. For example, it only takes that one person trying to find the Putty ssh client, and downloading a version with a backdoor to cause problems in your network.  For an example of how to backdoor putty see this recent post. Or use The Backdoor Factory (BDF). The thing is, it doesn’t matter that putty has a backdoor.  The original file has been altered, and will not pass the approval process for the whitelist, and the file will be denied execution. Only the approved version of putty would be able to execute in your environment.
2.     Too much effort.
Well… I’ve heard this, or some variation of it.  I understand that deploying and maintaining AW takes tremendous effort if you want to be successful.  It actually will take training multiple people to know how to make approvals and help with new deployments.
You will actually have to work very closely with your client teams, those in IT that manage the endpoints.  These partnerships can only strengthen the security team’s ability to respond to incidents. You can leverage tools like SCCM to assist with AW approvals and deployments.
The level of effort decreases over time.  Yes, there will be long hours on the front end, deploying configurations, reviewing audit logs, updating configs, etc… Some admins are so worried they will block something inadvertently; they are paralyzed to even try.  I think you’ll find out, Yes, you will block something legitimate.  Accept that this will happen, it’s a learning process, take it in steps.  Use that as an opportunity to get better.
I’ll say it again; I haven’t met anyone who has made the effort to deploy AW say that they regret the decision…
If you think it’s too hard, why not try 10% of the organization and see what you learn?
Stop telling me you aren’t doing this because it’s too hard… Anything worth doing well is going to require some effort and determination.
3.     It doesn’t scale.
Nope, it may not in your environment.  I never said it would… You must decide how far to go.  You may not get AW everywhere, but you can still win with it deployed in critical locations.  The image below describes how I think about how AW applies to different parts of your organization.  It is not a one-size-fits-all solution.  There are approaches and patterns that affect how you will deploy and configure whitelists. I think you should start with the bottom, and work your way up the stack.
Start to think of your environment in terms of how dynamic the systems are.  At the low end of the are those fixed function systems.  Think about systems similar to Automated Teller Machines.  These often only need to be able to apply patches.  New software rarely ever lands here.  Next, you have various department templates, each department will be unique, but likely fits a pattern.  Then IT Admins, who often need to install software to test or have more dynamic requirements.  At the top of the environment, are Developer workstations.  These are systems that are emitting code and testing.  I’m not saying you can’t whitelist here.  You can, I’ve done it.  But it will require some changes to build processes, code signing etc…


Yes, this is an overly simplified analogy, but I hope it helps you see where you can begin to prioritize AW deployments.
So, begin to reorient how you think about your systems to how dynamic they are.  You will have your quickest wins and earliest wins by starting at the bottom and moving your way up the hierarchy.


Conclusion


I am curious for open debate here.  If AW sucks, then let me hear why.  Tell me what your experience has been.  What would have made it work?  I’m interested in solutions that make a long term actual difference in your environment.  It is my opinion that AW works, despite some flaws.  It can dramatically reduce the attack patterns used by an adversary and increase the noise they generate.  I also believe that by implementing AW, your security teams can gain efficiencies how they operate. I am open to learn here.
If you are tasked with defending your organization, I’m asking you, as you begin to roll out Windows 10, to consider using Device Guard.


Ok, that’s all I have today.  Sincere feedback welcome.  If you think I’m wrong, I’d like to hear why...

Cheers,

Casey
@subTee

Bypassing Application Whitelisting using MSBuild.exe - Device Guard Example and Mitigations

I’ve said it before, but when you start down the road of Application Whitelisting, you need to take the extra steps to look at the functionality of the applications you are trusting, and see if they come with “extra features”.
By using signed Microsoft binaries, and injecting code into them, we effectively cloak our binaries so that they can execute, even under the watchful eye of Device Guard. 

It is important to realize; this is a misplaced trust bypass.  The product works fine, in fact, you can even use Device Guard to mitigate against this bypass. See details below.

Device Guard is a new addition and is very effective at mitigating untrusted code. Please don’t mistake this bypass as a reason to dismiss this defense.  I highly recommend Device Guard to organizations.  For additional information, you can watch this talk:

In May of this year, I started looking into a way to bypass Device Guard. I like to start with default utilities that may be able to execute code as they are often implicitly trusted.  None of my previous AppLocker bypasses would work against Device Guard, so it was time to try something new.
I built up a base Windows 10 Enterprise Workstation.  An example Device Guard configuration can be found here by Matt Graeber (@mattifestation):


I found a Microsoft signed tool called MSBuild.exe. This is a default .NET utility that ships with Windows. I usually start with the question; ‘HOW could I get MSbuild to execute code for me?’.

Turns out, MSBuild.exe has a built in capability called “Inline Tasks”.  These are snippets of C# code that can be used to enrich the C# build process.  Essentially, what this does, is take an XML file, compile and execute in memory on the target, so it is not a traditional image/module execution event.

If you trust MSbuild on your system, or if it gets picked up in a “Gold” Image for Device Guard, it can be used to execute arbitrary binaries. 

Inline Task Reference:

So, I wrote a quick POC to make sure I could get my code to execute on the system, before going too far down the road.


Once I knew the code would execute via MSbuild.exe, I set out to wrap Mimikatz into a file to allow it to execute inside of MSBuild.exe. This wasn’t too hard, since I had done something like this for InstallUtil.exe last year.  I also wrote a utility to remove PowerShell Constrained Language mode, if needed.


Examples:  Tested on Windows 10 x64 Only - 
1.)   Hello World!
2.)   Remove Constrained Language Mode in PowerShell
3.)   Mimikatz Execute -
b.)   Note: This simply executes Mimikatz, it does NOT bypass Credential Guard.


Mitigations:
You will need to monitor execution of this tool in your environment. It is my belief, that you will likely not need this tool on devices that run Device Guard, but it will be up to you to monitor execution events to determine that.  Tools like Sysmon or even Device Guard in Audit Mode.
Also monitoring 4688 events

One documented mitigation solution using Device Guard is to follow the guidance in Matt’s blog reference below to be certain that untrustworthy binaries don’t execute.


Matt has also created a sample configuration to block these types of binaries.  This can be found here:



Here is what I have been trying to say for some time…"If you authorize things to run that that can then be used to run arbitrary code, then it can bypass many whitelisting applications. This means for a real lockdown administrators need to block these types of binaries.  MsBuild.exe being the latest in a growing list of default tools that behave this way."

If you find these types of files, help us catalog how they work and we can deploy proper mitigations. I will be posting these only when I have the vetted mitigation details ready for defenders.

Proof of Concept Video:  With Music ;-)


That’s all I have for today.

Cheers,


Casey
@subTee

Attacking Drivers With MSBuild.exe

I’ve recently been experimenting with the full, offensive capabilities of MSBuild.exe. As a reference, MSBuild.exe ships with the .NET framework and comes installed by default on Windows 10.  


Starting in .NET Framework version 4, you can create tasks inline in the project file. You do not have to create a separate assembly to host the task. This makes it easier to keep track of source code and easier to deploy the task. The source code is integrated into the script.”


Specifically, the aspect of MSBuild.exe that we are leveraging is called an Inline Task.
This feature allows us to specify C# code in an XML file that gets compiled and executed in memory when called. The C# code that is included in the XML task, is compiled and loaded as a byte array in memory.  This gives us the huge advantage, since this will likely not be picked up by tools that monitor library loads from disk like Application Whitelisting or Anti Virus. Really, if you think about it, this is every bit as powerful as PowerShell, without all the logging and detection that comes with PowerShell these days.  By leveraging pure C# you can avoid the PowerShell Logging.
This idea led me to exploring the full potential of using MSBuild.exe for bypassing UMCI (User Mode Code Integrity). For example, to expand our influence on the local system, we could exploit a local, approved vulnerable driver. Normally, this process is kicked off by a user mode process to interact with the driver.  However… with UMCI in place, your PoC binary won’t execute and you are stuck… This blog will describe the details and methods that you can call to interact with the driver using the .NET framework, hosted inside MSBuild.exe.
If you would like to review the code sample. I’ve posted it here.
First a bit of background on the driver, and the exploit technique. I stumbled upon this driver on GitHub a couple weeks ago. All the research on this exploit was done by Shahriyar Jalayeri
( @ponez )
I wanted to see if I could port the exploit to C# so that I could use MSBuild.exe to execute it. And the answer is yes, yes you can ;-).
In this example, we are going to exploit a Write-What-Where vulnerability. This means that we can overwrite a location controlled by the Windows kernel.  The question is, how do we identify the “what” and the “where”? There is an excellent book here that provided a lot of the background for me.
A couple of preliminary steps:
First, we need to locate the base address of ntoskrnl.exe.  This can be done using the following routine here.  All of this can be done as a normal user.  As my colleague Matt Graeber (@mattifestation) pointed out, this is a fantastic heuristic for a sysmon rule. i.e. detection of any PID besides 4 (system process) that loads ntoskrnl.exe. There is no legitimate purpose for this. lt is almost certainly guaranteed to be malicious.


Second, once we have the base address of the kernel, we need to locate the offset to important structures and functions.  Here, we load ntoskrnl.exe into our process so that we can calculate offsets and calculate the values we need to overwrite.  


After discovering the correct base address of the Kernel Executive, we will be able to relocate whichever exported function we’d like to move by simply loading the same binary image in user land and relocating the relative virtual address (RVA) using the real kernel base address leaked by that function. Do not confuse RVAs with virtual memory addresses. An RVA is a virtual address of an object (a symbol) from the binary file after being loaded into memory, minus the actual base address of the file image in memory. To convert an RVA to the corresponding virtual address, we have to add the RVA to the corresponding module image base address. The procedure to relocate Kernel Executive functions, hence, is straightforward. We have to load the kernel image into user-mode address space via the LoadLibrary() API, and then pass the HMODULE handle to a function which resolves the RVA…” - Guide to Kernel Exploitation p276.


Ok.  Now we need to actually perform the overwrite. This is done by interacting with the driver and passing a malicious request that actually overwrites the locations we have found.


This is seen here.  


I ended up just writing a bunch of shellcode with NOP instructions, and 0xCC breaks.   I leave this up to you to experiment with to see what kind of interesting exploit you can come up with.  My code is a simple POC. Be sure to check out https://www.fuzzysecurity.com/ to see some cool exploits using PowerShell, much of this can be ported to .NET easily.


Ok.  So, what does this all mean?  Well, I’m an advocate of Application Whitelisting, and one of the reasons for exploring this area was to demonstrate that a valid signed driver can undermine your local systems.  The attacker can bring/install this driver and can use it to install rootkits or other malicious software running in the kernel context. The combination of a kernel mode and user mode bypass has significant implications.


Device Guard actually has a driver policy referred to as kernel mode code integrity (KMCI). This allows your organizations to approve drivers.  Even if the driver is signed, you can prevent this driver from being loaded on your systems. It is important to have a UMCI policy.  It is just as important to consider a KMCI policy as well.  Drivers should be far less dynamic in your environment.  You should know EXACTLY which drivers are deployed, and their versions.  A good reference on that is here and on Matt’s blog.


That’s all I have today.


Screen Shot 2017-01-13 at 1.17.53 PM.png


Casey
@subTee

Shellcode Injection via QueueUserAPC - Hiding From Sysmon

Recently, our team was discussing some defender capabilities.  One excellent tool is Sysmon from Sysinternals. This tool allows you to collect detailed information on processes, network connections, and several other artifacts.  Check out these resources for additional detail.




One of the events that is collected by Sysmon is explained as follows.


Event ID 8: CreateRemoteThread

“The CreateRemoteThread event detects when a process creates a thread in another process. This technique is used by malware to inject code and hide in other processes. The event indicates the source and target process. It gives information on the code that will be run in the new thread: StartAddress, StartModule and StartFunction. Note that StartModule and StartFunction fields are inferred, they might be empty if the starting address is outside loaded modules or known exported functions.” -Sysmon Documentation


This can be seen in a event like this:


Screen Shot 2017-01-18 at 4.39.53 PM.png


There are some really solid indicators here, including the base address of our shellcode.


So, the next question we had was to see if we could avoid these types of alerts and still accomplish our action on objective. The answer is yes, yes you can ;-) !


First some background on a function called QueueUserAPC.  This actually allows us to execute a block of shellcode by attaching it to the APC Queue.  Every Asynchronous Procedure Call (APC) waiting to execute resides in a thread-specific, kernel-managed queue and every thread in the system contains two APC queues, one for user-mode APCs and another for kernel-mode APCs.[1]




In this example, I’m taking a departure from the normal approach and combining something like process hollowing and thread hijacking.  First, we will create a process in the suspended state and copy our shellcode into that child process.  Next, we will call QueueUserAPC to attach our shellcode to a thread queue, so it executes when we resume.


Example code here.


You can invoke this as either a standalone exe or from InstallUtil.exe.  Also, here is an example using MSBuild.exe.


Most everything is pretty standard.  Here is where the interesting code is.


Screen Shot 2017-01-18 at 8.41.08 PM.png


So, there you have it.  This is one way that attackers might attempt to circumvent your CreateRemoteThread log collection.  No more meddling Sysmon Event ID 8 alerts *grin*.


That is all I have today.


Screen Shot 2017-01-18 at 5.09.03 PM.png


Cheers,


Casey

@subTee