- Status Closed
-
Assigned To
cbay - Private
Opened by awais0x01 - 21.07.2026
Last edited by cbay - 22.07.2026
FS#419 - Server-Side Request Forgery via Reverse Proxy Site Type Accepting Internal URLs
## Severity
High (CVSS 3.1: 7.2 - CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N)
## Weakness
CWE-918: Server-Side Request Forgery (SSRF)
## Summary
The "Reverse proxy" site type in the site creation form (`/site/add/`) accepts arbitrary URLs including private/internal IP addresses (127.0.0.1, 169.254.169.254, 10.x.x.x) as the "Remote URL" target. The platform creates an Apache ProxyPass directive proxying all requests to the attacker-specified URL without IP validation. This enables full-read SSRF from the shared hosting server, allowing an attacker to scan internal services, probe localhost ports, and exfiltrate response bodies from any HTTP service reachable from the web server process.
## Steps to Reproduce
Environment: Free hosting account on alwaysdata.com.
1. Log in to the admin panel at `https://admin.alwaysdata.com/login/`.
2. Navigate to the site creation form at `https://admin.alwaysdata.com/site/add/`.
3. Select the "Reverse proxy" site type from the Type dropdown.
4. In the "Remote URL" field, enter an internal IP address or a Collaborator URL:
For external SSRF verification:
```
http://YOUR-COLLABORATOR-ID.oastify.com/ ```
For internal port scanning:
```
http://127.0.0.1:9200/ ```
5. Set a site address (use your assigned subdomain, e.g., `ACCOUNT.alwaysdata.net`).
6. Save the form. The form accepts the URL and creates the site (HTTP 302 redirect).
7. Trigger the SSRF by visiting your site:
```
curl https://ACCOUNT.alwaysdata.net/ ```
8. Observe the result:
- For external URLs: the Collaborator receives a DNS and HTTP interaction from the alwaysdata infrastructure IP (185.31.41.10). The full response body from the target URL is returned to the attacker.
- For localhost ports: HTTP 503 indicates the port is closed/down; timeout indicates a firewall block. This differential enables internal port scanning.
## Evidence
Collaborator interaction captured: - DNS query from 185.31.40.97 (alwaysdata DNS resolver)
- HTTP request from 185.31.41.10 (shared web hosting server)
- Request headers: `Via: 1.1 alproxy, 1.1 ACCOUNT.alwaysdata.net`
- Full response body from the target was returned verbatim to the attacker (not blind SSRF)
Internal port scan results: - 127.0.0.1:9200 (Elasticsearch port): HTTP 503 (connection refused - port accessible but service down)
- 127.0.0.1:8500 (Consul port): HTTP 503 (connection refused)
- 169.254.169.254 (cloud metadata): timeout (network-level block present)
## Impact
An authenticated user with a free hosting account can:
1. Scan internal services on the shared hosting node via localhost, identifying running services by port
2. Exfiltrate data from any internal HTTP service reachable from the Apache process, including services that are not exposed to the internet
3. Bypass IP-based access controls that trust the hosting infrastructure's IP range (185.31.x.x)
4. Probe internal network for services on RFC 1918 addresses
The SSRF is full-read (response bodies are returned to the attacker), not blind. The Apache process making these requests runs as a system service, potentially reaching services that individual tenant processes cannot access.
## Root Cause
The "Remote URL" field in the reverse proxy site type does not validate the target URL against a blocklist of private/internal IP ranges. The validation only checks URL scheme (allowing http, https, ftp; blocking gopher, file, dict) but does not verify that the resolved IP address is not a private/loopback/link-local address.
## Remediation
1. Validate the Remote URL against private IP ranges before creating the ProxyPass directive. Block: 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, ::1/128, fc00::/7
2. Resolve DNS before validation to prevent DNS rebinding attacks (check the IP AFTER resolution, not just the hostname)
3. Apply the same validation to both initial configuration and Apache runtime (in case of DNS changes after configuration)
Loading...
Available keyboard shortcuts
- Alt + ⇧ Shift + l Login Dialog / Logout
- Alt + ⇧ Shift + a Add new task
- Alt + ⇧ Shift + m My searches
- Alt + ⇧ Shift + t focus taskid search
Tasklist
- o open selected task
- j move cursor down
- k move cursor up
Task Details
- n Next task
- p Previous task
- Alt + ⇧ Shift + e ↵ Enter Edit this task
- Alt + ⇧ Shift + w watch task
- Alt + ⇧ Shift + y Close Task
Task Editing
- Alt + ⇧ Shift + s save task