(Re)visiting Cloudflare Workers for C2
(Ab)using Cloudflare Workers for C2 isn’t a new concept1. Having worked with them heavily for the past couple of months, I ran across some features that make them extra interesting for C2 redirectors.
The request.cf object
I haven’t seen other posts about the subject mentioning the request.cf object. This object “… contains information about the request provided by Cloudflare’s edge…”
In practice this means that it has a number of attributes automatically populated with information about the request that you usually have to manually query for in traditional C2 redirector setups (E.g. self-hosted reverse proxies).
Here are some of the things the request.cf object populates for each request (For a full list refer to the documentation):
ASN
ASN Organization
Country
City
TLS Cipher
TLS Version
Timezone
“Implicitly” having this info makes C2 redirection logic a breeze and the entire setup more lightweight, especially compared to using NGINX where wrestling with a bunch of weird-ass modules and it's config syntax is required to get this same information.
Here’s a dumb example of using some of the attributes in the request.cf object with the HonoJS framework and conditionally redirecting based off of their value:
import { Hono } from "hono"; | |
const app = new Hono() | |
app.get('/', async (c) => { | |
const bad_user_agent_array = ['curl', 'httpie'] | |
const user_agent = c.req.header('User-Agent') | |
const ip = c.req.header("CF-Connecting-IP") | |
console.log(user_agent) | |
//Object.keys(c.req.cf) | |
// .forEach( key => console.log(`${key}: ${c.req.cf[key]}`)) | |
const user_agent_test = bad_user_agent_array.some( x => { | |
return user_agent.toLowerCase().startsWith(x.toLowerCase()) | |
}) | |
const asn_org_test = c.req.cf.asOrganization.starsWith("Microsoft") | |
const detected = user_agent_test || asn_org_test | |
console.log(detected) | |
switch(detected){ | |
case true: | |
return c.body('nope', 404) | |
case false: | |
return c.body('yes', 200) | |
} | |
}) |
API Shield
A tlsClientAuth attribute is also available in the aforementioned request.cf object
Long story short you can setup Cloudflare API Shield in front of your Workers in order to only allow requests with a client certificate (mTLS). This is really nice for mTLS C2 transports.
Bot Management
Bots suck. Especially the kind of bots that try to automatically grab your stage0 (e.g. sandboxes). Initially, I was super excited when I read the description of the botManagement attribute:
However, after a bit of digging into setting this up, it appears that Bot Management is only available for Cloudflare customers with an Enterprise plan (😭). This shouldn’t be that out of reach for internal Red Teams or consultancies.
Needless to say, having access to the client’s ja3Hash would be super interesting for this use case and opens up a lot of interesting OpSec logic.
https://ajpc500.github.io/c2/Using-CloudFlare-Workers-as-Redirectors/
https://www.bleepingcomputer.com/news/security/blackwater-malware-abuses-cloudflare-workers-for-c2-communication/