Abuser Cloudflare Workers en tant que proxies pass-through (rotation d'IP, FireProx-style)

Reading time: 9 minutes

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Cloudflare Workers peuvent ĂȘtre dĂ©ployĂ©s comme des proxies HTTP transparents pass-through oĂč l'URL cible upstream est fournie par le client. Les requĂȘtes sortent du rĂ©seau Cloudflare, donc la cible voit les IPs de Cloudflare au lieu de celles du client. Cela reflĂšte la technique bien connue FireProx sur AWS API Gateway, mais utilise Cloudflare Workers.

Fonctionnalités clés

  • Prise en charge de toutes les mĂ©thodes HTTP (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)
  • La cible peut ĂȘtre fournie via un paramĂštre de requĂȘte (?url=...), un header (X-Target-URL), ou mĂȘme encodĂ©e dans le chemin (par ex. /https://target)
  • Les headers et le corps sont relayĂ©s via le proxy avec filtrage des headers hop-by-hop si nĂ©cessaire
  • Les rĂ©ponses sont renvoyĂ©es en conservant le code de statut et la plupart des headers
  • Usurpation optionnelle de X-Forwarded-For (si le Worker le dĂ©finit Ă  partir d'un header contrĂŽlĂ© par l'utilisateur)
  • Rotation trĂšs rapide/facile en dĂ©ployant plusieurs endpoints Worker et en rĂ©partissant les requĂȘtes

Comment ça marche (flux)

  1. Le client envoie une requĂȘte HTTP vers une URL Worker (<name>.<account>.workers.dev ou un route de domaine personnalisĂ©).
  2. Le Worker extrait la cible soit d'un paramĂštre de requĂȘte (?url=...), soit du header X-Target-URL, ou d'un segment de chemin si implĂ©mentĂ©.
  3. Le Worker transfÚre la méthode, les headers et le corps entrants vers l'URL upstream spécifiée (en filtrant les headers problématiques).
  4. La réponse upstream est streamée vers le client via Cloudflare ; l'origine voit les IPs de sortie de Cloudflare.

Exemple d'implémentation du Worker

  • Lit l'URL cible depuis un paramĂštre de requĂȘte, un header ou le chemin
  • Copie un sous-ensemble sĂ»r de headers et transmet la mĂ©thode/le corps originaux
  • DĂ©finit optionnellement X-Forwarded-For en utilisant un header contrĂŽlĂ© par l'utilisateur (X-My-X-Forwarded-For) ou une IP alĂ©atoire
  • Ajoute un CORS permissif et gĂšre les preflight
Exemple de Worker (JavaScript) pour le proxy pass-through
javascript
/**
* Minimal Worker pass-through proxy
* - Target URL from ?url=, X-Target-URL, or /https://...
* - Proxies method/headers/body to upstream; relays response
*/
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
try {
const url = new URL(request.url)
const targetUrl = getTargetUrl(url, request.headers)

if (!targetUrl) {
return errorJSON('No target URL specified', 400, {
usage: {
query_param: '?url=https://example.com',
header: 'X-Target-URL: https://example.com',
path: '/https://example.com'
}
})
}

let target
try { target = new URL(targetUrl) } catch (e) {
return errorJSON('Invalid target URL', 400, { provided: targetUrl })
}

// Forward original query params except control ones
const passthru = new URLSearchParams()
for (const [k, v] of url.searchParams) {
if (!['url', '_cb', '_t'].includes(k)) passthru.append(k, v)
}
if (passthru.toString()) target.search = passthru.toString()

// Build proxied request
const proxyReq = buildProxyRequest(request, target)
const upstream = await fetch(proxyReq)

return buildProxyResponse(upstream, request.method)
} catch (error) {
return errorJSON('Proxy request failed', 500, {
message: error.message,
timestamp: new Date().toISOString()
})
}
}

function getTargetUrl(url, headers) {
let t = url.searchParams.get('url') || headers.get('X-Target-URL')
if (!t && url.pathname !== '/') {
const p = url.pathname.slice(1)
if (p.startsWith('http')) t = p
}
return t
}

function buildProxyRequest(request, target) {
const h = new Headers()
const allow = [
'accept','accept-language','accept-encoding','authorization',
'cache-control','content-type','origin','referer','user-agent'
]
for (const [k, v] of request.headers) {
if (allow.includes(k.toLowerCase())) h.set(k, v)
}
h.set('Host', target.hostname)

// Optional: spoof X-Forwarded-For if provided
const spoof = request.headers.get('X-My-X-Forwarded-For')
h.set('X-Forwarded-For', spoof || randomIP())

return new Request(target.toString(), {
method: request.method,
headers: h,
body: ['GET','HEAD'].includes(request.method) ? null : request.body
})
}

function buildProxyResponse(resp, method) {
const h = new Headers()
for (const [k, v] of resp.headers) {
if (!['content-encoding','content-length','transfer-encoding'].includes(k.toLowerCase())) {
h.set(k, v)
}
}
// Permissive CORS for tooling convenience
h.set('Access-Control-Allow-Origin', '*')
h.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, PATCH, HEAD')
h.set('Access-Control-Allow-Headers', '*')

if (method === 'OPTIONS') return new Response(null, { status: 204, headers: h })
return new Response(resp.body, { status: resp.status, statusText: resp.statusText, headers: h })
}

function errorJSON(msg, status=400, extra={}) {
return new Response(JSON.stringify({ error: msg, ...extra }), {
status, headers: { 'Content-Type': 'application/json' }
})
}

function randomIP() { return [1,2,3,4].map(() => Math.floor(Math.random()*255)+1).join('.') }

Automatisation du déploiement et de la rotation avec FlareProx

FlareProx est un outil Python qui utilise l'API Cloudflare pour déployer plusieurs endpoints Worker et effectuer la rotation entre eux. Cela fournit une rotation d'IP de type FireProx depuis le réseau de Cloudflare.

Setup

  1. CrĂ©ez un Cloudflare API Token en utilisant le template “Edit Cloudflare Workers” et rĂ©cupĂ©rez votre Account ID depuis le tableau de bord.
  2. Configurez FlareProx:
bash
git clone https://github.com/MrTurvey/flareprox
cd flareprox
pip install -r requirements.txt

Créer le fichier de configuration flareprox.json :

json
{
"cloudflare": {
"api_token": "your_cloudflare_api_token",
"account_id": "your_cloudflare_account_id"
}
}

Utilisation de la CLI

  • CrĂ©er N proxies Worker :
bash
python3 flareprox.py create --count 2
  • Lister les endpoints :
bash
python3 flareprox.py list
  • Points de terminaison de vĂ©rification de santĂ© :
bash
python3 flareprox.py test
  • Supprimer tous les endpoints:
bash
python3 flareprox.py cleanup

Acheminer le trafic via un Worker

  • Forme de paramĂštre de requĂȘte :
bash
curl "https://your-worker.account.workers.dev?url=https://httpbin.org/ip"
  • Formulaire d'en-tĂȘte:
bash
curl -H "X-Target-URL: https://httpbin.org/ip" https://your-worker.account.workers.dev
  • Format de chemin (si implĂ©mentĂ©):
bash
curl https://your-worker.account.workers.dev/https://httpbin.org/ip
  • Exemples de mĂ©thodes:
bash
# GET
curl "https://your-worker.account.workers.dev?url=https://httpbin.org/get"

# POST (form)
curl -X POST -d "username=admin" \
"https://your-worker.account.workers.dev?url=https://httpbin.org/post"

# PUT (JSON)
curl -X PUT -d '{"username":"admin"}' -H "Content-Type: application/json" \
"https://your-worker.account.workers.dev?url=https://httpbin.org/put"

# DELETE
curl -X DELETE \
"https://your-worker.account.workers.dev?url=https://httpbin.org/delete"

contrĂŽle de X-Forwarded-For

Si le Worker honore X-My-X-Forwarded-For, vous pouvez influencer la valeur en amont de X-Forwarded-For :

bash
curl -H "X-My-X-Forwarded-For: 203.0.113.10" \
"https://your-worker.account.workers.dev?url=https://httpbin.org/headers"

Utilisation programmatique

Utilisez la bibliothĂšque FlareProx pour crĂ©er/lister/tester des endpoints et acheminer des requĂȘtes depuis Python.

Exemple Python : Envoyer un POST via un endpoint Worker aléatoire
python
#!/usr/bin/env python3
from flareprox import FlareProx, FlareProxError
import json

# Initialize
flareprox = FlareProx(config_file="flareprox.json")
if not flareprox.is_configured:
print("FlareProx not configured. Run: python3 flareprox.py config")
exit(1)

# Ensure endpoints exist
endpoints = flareprox.sync_endpoints()
if not endpoints:
print("Creating proxy endpoints...")
flareprox.create_proxies(count=2)

# Make a POST request through a random endpoint
try:
post_data = json.dumps({
"username": "testuser",
"message": "Hello from FlareProx!",
"timestamp": "2025-01-01T12:00:00Z"
})

headers = {
"Content-Type": "application/json",
"User-Agent": "FlareProx-Client/1.0"
}

response = flareprox.redirect_request(
target_url="https://httpbin.org/post",
method="POST",
headers=headers,
data=post_data
)

if response.status_code == 200:
result = response.json()
print("✓ POST successful via FlareProx")
print(f"Origin IP: {result.get('origin', 'unknown')}")
print(f"Posted data: {result.get('json', {})}")
else:
print(f"Request failed with status: {response.status_code}")

except FlareProxError as e:
print(f"FlareProx error: {e}")
except Exception as e:
print(f"Request error: {e}")

Intégration Burp/Scanner

  • Redirigez vos outils (par exemple, Burp Suite) vers l'URL du Worker.
  • Fournissez l'upstream rĂ©el en utilisant ?url= ou X-Target-URL.
  • La sĂ©mantique HTTP (methods/headers/body) est prĂ©servĂ©e tout en masquant votre IP source derriĂšre Cloudflare.

Notes opérationnelles et limites

  • Le plan Free de Cloudflare Workers permet environ 100 000 requĂȘtes/jour par compte ; utilisez plusieurs endpoints pour rĂ©partir le trafic si nĂ©cessaire.
  • Les Workers s'exĂ©cutent sur le rĂ©seau Cloudflare ; de nombreuses cibles ne verront que les IPs/ASN de Cloudflare, ce qui peut contourner des listes d'autorisation/refus IP naĂŻves ou des heuristiques gĂ©ographiques.
  • Utilisez de maniĂšre responsable et seulement avec autorisation. Respectez les ToS et robots.txt.

Références

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks