Escape and Evasion Egressing Restricted Networks
January 25, 2017
A command kill chain consists of payload delivery, code execution on a target system, and establishing a command and control (C2) channel outside of a network. There are many ways to achieve each of these steps; for example, Microsoft Office Macro for delivery, PowerShell for code execution and HTTP as a transport for C2.
We and our fellow attack and penetration teammates are constantly looking for new tactics, techniques and procedures (TTP) to bypass network-based and host-based deterrents that can introduce block points within the kill chain. In this post, we’ll specifically be speaking to solutions and controls such as firewalls, IDP, IPS, and proxies that aim to prevent C2. The post will conclude with TTPs that we have used with various levels of success.
Before we jump in, a little bit of a high-level background regarding how most of these solutions work and some of their features. Forgive our brevity here - going over each feature could be a book. If you are familiar with these controls and just want to get to the relevant sections, feel free to jump ahead.
- Firewalls can be used to restrict outbound network traffic. For example, the traffic may consist of only allowing TCP 80 and 443 out of a network through a proxy. Further, many devices can inspect this traffic at the application layer.
- Inline proxies can inspect traffic including encrypted transports such as TLS/SSL by essentially intercepting all traffic.
- Proxies can categorize and allow outbound URLs based on defined rules. For example, rules may be defined as blocking access to Dropbox and categorizing it as a file sharing service.
- Additional inline protections can inspect traffic for malicious payloads, some can even execute those payloads in a sandbox environment and identify malicious execution and known indicators of compromise (IOC).
Bypassing these solutions and others has always been a reciprocal arms race between aggressor and defender. In the current landscape, when we’re planning attacks, we assume that TCP 80 and 443 are allowed outbound through an inspecting proxy that will be using a whitelist approach of categorized URLs, and will be inspecting the application layer for correctness. Meaning, we cannot configure our payloads to simply connect over a raw TCP connection over some arbitrary port to some arbitrary IP. Thus, our payloads must:
- Connect over TCP 80 and/or 443 using HTTP(s)
- Connect to a categorized URL
- Bypass inspection
You may have said to yourself, “They forgot about ICMP and DNS!” Yes, you are right! We have seen great success using DNS tunneling, and would say it’s 50/50 as to whether ICMP is blocked. In fact, in our opinion the best approach is to configure payloads to attempt to establish connections over DNS and HTTP, thus giving you the greatest chance for success. Using DNS as a main channel and then establishing additional channels using HTTP is a great approach as well. We’ve also used other protocols and applications, such as SIP and Exchange, but we’ll save that for another post.
Getting a site categorized isn’t too difficult, it just takes time; and it’s a little “sketchy.” Albeit, taking the time to register a false business such as a healthcare provider, setting up the site, and waiting indefinitely for multiple vendors to categorize it is not always ideal. Additionally, there is the problem of dealing with the many vendors, and you can never be too sure your site will be categorized correctly, and then you can’t know for sure if that category will be allowed. There have been some posts written on that, so we won’t go into further detail here.
Next up is the task of bypassing any inspection. We use Cobalt Strike, which supports a featured called “Malleable C2.” This permits us to customize how the traffic of our payload will appear on the network. Making it very difficult to detect. For example, we can make our traffic look like Microsoft Updates or banking traffic from a popular site.
Vendor mitigation solutions used to grab payloads during delivery, and then execute them in a sandbox while identifying indicators of compromise have had some success against Cobalt Strike, but we have had success against these mitigation tactics using keyed payloads (check out Ebowla), and a little sum-sum we’ll be releasing at DefCon.
THE GOOD STUFF
Enough with the background, on to the cool stuff! Here are several methods that can be used to bypass not only URL categorization, but often inspection. This is not a comprehensive list, and none of these methods are “new”; there are no 0-dayz here.
The bonus to each of these bypasses is that most vendor mitigation tactics by default will not perform any inspection at all.
HOST HEADER SPOOFING
We identified this several years ago, and didn’t think much of it. We thought for sure that vendors were aware of this issue. Turns out, they were not, and within the past couple of years several researchers have disclosed the method and it has, for the most part, been fixed, or workarounds have been developed. The CVE’s are light on the details, but the problem is easy to understand.
These vendor mitigation tactics inspect the HTTP host header to categorize a site, which can easily be set by an attacker. For example, there is nothing preventing us from establishing a TCP connection by one hostname or IP address and then specifying the host header as “www.microsoft.com.” Thus, anything inline keying off this header should allow our payload through because it matches an allowed site.
One way this problem has been solved is by allowing the inline solution to perform DNS on behalf of the requester. This way they can ensure the IP to which the host header resolves matches the requested destination IP. Okay, can’t depend on this one as bullet proof, but this still works occasionally.
OVERLY PERMISSIVE RULES
We actually didn’t know how to title this one, because it’s not fair to say the rules are entirely overly permissive. But there are a few tricks that can be used to bypass some rules. For example, *.amazonaws.com is often allowed. If you have ever used EC2 you may have noticed your system is given a hostname that can be used as a URL, such as ec2-10-1-1-1.compute-1.amazonaws.com. By using EC2 you now have a categorized site.
S3 can also be used as a channel (with some work) and is a great delivery method as it is categorized and often allowed.
Finally, the reason we started writing this post. This is a method we became aware of just recently after reading a post from Signal regarding bypassing restrictions in Egypt. They are using a method called “domain fronting” to ensure users have connectivity. From the post:
“Many popular services and CDNs, such as Google, Amazon Cloudfront, Amazon S3, Azure, CloudFlare, Fastly, and Akamai can be used to access Signal in ways that look indistinguishable from other uncensored traffic. The idea is that to block the target traffic, the censor would also have to block those entire services. With enough large scale services acting as domain fronts, disabling Signal starts to look like disabling the internet.”
The TL;DR is that we can use many of these services as a reverse proxy for HTTP, and since they are trusted resources, they will bypass filtering rules.
We dug into one of these services, Amazon CloudFront, and developed a proof-of-concept for the team as soon as we read this, and present it here for you the reader.
Step 0: Punch a hole in our NAT for demo purposes
In this example we were using Ngrok to punch a hole in our NAT and to hide our IP address from you pesky readers. If you’re going to do this IRL replace any instance of 0.tcp.ngrok.io with your own hostname or IP address. If you haven’t heard of Ngrok, check it out!
Pro Tip: Use a hostname for C2 channels, if an IP address gets blocked, you can easily move your infrastructure.
This creates a listener at 0.tcp.ngrok.io on port 14380 and will forward all traffic to our localhost on port 80.
Step 1: Setup CloudFront
The process of setting up CloudFront is not too difficult, but we’ll save you some time by giving you the configuration details needed to make a C2 payload work. Please feel free to buy us a Coke next time you see us. We’re going to assume you have setup an AWS account. You will end up with a “CloudFront Distribution” that looks like this on your dashboard.
In the above picture, you can see a domain name has been provided “d6xxxxf1ac.cloudfront.net”. We will use this in our payload for the destination address.
To get there you’ll need to modify the origin and behaviors, here’s what we used.
The “edit behavior” menu is the most important part of this equation. We need to ensure that CloudFront never caches the request/response and will always forward. Additionally, we need to ensure that the request and response are not modified, or else our Malleable C2 profile may not work.
Step 2: Cobalt Strike
We need to configure Cobalt Strike to work with CloudFront, which is easy. First, the listener needs to be configured for the CloudFront domain provided. Then we need to build a Malleable C2 profile that will set the host header to the CloudFront domain. Finally, we’ll setup scripted web delivery for our demo.
Step 3: Delivery and Execution
We used PowerShell on a lab system for demonstration purposes.
Here is a portion of the packet capture showing the stager loading over the wire.
The Cobalt Strike stager does not currently use the Malleable C2 profile. So, you will need to have your beacon listener set accordingly in the console, that way the host header in the initial HTTP requests will be set correctly.
There you have it. There is another aspect on domain fronting that is discussed within the aforementioned post and research - you can establish the TCP connection using the hostname of a different domain than the one you are using, and then use the host header for routing. We did not attempt this approach, but it is something worth investigating for sure.
So, how do you prevent this? We haven’t come up with the almighty panacea, however; there are a few things you can do.
- Configure your systems to perform active inspection of all traffic, even if the URL is allowed.
- Enforce stricter rules, for example, don’t allow *.amazonaws.com, or *.google.com. Note, this is going to be tedious and may block legitimate traffic.
- Monitor and alert on excessive requests to any site, especially outside of normal operating hours.
Any others? Please provide suggestions in the comments. We would love to hear them. Additionally, if you would like to talk more about how you can prevent this step in the attack chain as well as others, please reach out to us. We can work with you to ensure your network is resilient to attacks, such as this.