Discovery

Each month, I take the time to collect my gym invoices. This process has changed over the years. Initially, it was done using a mobile app. Later on, it moved to a website. Using said website was simple: log in, navigate to the invoices page, and press download on the relevant invoice from the list.

Assuming that invoices are not generated by the website (due to a number of legal requirements), it fascinated me (on a small degree) that they had a list of my invoices. Certainly there was an external system which the website contacted to get:

  1. an invoice list (given a user)
  2. a specific invoice

Being curious, I looked at the page for a while and decided to take a look at the HTML. Each invoice element from the list had a custom data attribute with the invoice number, which was clearly what the frontend was using to do the download request.

So I wondered: what will happen if I increment this number by 1?

Initial Assessment

The issue was an authorization failure (an Insecure Direct Object Reference / IDOR) in the invoice download flow. The frontend exposed a numeric invoice identifier in a data attribute; by modifying that identifier and issuing the download request while authenticated, the server returned a different invoice that did not belong to my account.

The impact was big: the vulnerability could expose other users’ invoices and the personal data they contain (names, addresses, invoiced services, and ammounts). Fortunately, the exploitability was moderately low — the identifier was predictable (sequential numeric), but an attacker needed an authenticated account to retrieve other invoices. And having an account required either having access to someone else’s, or being a gym member.

Considering the relative gravity of the situation, I started looking into ways to report this in a responsible way. The gym we’re talking about, one of the biggest in Portugal, belongs to one of the biggest conglomerates in the country — with its very own CSIRT, and a Responsible Vulnerability Disclosure program in their web page. It seemed that getting in touch would be easy.

Finding the Right Contact

The conglomerate had a Responsible Vulnerability Disclosure program listed on their website. Said page explicitly asked for 90 before making the breach public. They also explained that they do not make any kind of retribution, or in other words, that the RVD program was not a bounty hunter program. Sad…

It also included instructions to encrypt communications using PGP for confidentiality. However, there was a problem: their public key fingerprint was listed on the page, but the key itself wasn’t available on any public keyserver.

I searched multiple keyservers using both the Key ID and the fingerprint, but found no results. This left me unable to encrypt my initial disclosure as they had instructed.

On July 7th, I sent an email to the RVD address requesting their PGP public key. However, I received no response.

Four days later, I resent the same email, CC’ing the DPO address. Still no answer.

It was only when I emailed the CSIRT on July 25th that I got a response. They explained that previously sent emails had been flagged as spam. Fortunately, they provided the RVD program’s PGP key, which I could now use to encrypt the reproduction steps for the vulnerability.

The Disclosure Process

I wrote a simple explanation of the issue. No examples, no steps to follow. Honestly, I’m not sure that was the best for them, but I was trying to reduce my liability for anything that could go wrong. I didn’t want to give them a step-by-step guide on how to exploit the vulnerability, but I also wanted to provide enough information for them to understand the issue and reproduce it. I then encrypted and signed it. I took the payload and put it in a new e-mail. In that same e-mail, I asked for two things which seemed appropriate at the moment:

  1. “any form of acknowledgment or certificate for responsible disclosures”
  2. “a small goodwill gesture like a discount on my gym subscription”

Unfortunately, none of these two small request have been answered until today.

Timeline

Day Date Event
Day -19 July 6th Discovered the IDOR vulnerability
Day -18 July 7th Contacted RVD program requesting PGP key (no response)
Day -14 July 11th Resent email, CC’d DPO address (no response)
Day 0 July 25th Contacted CSIRT directly; received PGP key and explanation about spam filtering
Day 0 July 25th Submitted encrypted vulnerability report; received confirmation of reception
Day 41 September 4th Requested status update (no response)
Day 89 October 22nd Requested status update again; confirmed as valid vulnerability; website supplier notified
Day 103 November 5th Notified that fix was deployed; verified resolution; followed up on acknowledgment requests
Day 104 November 6th Received confirmation that requests were under evaluation
(Today) - No further response received

Response and Resolution

Once I managed to contact them, their response was professional enough. Thee cadence, however, was less than expectable. Confirmation of the vulnerability only took place on the 89th day, whereas their policy states that they would provide a vulnerability evalutaion and fix estimate within 7 days.

Alas, despite the technical issue having been resolved and verified, the requests for formal acknowledgment or a goodwill gesture remain unaddressed.

Lessons Learned

Technical and Ethical Takeaways

  • Secure Communication Channels: This disclosure served as a practical introduction to using PGP. It highlighted that even when a company requests encrypted communication, the infrastructure (like public keyservers) may not always be maintained, requiring manual intervention. Also, the situation has not changed… which is a shame.
  • Ethical Boundaries and Data Minimization: There is a strong temptation to test the full scale of an IDOR vulnerability. However, responsible disclosure requires strict adherence to data minimization, i.e., extracting only enough information to prove the flaw without compromising the privacy of other users.
  • Managing Communication Expectations: The “black hole” effect, where a report is submitted but no feedback is provided for weeks, can be distressing. Despite understanding that it may be hard to stick to their timeline, they’re the ones who set it. And a message saying “We don’t have news (yet)” is better than no message at all.

Additional Considerations

  • Persistence in Outreach: Standard reporting channels (like RVD aliases) can fail due to aggressive spam filters. Identifying alternative contacts, such as the CSIRT or the Data Protection Officer (DPO), may be important to ensure the report is seen.
  • The Importance of a Timeline: Maintaining a meticulous log of every interaction can help do a retrospective. And making it public is my way of saying “I’m playing by the rules :)”.
  • Vendor Complexity: Vulnerabilities in large organizations may involve third-party suppliers, like in this case. This adds layers of bureaucracy to the patching process, which kind of explains why fixes may take longer than the initial 90-day estimate… but still does not justify it.

Final Thoughts

I feel small. Such a big company, with such a big CSIRT, and I had to go through so much just to report a vulnerability. It makes me wonder how many other vulnerabilities are out there, unreported, because people don’t have the time, resources, or patience to navigate this complex landscape of responsible disclosure.

But I also feel slightly disappointed: they’re not rewarding me for my efforts. I understand that they don’t have to, but a little acknowledgment would go a long way in encouraging responsible disclosure in the future. It’s the kind of thing that could help shape career paths, or at least make someone feel appreciated for their contribution to security. Especially considering that there are no financial incentives involved, a simple certificate of acknowledgment, public mention or service perk/discount would be a nice gesture.

In the end, I live with the knowledge that I did it, they fixed it, and personal details of other users are now safe. And I have a story to tell.