Skip to content

Commit 01e37a9

Browse files
author
HackTricks News Bot
committed
Add content from: FlareProx: Deploy Cloudflare Worker pass-through proxies for...
- Remove searchindex.js (auto-generated file)
1 parent 1719f8e commit 01e37a9

23 files changed

Lines changed: 360 additions & 12 deletions

File tree

searchindex.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/SUMMARY.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
- [Atlantis Security](pentesting-ci-cd/atlantis-security.md)
4242
- [Cloudflare Security](pentesting-ci-cd/cloudflare-security/README.md)
4343
- [Cloudflare Domains](pentesting-ci-cd/cloudflare-security/cloudflare-domains.md)
44+
- [Cloudflare Workers Pass Through Proxy Ip Rotation](pentesting-ci-cd/cloudflare-security/cloudflare-workers-pass-through-proxy-ip-rotation.md)
4445
- [Cloudflare Zero Trust Network](pentesting-ci-cd/cloudflare-security/cloudflare-zero-trust-network.md)
4546
- [Okta Security](pentesting-ci-cd/okta-security/README.md)
4647
- [Okta Hardening](pentesting-ci-cd/okta-security/okta-hardening.md)
@@ -572,3 +573,6 @@
572573

573574
- [HackTricks Pentesting Network$$external:https://book.hacktricks.wiki/en/generic-methodologies-and-resources/pentesting-network/index.html$$]()
574575
- [HackTricks Pentesting Services$$external:https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-ssh.html$$]()
576+
577+
- [Feature Store Poisoning](pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/feature-store-poisoning.md)
578+
- [Aws Sqs Dlq Redrive Exfiltration](pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-dlq-redrive-exfiltration.md)

src/pentesting-ci-cd/cloudflare-security/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ On each Cloudflare's worker check:
5454
> [!WARNING]
5555
> Note that by default a **Worker is given a URL** such as `<worker-name>.<account>.workers.dev`. The user can set it to a **subdomain** but you can always access it with that **original URL** if you know it.
5656
57+
For a practical abuse of Workers as pass-through proxies (IP rotation, FireProx-style), check:
58+
59+
{{#ref}}
60+
cloudflare-workers-pass-through-proxy-ip-rotation.md
61+
{{#endref}}
62+
5763
## R2
5864

5965
On each R2 bucket check:
Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
# Abusing Cloudflare Workers as pass-through proxies (IP rotation, FireProx-style)
2+
3+
{{#include ../../banners/hacktricks-training.md}}
4+
5+
Cloudflare Workers can be deployed as transparent HTTP pass-through proxies where the upstream target URL is supplied by the client. Requests egress from Cloudflare's network so the target observes Cloudflare IPs instead of the client's. This mirrors the well-known FireProx technique on AWS API Gateway, but uses Cloudflare Workers.
6+
7+
Key capabilities:
8+
- Support for all HTTP methods (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)
9+
- Target can be supplied via query parameter (?url=...), a header (X-Target-URL), or even encoded in the path (e.g., /https://target)
10+
- Headers and body are proxied through with hop-by-hop/header filtering as needed
11+
- Responses are relayed back, preserving status code and most headers
12+
- Optional spoofing of X-Forwarded-For (if the Worker sets it from a user-controlled header)
13+
- Extremely fast/easy rotation by deploying multiple Worker endpoints and fanning out requests
14+
15+
How it works (flow):
16+
1) Client sends an HTTP request to a Worker URL (<name>.<account>.workers.dev or a custom domain route).
17+
2) Worker extracts the target from either a query parameter (?url=...), the X-Target-URL header, or a path segment if implemented.
18+
3) Worker forwards the incoming method, headers, and body to the specified upstream URL (filtering problematic headers).
19+
4) Upstream response is streamed back to the client through Cloudflare; the origin sees Cloudflare egress IPs.
20+
21+
Worker implementation example
22+
- Reads target URL from query param, header, or path
23+
- Copies a safe subset of headers and forwards the original method/body
24+
- Optionally sets X-Forwarded-For using a user-controlled header (X-My-X-Forwarded-For) or a random IP
25+
- Adds permissive CORS and handles preflight
26+
27+
<details>
28+
<summary>Example Worker (JavaScript) for pass-through proxying</summary>
29+
30+
```javascript
31+
/**
32+
* Minimal Worker pass-through proxy
33+
* - Target URL from ?url=, X-Target-URL, or /https://...
34+
* - Proxies method/headers/body to upstream; relays response
35+
*/
36+
addEventListener('fetch', event => {
37+
event.respondWith(handleRequest(event.request))
38+
})
39+
40+
async function handleRequest(request) {
41+
try {
42+
const url = new URL(request.url)
43+
const targetUrl = getTargetUrl(url, request.headers)
44+
45+
if (!targetUrl) {
46+
return errorJSON('No target URL specified', 400, {
47+
usage: {
48+
query_param: '?url=https://example.com',
49+
header: 'X-Target-URL: https://example.com',
50+
path: '/https://example.com'
51+
}
52+
})
53+
}
54+
55+
let target
56+
try { target = new URL(targetUrl) } catch (e) {
57+
return errorJSON('Invalid target URL', 400, { provided: targetUrl })
58+
}
59+
60+
// Forward original query params except control ones
61+
const passthru = new URLSearchParams()
62+
for (const [k, v] of url.searchParams) {
63+
if (!['url', '_cb', '_t'].includes(k)) passthru.append(k, v)
64+
}
65+
if (passthru.toString()) target.search = passthru.toString()
66+
67+
// Build proxied request
68+
const proxyReq = buildProxyRequest(request, target)
69+
const upstream = await fetch(proxyReq)
70+
71+
return buildProxyResponse(upstream, request.method)
72+
} catch (error) {
73+
return errorJSON('Proxy request failed', 500, {
74+
message: error.message,
75+
timestamp: new Date().toISOString()
76+
})
77+
}
78+
}
79+
80+
function getTargetUrl(url, headers) {
81+
let t = url.searchParams.get('url') || headers.get('X-Target-URL')
82+
if (!t && url.pathname !== '/') {
83+
const p = url.pathname.slice(1)
84+
if (p.startsWith('http')) t = p
85+
}
86+
return t
87+
}
88+
89+
function buildProxyRequest(request, target) {
90+
const h = new Headers()
91+
const allow = [
92+
'accept','accept-language','accept-encoding','authorization',
93+
'cache-control','content-type','origin','referer','user-agent'
94+
]
95+
for (const [k, v] of request.headers) {
96+
if (allow.includes(k.toLowerCase())) h.set(k, v)
97+
}
98+
h.set('Host', target.hostname)
99+
100+
// Optional: spoof X-Forwarded-For if provided
101+
const spoof = request.headers.get('X-My-X-Forwarded-For')
102+
h.set('X-Forwarded-For', spoof || randomIP())
103+
104+
return new Request(target.toString(), {
105+
method: request.method,
106+
headers: h,
107+
body: ['GET','HEAD'].includes(request.method) ? null : request.body
108+
})
109+
}
110+
111+
function buildProxyResponse(resp, method) {
112+
const h = new Headers()
113+
for (const [k, v] of resp.headers) {
114+
if (!['content-encoding','content-length','transfer-encoding'].includes(k.toLowerCase())) {
115+
h.set(k, v)
116+
}
117+
}
118+
// Permissive CORS for tooling convenience
119+
h.set('Access-Control-Allow-Origin', '*')
120+
h.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, PATCH, HEAD')
121+
h.set('Access-Control-Allow-Headers', '*')
122+
123+
if (method === 'OPTIONS') return new Response(null, { status: 204, headers: h })
124+
return new Response(resp.body, { status: resp.status, statusText: resp.statusText, headers: h })
125+
}
126+
127+
function errorJSON(msg, status=400, extra={}) {
128+
return new Response(JSON.stringify({ error: msg, ...extra }), {
129+
status, headers: { 'Content-Type': 'application/json' }
130+
})
131+
}
132+
133+
function randomIP() { return [1,2,3,4].map(() => Math.floor(Math.random()*255)+1).join('.') }
134+
```
135+
136+
</details>
137+
138+
Automating deployment and rotation with FlareProx
139+
FlareProx is a Python tool that uses the Cloudflare API to deploy many Worker endpoints and rotate across them. This provides FireProx-like IP rotation from Cloudflare’s network.
140+
141+
Setup
142+
1) Create a Cloudflare API Token using the “Edit Cloudflare Workers” template and get your Account ID from the dashboard.
143+
2) Configure FlareProx:
144+
145+
```bash
146+
git clone https://github.com/MrTurvey/flareprox
147+
cd flareprox
148+
pip install -r requirements.txt
149+
```
150+
151+
Create config file flareprox.json:
152+
153+
```json
154+
{
155+
"cloudflare": {
156+
"api_token": "your_cloudflare_api_token",
157+
"account_id": "your_cloudflare_account_id"
158+
}
159+
}
160+
```
161+
162+
CLI usage
163+
- Create N Worker proxies:
164+
```bash
165+
python3 flareprox.py create --count 2
166+
```
167+
- List endpoints:
168+
```bash
169+
python3 flareprox.py list
170+
```
171+
- Health-test endpoints:
172+
```bash
173+
python3 flareprox.py test
174+
```
175+
- Delete all endpoints:
176+
```bash
177+
python3 flareprox.py cleanup
178+
```
179+
180+
Routing traffic through a Worker
181+
- Query parameter form:
182+
```bash
183+
curl "https://your-worker.account.workers.dev?url=https://httpbin.org/ip"
184+
```
185+
- Header form:
186+
```bash
187+
curl -H "X-Target-URL: https://httpbin.org/ip" https://your-worker.account.workers.dev
188+
```
189+
- Path form (if implemented):
190+
```bash
191+
curl https://your-worker.account.workers.dev/https://httpbin.org/ip
192+
```
193+
- Method examples:
194+
```bash
195+
# GET
196+
curl "https://your-worker.account.workers.dev?url=https://httpbin.org/get"
197+
198+
# POST (form)
199+
curl -X POST -d "username=admin" \
200+
"https://your-worker.account.workers.dev?url=https://httpbin.org/post"
201+
202+
# PUT (JSON)
203+
curl -X PUT -d '{"username":"admin"}' -H "Content-Type: application/json" \
204+
"https://your-worker.account.workers.dev?url=https://httpbin.org/put"
205+
206+
# DELETE
207+
curl -X DELETE \
208+
"https://your-worker.account.workers.dev?url=https://httpbin.org/delete"
209+
```
210+
211+
X-Forwarded-For control
212+
If the Worker honors X-My-X-Forwarded-For, you can influence the upstream X-Forwarded-For value:
213+
```bash
214+
curl -H "X-My-X-Forwarded-For: 203.0.113.10" \
215+
"https://your-worker.account.workers.dev?url=https://httpbin.org/headers"
216+
```
217+
218+
Programmatic usage
219+
Use the FlareProx library to create/list/test endpoints and route requests from Python.
220+
221+
<details>
222+
<summary>Python example: Send a POST via a random Worker endpoint</summary>
223+
224+
```python
225+
#!/usr/bin/env python3
226+
from flareprox import FlareProx, FlareProxError
227+
import json
228+
229+
# Initialize
230+
flareprox = FlareProx(config_file="flareprox.json")
231+
if not flareprox.is_configured:
232+
print("FlareProx not configured. Run: python3 flareprox.py config")
233+
exit(1)
234+
235+
# Ensure endpoints exist
236+
endpoints = flareprox.sync_endpoints()
237+
if not endpoints:
238+
print("Creating proxy endpoints...")
239+
flareprox.create_proxies(count=2)
240+
241+
# Make a POST request through a random endpoint
242+
try:
243+
post_data = json.dumps({
244+
"username": "testuser",
245+
"message": "Hello from FlareProx!",
246+
"timestamp": "2025-01-01T12:00:00Z"
247+
})
248+
249+
headers = {
250+
"Content-Type": "application/json",
251+
"User-Agent": "FlareProx-Client/1.0"
252+
}
253+
254+
response = flareprox.redirect_request(
255+
target_url="https://httpbin.org/post",
256+
method="POST",
257+
headers=headers,
258+
data=post_data
259+
)
260+
261+
if response.status_code == 200:
262+
result = response.json()
263+
print("✓ POST successful via FlareProx")
264+
print(f"Origin IP: {result.get('origin', 'unknown')}")
265+
print(f"Posted data: {result.get('json', {})}")
266+
else:
267+
print(f"Request failed with status: {response.status_code}")
268+
269+
except FlareProxError as e:
270+
print(f"FlareProx error: {e}")
271+
except Exception as e:
272+
print(f"Request error: {e}")
273+
```
274+
275+
</details>
276+
277+
Burp/Scanner integration
278+
- Point tooling (for example, Burp Suite) at the Worker URL.
279+
- Supply the real upstream using ?url= or X-Target-URL.
280+
- HTTP semantics (methods/headers/body) are preserved while masking your source IP behind Cloudflare.
281+
282+
Operational notes and limits
283+
- Cloudflare Workers Free plan allows roughly 100,000 requests/day per account; use multiple endpoints to distribute traffic if needed.
284+
- Workers run on Cloudflare’s network; many targets will only see Cloudflare IPs/ASN, which can bypass naive IP allow/deny lists or geo heuristics.
285+
- Use responsibly and only with authorization. Respect ToS and robots.txt.
286+
287+
Detection and mitigation (defender notes)
288+
If your application is the target and you wish to prevent access via generic Cloudflare-originated proxies (Workers, other Cloudflare egress):
289+
- Do not rely solely on IP allow/deny lists; Cloudflare Workers share Cloudflare IP space and ASN (AS13335). Blocking all Cloudflare IPs is often impractical.
290+
- Require strong request authentication at the application layer (tokens, HMAC-signed headers, mTLS, per-client API keys), and validate them server-side.
291+
- For Cloudflare-protected origins you control, consider:
292+
- Authenticated Origin Pulls or mTLS between Cloudflare and origin so only your own zone can reach the origin.
293+
- WAF/Firewall Rules that require a secret header or signed token and block requests missing them.
294+
- API Shield (schema validation, mTLS, JWT validation) and Bot Fight Mode/Super Bot Fight Mode to reduce automated abuse.
295+
- Rate limiting by path/user token; challenge or block requests lacking expected cookies/headers from your first-party app flows.
296+
- Monitor for anomalies: unusual user agents, inconsistent headers, rapidly shifting Cloudflare IPs, or requests to endpoints that should only be hit by your front-end.
297+
298+
Related techniques
299+
- FireProx (AWS API Gateway) pioneered pass-through proxying for IP rotation and header control; Workers provide a similar pattern with Cloudflare egress.
300+
301+
## References
302+
- [FlareProx (Cloudflare Workers pass-through/rotation)](https://github.com/MrTurvey/flareprox)
303+
- [Cloudflare Workers fetch() API](https://developers.cloudflare.com/workers/runtime-apis/fetch/)
304+
- [Cloudflare Workers pricing and free tier](https://developers.cloudflare.com/workers/platform/pricing/)
305+
- [FireProx (AWS API Gateway)](https://github.com/ustayready/fireprox)
306+
307+
{{#include ../../banners/hacktricks-training.md}}

src/pentesting-cloud/aws-security/aws-persistence/aws-lambda-persistence/aws-lambda-async-self-loop-persistence.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# AWS - Lambda Async Self-Loop Persistence via Destinations + Recursion Allow
22

3+
{{#include ../../../../banners/hacktricks-training.md}}
4+
35
Abuse Lambda asynchronous destinations together with the Recursion configuration to make a function continually re-invoke itself with no external scheduler (no EventBridge, cron, etc.). By default, Lambda terminates recursive loops, but setting the recursion config to Allow re-enables them. Destinations deliver on the service side for async invokes, so a single seed invoke creates a stealthy, code-free heartbeat/backdoor channel. Optionally throttle with reserved concurrency to keep noise low.
46

57
Notes
@@ -99,3 +101,4 @@ aws iam delete-role-policy --role-name "$ROLE_NAME" --policy-name allow-invoke-s
99101

100102
## Impact
101103
- Single async invoke causes Lambda to continually re-invoke itself with no external scheduler, enabling stealthy persistence/heartbeat. Reserved concurrency can limit noise to a single warm execution.
104+
{{#include ../../../../banners/hacktricks-training.md}}

src/pentesting-cloud/aws-security/aws-persistence/aws-secrets-manager-persistence/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def generate_password():
5050
return password
5151
```
5252

53-
{{#include ../../../../banners/hacktricks-training.md}}
53+
5454

5555

5656

@@ -248,3 +248,4 @@ aws secretsmanager get-resource-policy --region "$R2" --secret-id "$NAME"
248248
# Configure attacker credentials and read
249249
aws secretsmanager get-secret-value --region "$R2" --secret-id "$NAME" --query SecretString --output text
250250
```
251+
{{#include ../../../../banners/hacktricks-training.md}}

src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-ec2-instance-connect-endpoint-backdoor.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,4 @@ aws ec2 delete-instance-connect-endpoint \
119119
> Notes
120120
> - The injected SSH key is only valid for ~60 seconds; send the key right before opening the tunnel/SSH.
121121
> - `OS_USER` must match the AMI (e.g., `ubuntu` for Ubuntu, `ec2-user` for Amazon Linux 2).
122+
{{#include ../../../../banners/hacktricks-training.md}}

src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-eni-secondary-ip-hijack.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,4 @@ curl --interface $HIJACK_IP -sS http://$PROTECTED_HOST -o /tmp/poc.out && head -
5555
## Impact
5656
- Bypass IP allowlists and impersonate trusted hosts within the VPC by moving secondary private IPs between ENIs in the same subnet/AZ.
5757
- Reach internal services that gate access by specific source IPs, enabling lateral movement and data access.
58+
{{#include ../../../../banners/hacktricks-training.md}}

src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ aws ecr batch-delete-image --repository-name your-ecr-repo-name --image-ids imag
9494
aws ecr-public batch-delete-image --repository-name your-ecr-repo-name --image-ids imageTag=latest imageTag=v1.0.0
9595
```
9696

97-
{{#include ../../../../banners/hacktricks-training.md}}
97+
9898

9999

100100

@@ -218,3 +218,4 @@ aws ecr put-registry-scanning-configuration --region $REGION --scan-type BASIC -
218218
aws ecr put-account-setting --region $REGION --name BASIC_SCAN_TYPE_VERSION --value AWS_NATIVE
219219
```
220220

221+
{{#include ../../../../banners/hacktricks-training.md}}

0 commit comments

Comments
 (0)