How I Hacked a Rental Car Company
An email unsubscribe form should do one small thing: stop marketing emails. While testing a rental car company's application, I submitted an address to that form, returned to the main page, and found myself logged in as a privileged system user.
This happened during research for the company's bug bounty programme on Intigriti. The company is anonymised here.
Start with the application
The programme had a small scope: just one asset. I did not need a sprawling reconnaissance process. I began by browsing the application with Burp Suite intercepting its traffic, so I could understand its requests and behaviour.
Scope defines what a researcher is allowed to test. A company may operate many sites and services while including only one in its programme. Here, that narrow scope let me concentrate on how the application worked rather than spend time mapping a large collection of targets.
Burp Suite's proxy sits between the browser and the application. It lets a researcher inspect the requests a page sends and the responses it receives. Browsing through that proxy helps connect visible actions, such as submitting a form, to the underlying HTTP traffic.
Wappalyzer identified PHP as part of the application's technology stack. That gave me a more focused starting point for looking for paths. I used FFUF with a wordlist tailored to PHP applications.
Wappalyzer provides clues about technologies used by a website. FFUF can try candidate paths from a list and surface responses worth inspecting. In this case, the PHP clue helped narrow that list. Neither tool identified the access-control failure by itself; the useful finding came from examining what one of the discovered pages actually did.
Several paths came back. One caught my attention: /unsubscribe.php.
Finding a reachable path only establishes that a page responds. Understanding its security impact requires following the action through to the application's subsequent behaviour.
A successful unsubscribe
Opening the path took me to an email marketing unsubscription page. On my first and only attempt, I entered admin@admin.com and submitted the form.
I chose it as a guess: it was an address I recognised as common in leaked credentials. I had not identified it through reconnaissance or fuzzed a list of accounts. That explains the input, but not why the application accepted it or whether other addresses would have produced the same result.
The application displayed a success message: I had been unsubscribed from further marketing emails. Nothing in that response suggested I had just gained access to anything else.
An unsubscribe page may need to work without asking someone to sign in to the main product. That public availability is not, by itself, the problem in this case. The distinction is between permission to change a narrow email preference and permission to enter an internal management application.

The main page opened as System User
I then navigated to the application's main page. Instead of remaining an unauthenticated visitor, I was logged in as a system user with elevated privileges.


The access exposed management functions for vehicles, rentals, prices, bank information, reports, configuration, dealers, and users. The issue reached far beyond the email preferences screen where it began.
The main page displayed System User and the management menus after the form submission.Compare the vulnerable and expected behaviour
The comparison starts with the same visitor and follows the same three actions in both versions. Advance through the steps, then select an internal area to compare access. The expected version illustrates a protected application: changing an email preference leaves the visitor signed out.
Enter an address to stop marketing emails.
Enter an address to stop marketing emails.
Both versions offer a public email preference form.
I also opened the mobile system and found access under the same system user. The unexpected access was visible in both interfaces.

That matters because a desktop interface is only one way into an application. When several interfaces use an identity or permissions system, checking one screen cannot establish that the others enforce the same restrictions.
The HTTP exchange and the missing session evidence
The screenshots preserve the submitted address, the success message, and the subsequent System User interface, but not the raw traffic. I no longer recall the method, parameter name, headers or cookies. This is an illustrative request shape, not a captured request or a tested reproducer. POST and the conventional email field are assumptions; the hostname is fictional.
POST /unsubscribe.php HTTP/1.1
Host: rental.example
Content-Type: application/x-www-form-urlencoded
Content-Length: 23
email=admin%40admin.com
The response headers are the missing part of the mechanism. A Set-Cookie header could have introduced a new session identifier, but an opaque identifier would not itself reveal an administrative role. The server could instead have updated the identity attached to an existing session without changing its cookie. An IP-based association is another hypothesis, with no supporting evidence in the screenshots. PHP being present does not establish that the application used PHPSESSID.
Distinguishing these possibilities would require the initial cookies, the submission and its redirects, any Set-Cookie headers, and the cookies sent when opening the protected application. A separate browser session could help establish whether access followed the session or other shared state; logs or code would be needed to confirm the implementation. The original response cannot be reproduced here because it was not retained.
What the behaviour tells us
Three related concepts help explain the failure:
- Authentication establishes who the visitor is. Entering an email address is an identity claim; it does not establish that the visitor controls the associated account.
- Session management carries the authenticated identity between requests. It allows a browser to stay signed in as it moves from one page to another.
- Authorisation determines what that identity may do, such as view reports or manage users. Being signed in does not automatically justify every permission.
These distinctions follow OWASP's authentication guidance, session management guidance, and authorisation guidance.
In this case, the transition from the public form to a privileged identity showed an authentication boundary failing. The application granted a privileged identity without a password or another authentication step. The range of management functions then explains why that identity change had significant consequences.
The test established a change in access, but did not identify the server-side code responsible for it.
The account shown after the request does not prove that every email address would have worked or that arbitrary accounts could be selected. I tested one address and observed the access that followed it.
Classification and severity
The reported behaviour is an authentication bypass leading to a privileged identity. CWE-306: Missing Authentication for Critical Functionality is a candidate mapping if the unsubscribe flow established that identity without authenticating the visitor. CWE-287: Improper Authentication describes the broader family; MITRE recommends a more specific mapping where possible. The exact session-handling defect remains unresolved without the vulnerable code or traffic.
This also crosses an access-control boundary, but visible management menus do not prove that every underlying administrative request would succeed. The demonstrated result is access identified as System User after one email submission. Arbitrary-account takeover, unrestricted writes and remote code execution were not established.
Triage described the finding as critical, but did not supply a CVSS score. Under CVSS v3.1, a conditional scenario with network access, low complexity, no prior privileges, no victim interaction, unchanged scope and high confidentiality, integrity and availability impact scores 9.8 Critical:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
This is a scoring scenario, not the programme's recorded vector or a verified score for this finding. Reaching an administrative interface alone does not establish C:H/I:H/A:H. In particular, availability impact was not demonstrated. Testing one address also does not establish takeover of every administrative account.
Understand the scope of the impact
The interface exposed both operational and administrative areas. If the corresponding server-side operations accepted that identity, the potential consequences included:
- Rentals and pricing: unauthorised changes could disrupt bookings or alter commercial terms.
- Reports and bank information: access could expose sensitive business data.
- Users and configuration: account, permission, or settings changes could affect who can enter the system and what they can do.
These potential consequences explain the severity of gaining a privileged identity through a public preference form.
What a correction needs to preserve
An unsubscribe operation should be able to update the relevant preference without establishing a product login or assigning a privileged identity. An existing signed-in visitor should likewise retain their own identity and permissions.
Protecting only the navigation would leave the underlying question unresolved. Internal requests need permission checks on the server, including requests reached directly or through another interface. OWASP recommends denying access by default and validating permissions on every request.
For a regression check, a developer could compare identity and access before and after the preference change:
- A signed-out visitor remains signed out and cannot open protected functions.
- A signed-in user retains the same account and receives no additional permissions.
- The same restrictions hold when accessing internal functions directly and through the mobile interface.
Together, these regression checks verify both the preference change and the preservation of account permissions.
Reported, verified, and marked as a duplicate
I reported the issue through the programme. The triage team verified the security issue and initially forwarded it for review.

The report was later marked as a duplicate because another researcher had submitted the same issue earlier. The follow-up explained that my submission had been prioritised as critical, which was why the earlier report had initially been missed. My original account states that the company promptly resolved the issue; the material preserved here does not establish the remediation date or include a retest.

The duplicate decision concerned the order in which researchers reported the issue. Verification concerned whether the behaviour was reproducible and security-relevant. Those are separate decisions: a valid finding may already have been reported by someone else.
Disclosure timeline
The triage screenshots date the finding to February 2022. September 2023 is the publication date of the original thread, rather than the date of the test.
| Event | Date or available record |
|---|---|
| Report submitted through Intigriti | Before verification; exact date unavailable. |
| Triage verified the issue and forwarded it for review | 15 February 2022, 09:31:40. |
| Triage announced closure as a duplicate | 15 February 2022, 10:33:53. |
| Remediation | Reported as promptly resolved; exact date and retest evidence unavailable. |
| Original thread published | 27 September 2023. |
Times are transcribed from the screenshots; their timezone is not shown. The duplicate decision concerns reporting order, not a failed reproduction or proof that remediation had already happened.
Adapted from my original thread on X, published on 27 September 2023. The screenshots are from that thread; the interactive sequence and illustrative HTTP request are reconstructions.