Private photos reachable by reference
Consumer internet
A dating platform let members share photos privately with matches. We were asked whether a private photo could be reached by someone it was never shared with, and whether profiles could be collected in bulk.
Web & API penetration test, Consumer dating platform, severity CRITICAL, reported 2024
At a glance
- Challenge. Private photos could be fetched by reference alone, without checking the match, and profiles could be requested in sequence without limit.
- Approach. We shared a photo between two accounts we controlled, fetched it from an unmatched third account, and called the profile endpoint in sequence.
- Result. Media and profile endpoints now enforce the viewer relationship, references are unguessable, profiles are rate limited, and both surfaces were retested.
- Impact. Any member could have viewed photos others had shared privately with a match, and harvested member profiles in bulk by calling the profile endpoint in sequence.
- Classification. CWE-639 Authorization Bypass Through User-Controlled Key, OWASP API Security Top 10 (2023): API1 Broken Object Level Authorization. Component: Private media retrieval and profile endpoints.
The challenge
A private photo is private because of who is allowed to fetch it, not because of where it is stored. When the address of the file is enough to retrieve it, and the address is a reference that can be guessed or walked, privacy has been delegated to obscurity, and obscurity is not a permission.
Bulk collection is the same weakness seen from a distance. An endpoint that returns one profile to an authorised viewer becomes a way to harvest every profile when it can be called in sequence without limit and without checking the relationship between viewer and viewed. Each call is legitimate. The pattern is the harm.
On a platform whose members have shared exactly what they expected only a match to see, a reference that ignores the match is the most sensitive kind of flaw there is.
Our approach
We shared a photo between two accounts we controlled and then tried to fetch it from a third that was not a match, and we exercised the profile endpoint in sequence to see whether relationship and rate were enforced.
Around those findings we checked the surface that shared the assumption:
- Whether private media enforced the viewer relationship on retrieval
- Whether media references were unguessable rather than sequential
- Whether profile endpoints checked relationship and applied rate limits
- Whether the same gap reached other member-only content
Delivered with the accounts and references used, so each finding could be reproduced against test profiles without taking our word for it.
From finding to fix
- Shared a private photo between accounts
- Fetched it from an unmatched account
- Collected profiles in sequence
- Enforced relationship and limits, retested
The outcome
Private media now enforces the viewer relationship on retrieval and references were made unguessable, so a photo reaches only the match it was shared with. Profile endpoints check relationship and apply rate limits, so bulk collection is no longer available.
We retested the media and profile surfaces after the fix. Reported as CRITICAL in 2024. Retest included in the engagement.
Check your own system
- Share a private photo between two test accounts, request it from a third unmatched account, and confirm the server refuses it.
- Check that media references are random rather than sequential, and that knowing a reference grants nothing on its own.
- Call the profile endpoint in sequence from one account and confirm it checks the viewer relationship and applies a rate limit.
- List every other member-only resource and repeat the unmatched-account request against each one.
Read more case studies, see Web Application Penetration Testing, or write to hello@yaamlabs.com.