July 31, 2026
Chaining an IDOR Bug into an Account Takeover
While testing, I came across this API endpoint: POST /auth/v1/sync. This endpoint is triggered during the registration and login flow and…

By Mahmoud Elsaidy
3 min read
While testing, I came across this API endpoint: POST /auth/v1/sync. This endpoint is triggered during the registration and login flow and is responsible for linking a GUID to a user account, and it has multiple functionalities depending on the "event" in the body.
I noticed that the response depended entirely on the auth_guid value supplied in the request body, so I wanted to see whether the endpoint actually verified who was making the request.
To test this, I removed both the Cookie and Csrf-Token headers and resent the request.
The result was surprising. The API still returned all of the user's information — including their email address, first and last name, phone number, internal IDs, and authentication tokens — for whatever auth_guid I supplied, without verifying that I was actually authorized to access that data.
At this point, I knew I had found a vulnerability, but by itself the impact was fairly limited. So I started thinking about how I could chain it with another issue to achieve something more significant. Two ideas came to mind:
- Find a way to obtain other users'
auth_guidvalues. - Determine where the token returned by
/auth/v1/syncwas used.
Unfortunately, I couldn't find a way to enumerate other users' auth_guid values, so I focused on the second idea. I began tracing where the token from the /auth/v1/sync response was used, which eventually led me to the POST /sessions endpoint.
This request is sent immediately after a successful login. Looking at the response, it appeared to simply redirect the user to the dashboard. That made me wonder: what if the server trusted the values in this request instead of the authenticated session?
To find out, I started testing.
Just like before, I removed the Cookie and Csrf-Token headers. Once again, the request still succeeded, suggesting that neither value was required for authentication.
Next, I modified the request body one parameter at a time to identify which fields actually mattered. I changed the email, then the authenticity_token, and finally the sac_id. None of these changes affected the result.
The only values that turned out to be important were the token and user_id, both of which were returned by the /auth/v1/sync endpoint. To confirm this, I replaced each value with a random one. This time, the server responded with InvalidLogin, confirming that it was validating these two fields while ignoring the others.
With that information, I replaced the token and user_id with values belonging to another account that I owned. The response returned /homehub/dashboard, which strongly suggested the authentication had succeeded.
To verify the behavior, I enabled Burp Suite's Intercept and logged in normally using the email address and password of one of my test accounts. When the POST /sessions request was intercepted, I replaced the token and user_id with the values from my second test account, forwarded the request, and disabled interception.
Voila. I was now logged into my second account without ever entering its password. The application authenticated me solely based on the supplied token and user_id, making it possible to switch accounts by modifying the request in transit.
So what started as a small information disclosure — an IDOR on /auth/v1/sync that leaked another user's profile data and tokens — turned into a full account takeover once I traced where those tokens were actually trusted. Neither endpoint checked the session at all; they just trusted whatever auth_guid, token, and user_id were handed to them. Chain the two together and anyone with a valid auth_guid could end up sitting in someone else's dashboard.
Here's the funny-not-so-funny part: the program was open scope, but the out-of-scope section listed specific subdomains, things like sub1.domain.com and sub2.domain.com. So I figured the main domain and every other subdomain were safe to test. After 10 days in triage, they responded with: