- Status Closed
-
Assigned To
cbay - Private
Opened by zlynv - 25.09.2026
Last edited by cbay - 25.09.2026
FS#502 - Site address binding lacks ownership validation
Summary field: Site address binding lacks ownership validation: any account can hijack vhost traffic for third-party domains resolving to Alwaysdata
—
Details field:
Affected endpoint (in scope) https://api.alwaysdata.com/v1/site/{id}/ - addresses (create and PATCH), and the equivalent front-end site address form (same validation).
Summary
Binding a hostname to a site requires no proof of domain control whatsoever. The platform accepts any syntactically valid domain and, after the async vhost update, serves the attacker's site for every request carrying that Host/SNI. A low-privileged account can therefore bind third-party domains whose traffic already reaches your infrastructure - dangling DNS left behind by churned customers, stale A/AAAA records, or domains that simply point at Alwaysdata without being hosted here - and answer that traffic with an attacker-controlled web application.
Two clarifications up front, because both will otherwise be raised:
1. *The documentation says customers just point DNS and declare the address:* true - but that documented workflow presumes the declarer hosts the domain. Nothing verifies the presumption. There is no DNS TXT challenge, no HTTP token, no whois/registry check at bind time. Format is the only validation ("recon-hijack.example" → 400 "format incorrect"; a fully formed domain the tester does not own → 204).
2. *Uniqueness between customers is enforced (cf. FS#321 closure: "two customers cannot configure the same domain"):* also true - and I verified it deliberately on both code paths:
CREATE site with an address already used by another site ->
400 {"address": ["L'adresse docs.alwaysdata.net/ est deja utilisee par un autre site."]}
PATCH site with the same already-used address ->
400 {"address": ["L'adresse docs.alwaysdata.net/ est deja utilisee par un autre site."]}
But uniqueness is not ownership: it only prevents conflicts among hostnames that are already configured on the platform. A third-party domain that is configured by nobody (the scenarios in the impact section) has no existing configuration to conflict with, passes the uniqueness check trivially, and is then bound with zero proof of control. The invariant "your hostname serves your site" silently fails for every hostname not currently claimed.
Steps to reproduce
1. Register any low-privilege account with one site (my existing test account, site id 1080353).
2. Add a domain you do not own and cannot prove control of:
PATCH https://api.alwaysdata.com/v1/site/1080353/
Authorization: Basic <token-id>:
Content-Type: application/json
{"addresses":["docs.alwaysdata.net/","recon-hijack-xyz123.com/"]}
→ 204 No Content.
3. Wait for the platform task "Updating the front-end HTTP configuration (hostnames)" to propagate (~45 seconds observed), then send traffic for the claimed domain to the server IP:
GET / HTTP/1.1 Host: recon-hijack-xyz123.com Connection: close -> 200, serving MY site's content (index page in my www/) Control - before the claim, after revert, or with an unclaimed host: -> 404 "Site not found"
The 404 → 200 → 404 control loop establishes causality between the API modification and the vhost routing change.
4. HTTP-01 challenge response control. Place a marker file at /.well-known/acme-challenge/recontest in my www/ (WebDAV, my own account), then:
GET /.well-known/acme-challenge/recontest HTTP/1.1 Host: recon-hijack-xyz123.com -> 200 "recon-acme-marker-OK"
The attacker can control the HTTP-01 challenge response for any domain that resolves to the affected Alwaysdata infrastructure. This creates the prerequisite for certificate issuance through an HTTP-01 ACME workflow, subject to the platform's certificate-provisioning behavior. (I have not demonstrated issuance for a domain owned by someone else, and no real third-party domain was ever claimed during testing - only a non-resolving throwaway name, requested solely against your own in-scope IP.)
5. Cleanup (immediately after verification):
PATCH {"addresses":["docs.alwaysdata.net/"]} -> 204
GET / with Host: recon-hijack-xyz123.com -> 404 again (async propagation, ~45s)
WebDAV DELETE marker + .well-known dirs -> 204, GET -> 404
Temporary second site (uniqueness test) -> DELETE 204, listings verified
Impact
Any third-party domain whose traffic resolves to an affected Alwaysdata server/IP can potentially be rebound to an attacker-controlled Alwaysdata site. Concretely:
- Dangling DNS - a former customer's A/AAAA records still point at your infrastructure after their site (and thus their address configuration) is gone. Uniqueness no longer protects it: nothing is configured to conflict with.
- Stale or misconfigured records - domains that were never hosted here but resolve here through leftover or erroneous DNS.
- Domains intentionally pointing at Alwaysdata for parts of their setup (mail, subdomains) while their main website lives elsewhere - the web traffic still lands on your IPs.
For any such domain the attacker serves arbitrary content on both HTTP and HTTPS (SNI routing demonstrated above) under the victim's exact hostname: phishing, credential harvesting, content spoofing. If certificate provisioning for the bound hostname follows the HTTP-01 path, the challenge response is the attacker's (demonstrated) - an escalation path to a publicly trusted certificate for the victim hostname, making the HTTPS hijack indistinguishable from legitimate.
Note this is not a Host-header reflection issue (excluded by program rules): the attacker modifies persistent vhost configuration through an authenticated API, and the platform itself routes real traffic to the attacker's site thereafter. The attacker does not gain control of the victim's DNS - they exploit the fact that the traffic already reaches Alwaysdata.
Suggested classification: High (cross-organization traffic takeover of third-party hostnames), with certificate issuance as an escalation path rather than the sole basis for severity. For reference, FS#438 (domain-transfer logic flaw) was classified Critical and fixed; FS#321 (HTTP-01 webroot poisoning) was closed as invalid on the grounds that "two customers cannot configure the same domain" - which, as shown above, is enforced, but answers a different question than the one this finding poses.
Root cause
Address binding performs a format check and a uniqueness check against currently configured addresses, but never a domain-control verification (DNS TXT challenge, HTTP token, or registry/whois check). Uniqueness and ownership are different properties; only the former is implemented, and only the former was ever the subject of the FS#321 dismissal.
Suggested remediation: require proof of domain control before a hostname becomes routable - e.g. DNS TXT record for the domain, or an HTTP token served from the domain's current origin - and apply the same gate on the PATCH/update path as on create. Additionally consider refusing to bind hostnames that resolve to your infrastructure but have no active customer configuration (the dangling-DNS case), or warn loudly when binding a hostname whose registry/SOA data indicates a different holder.
Relation to my previous reports
Independent of my earlier tasks (WebDAV ..%2f, site path "../", webdav/ftp path "../") - those were file-system root-escape issues bounded by your per-account UID isolation. This one is about the hosting control plane binding third-party domain names and reaches outside your customer base entirely.
Account used for testing
- Same test customer account as my previous tasks (details available on request).
- All state reverted (addresses, marker files, temporary test site); listings verified back to original.
- No third-party domain, customer, or traffic involved at any point; the claimed hostname does not resolve in public DNS.
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
Hello,
We do not consider this a vulnerability. If you own a domain and have it point to our servers, yet haven't setup anything on alwaysdata, then you have a problem.
Kind regards,
Cyril