Livesport - Vertical privilege escalation(s)

Intro

I was probing some Livesport properties and noticed something odd about how user registration worked on two of their subdomains - bonusy.livesport.cz and soutez.livesport.cz. What started as a fairly routine finding about a poorly secured signup endpoint quickly escalated: the same registration flaw turned out to be the entry point to full administrative access on both subdomains. One let me manipulate sports betting bonus listings shown to all users; the other let me rig Euro 2024 contest results.

All findings were reported to Livesport's security team, promptly fixed, and rewarded through their bug bounty program. This writeup covers the full chain across all three reports.

A note on classification: The access control issue is technically best described as privilege misassignment at registration - new users were granted admin-level access without any escalation step. In practice, most bug bounty programs and OWASP's Broken Access Control taxonomy (A01:2025) categorize this under Vertical Privilege Escalation, and that's how it was reported and accepted here. Worth being aware of the nuance if you're building your own reports.

The target

Both affected applications are built on Bubble, a no-code platform that compiles frontend interactions into API calls against a backend runtime. Bubble exposes a set of standard endpoints for user management (/user/signup, /user/login, /user/hi, etc.) and a workflow execution endpoint (/workflow/start) that drives server-side business logic. Understanding this underlying platform turned out to be key to all findings.

The two subdomains had different purposes but shared the same Bubble foundation and, as it turned out, the same security misconfigurations:

  • bonusy.livesport.cz - a bonus comparison page for Czech sports betting operators (Tipsport, Fortuna, Betano, Chance), showing deposit bonuses, free bet offers, and affiliate CTAs.
  • soutez.livesport.cz - a contest platform tied to Euro 2024, letting users predict match outcomes for a chance to win prizes.

Findings

#1: Insecure User Registration Endpoint

Affected URLs: https://bonusy.livesport.cz · https://soutez.livesport.cz

Description

While mapping the attack surface of both applications, I noticed the Bubble-standard /user/signup endpoint was publicly reachable and accepted registrations without any meaningful validation. Three issues stacked on top of each other:

  1. No email verification - accounts were created and immediately active; no confirmation link, no challenge.
  2. Weak password policy - the endpoint accepted a password as short as a single character.
  3. No rate limiting - nothing stopped automated, bulk account creation.

Proof of Concept

The discovery was iterative. Hitting the endpoint without parameters returned a descriptive error:

GET /user/signup HTTP/2
Host: bonusy.livesport.cz

HTTP/2 400 Bad Request
{"message":"NO_EMAIL","translation":"Prosím zadejte email"}

Adding an email but no password:

GET /user/signup?email=test2@qwerty.com HTTP/2
Host: bonusy.livesport.cz

HTTP/2 400 Bad Request
{"message":"NO_PASSWORD","translation":"Prosím zadejte heslo"}

And with both - success, with a single-character password:

GET /user/signup?email=test2@qwerty.com&password=a HTTP/2
Host: bonusy.livesport.cz

HTTP/2 200 OK
"1718007830927x469356327557668000"

The response returned the new user's internal ID, and the session cookies were immediately set and valid.

Mass Account Creation

To confirm the absence of rate limiting, I wrote a quick Bash script:

#!/bin/bash
for i in {1..10}; do
  email="testuser$i@qwerty.com"
  password="a"
  curl -X GET "https://bonusy.livesport.cz/user/signup?email=$email&password=$password"
done

All ten accounts were created in rapid succession with no throttling or blocking. I intentionally stopped at ten (using a traceable testuser1-10@qwerty.com range) so the accounts could be easily found and deleted in the database.

Account Enumeration

A useful side-effect of the descriptive error messages: re-registering an already-taken email returned a distinct USED_EMAIL error, making it straightforward to enumerate whether any given address was registered on the platform.

HTTP/2 400 Bad Request
{"message":"USED_EMAIL","translation":"Tento email se již používá: testuser3@qwerty.com"}

Impact

  • Account enumeration - an attacker can determine which email addresses have registered accounts.
  • Weak password policy - trivial brute-force against any account whose email is known.
  • Mass account creation - spam, abuse of per-user quotas, and potential resource exhaustion.

On its own, a medium-severity finding. In combination with Finding #2 and #3 below, the severity multiplies significantly.

#2: Vertical Privilege Escalation on bonusy.livesport.cz

Affected URL: https://bonusy.livesport.cz

Description

After registering a test account on bonusy.livesport.cz via the unprotected signup endpoint, I probed what that account could access. The admin panel at https://bonusy.livesport.cz/admin/ turned out to be fully accessible - with complete read/write/delete permissions over all bonus listings on the site.

The user data model confirmed the account had no special role. A call to /api/1.1/init/data showed _type: "user" with no admin flag, group membership, or elevated attribute of any kind. Despite this, the admin interface and all its workflows were freely accessible and fully functional.

Proof of Concept

Using test account bugbounty01@qwerty.com created via /user/signup, authenticating to the admin panel succeeded immediately. Inside the admin panel at https://bonusy.livesport.cz/admin/, I had access to:

  • A full list of all current bonus listings with edit and delete controls for each entry
  • A Create Bonus button to add new listings

Log into the administration.

I was able to see all available bonuses.

I can edit any of the existing bonuses as I see fit (Tipsport – Free 500 CZK for your first bets). Alternatively, there is a “trash can” icon, which means I can delete any bonusat the same time.

Or it's possible to create a fully new bonus using "Create Bonus" button.

Solely for proof-of-concept purposes, I took the liberty of creating a new bonus titled “Test Bonus – Non-functional” to confirm the above statement that everything can indeed be edited as desired. I set the URL to https://livesport.cz, so that if you happen to visit it “by accident,” you’ll be redirected to your main website at most.

Bonus created.

Impact

The impact here is more serious than it might initially appear. An attacker with this access could:

  • Content tampering for phishing: Modify the CTA URLs of existing bonus listings to redirect users to attacker-controlled phishing pages. The bonusy.livesport.cz page is a trusted Livesport property, so users clicking through a "Tipsport - 500 Kč zdarma" button would have no reason to suspect the destination had been swapped.

  • Fake bonus creation: Create entirely fictional, highly attractive bonuses to maximize click-through to a malicious URL - exploiting the trust users place in the Livesport brand.

  • Content destruction: Delete all existing listings, disrupting the page's core function.

The phishing vector in particular represents a meaningful risk to end users, not just to Livesport operationally.

#3: Vertical Privilege Escalation on soutez.livesport.cz

Affected URL: https://soutez.livesport.cz

Description

The same misconfiguration was present on the contest subdomain. After registering via /user/signup, the admin interface at https://soutez.livesport.cz/admin/ was fully accessible. In this case the stakes were different: the admin panel controlled Euro 2024 contest draws.

Proof of Concept

Test account bugbounty02@qwerty.com was registered and used to authenticate against the admin panel via POST /workflow/start. The server returned "outcome":"success" and the session was established.

I was successfully logged in to the admin panel. Inside the Administrace Soutěže panel, the active contest at the time was a prediction for the Germany vs. Scotland match (14 June 2024, 21:00), with 30 submitted entries and a Vylosovat (Draw Winner) button available and functional. I did not interact with the draw functionality. I stopped at confirming the access, documented it, and reported immediately.

As I was sending this report to Livesport, this poll was running.

Impact

The full abuse chain using Findings #1 and #3 together:

  1. Register multiple accounts via the unprotected /user/signup endpoint - no limit, no verification.
  2. Submit contest predictions from each account, maximizing the share of entries belonging to the attacker.
  3. Log into the admin panel with any of those same accounts.
  4. Trigger the winner draw at the moment that maximizes the chance of one of your own entries being selected - or simply wait and re-trigger if the result isn't favorable (depending on how the draw workflow is implemented).

Every future contest on this platform could be manipulated and won on demand. The combination of mass account creation and admin draw access made this a complete contest integrity failure.

Timeline

  • 14 Jun 2024: Insecure User Registration Endpoint and Vertical Privilege Escalations reported thru https://bugbounty.livesport.eu/
  • 14 Jun 2024: Vendor acknowledged all reports yet the same day and vulnerabilities was assessed as valid.
  • 7 August 2024: Unfortunately, both subdomains was officially out-of-scope, but they liked the issues and rewarded $200.00 and 10 points. Both websites were 3rd party website made via Bubble.io by their contractor.