How incorrect API design can lead to user removal
Continuing the story about the vulnerabilities that were discovered by UCSB pentesters and formed the basis for the cases at the Pentest Award, we publish an analysis of the following real example.
Let's tell you how a bunch of vulnerabilities were discovered in one company's web application, which made it possible to remove any registered user from the system.
Primary analysis
The application we studied was a classic system for remote user access to application resources. First, we tested the functionality that was available to the user without authentication. The system allowed registration using the user's phone number. This became the starting point in analyzing the application.
When trying to register by phone number, we discovered that after entering the name and number, a request is sent to the endpoint /api/v1/users?query=eq (phone_number,string:phoneNumber).
This endpoint checked for registered users with the same phone number.
When requesting a random phone number, the application, depending on the presence of the user in the system, revealed part of the user attributes and a test token in Basic format.
There were no other interesting findings, so we moved on to the analysis with user rights.
Assembling the vector
During API reconnaissance, we noticed that the application uses multiple handles to access user account information. This endpoint caught our attention:
In this case, the application was accessed by some identifier, which was suspiciously similar to those we saw when searching through phone numbers.
Driven by this idea, we tried to combine the two pieces of the puzzle and achieve the ability to receive custom attributes. However, we were met with failure:
The application was checking the token, and this made it difficult to sort through the identifiers. We decided not to let go of the idea and see what versions of the API might be available, except for version 3. As it turned out, the application also has version v2, but it was no longer available using the standard token.
However, when requesting with the test token that was detected in the first step, access was still available.
We decided to go through the available HTTP methods for this handle.
The result was pleasantly surprising: this endpoint supported the DELETE method. The only thing required was to indicate instanceId
It could be seen among those obtained when searching through phone numbers:
In general, all the pieces of the picture were already in hand – we just needed to see if we could actually delete the account. We had a spare account to test access restrictions – that’s what we decided to use for the test.
The request went to the server without problems and returned us a completely correct response.
To check if a user is in the system, we tried to re-access the API to obtain data about the user by phone number:
The user was successfully deleted:
As a result, we have the ability to remove any user from the system. The only thing needed for this is the user’s phone number.
Chain implementation
The following vulnerabilities were used to demonstrate the attack:
test token disclosure;
the ability to obtain a user ID by phone number;
access to an alternative version of the API using a test token;
available DELETE method at the endpoint /api/v2/users.
Attack chain diagram:
This case is indicative in that vulnerabilities of a seemingly low level of criticality can lead to the realization of a tangible business risk for the company if they are connected in a chain.
Lessons Learned
To protect your application from such attacks, you should follow the following practices:
Check applications for traces of development: test tokens, API endpoints, etc.
Disable insecure HTTP methods such as DELETE or allow only privileged accounts to use them.
Avoid allowing users to obtain account IDs based on any attribute, such as phone number or email address.
Restrict access based on JWT tokens or cookies, rather than based on identifiers.
Author: Nikita Raspopov, security analysis specialist at UCSB