This blog will describe how account takeovers (ATO) can be executed against APIs using GET methods, as opposed to POST. It’s an excellent example of how bad actors will analyze an application to uncover potential attack vectors.
A Brief Primer on GET and POST
The GET method allows you to fetch information from a website or an API. GET supports passing query parameters, path parameters, or HTTP request headers to display dynamic content from a site. POST is often used to send information from the client to server using a form, JSON, or other formats.
- users manually filling out a form to perform logins or to create new accounts.
- a script can also automatically collect information from the browser or mobile device and sends it back to the server.
The Role of Developers and Development Frameworks
Developers will publish their web application to server-side frameworks, which then process the method and parameter requests and respond with appropriate content.
Basic server-side frameworks need the developers to parse the parameters based on the method type. But, advanced server-side frameworks like Spring, PHP, and others automatically parse these parameters, be it query parameters in the GET request or the form parameters in the POST request and normalize them in a simple key-value collection.
Unless explicitly enforced, parameters like username and password combination can be passed as GET query parameters or POST form parameters, and they are treated the same way by the backend. Developers often implement logic that uses the normalized parameters and does not care about how these parameters were submitted.
Bad Actors Moving from POST to GET
This architecture works fine for basic bots running common browser automation tools like PhantomJS or Selenium. Those mimic the flow of a regular user, first retrieving the login page via a GET request and then sending in login credentials via a subsequent POST request. The second POST request will deliver all the telemetry data the tool needs to decide if it’s a “bot or not.” However, this design leaves a crack in the door, particularly over the API channel, and the bad actors began to drive a truck through that crack.
GET-based ATOs via APIs
Leveraging this crack in the door is the technique we call GET-based ATO attacks. Attacks use it to escape detection and mitigation efforts by merely avoiding the need to first GET a page and then POST to a server.
Many mobile apps are driven primarily through APIs, and those mobile apps often have an entire set of functions and areas behind an authentication gate. A user must be logged in to view profiles on a dating site. They must be logged in to view items in a shopping cart and so on.
The need for an application to understand if a user is logged in over a stateless API is a problem that’s been around forever and can be solved with secure coding practices. In this case, the problem lies in enumerating and understanding all possible APIs in your ecosystem and ensuring that no APIs accessed through GET requests could return different responses based on something a user themselves is inputting – such as credentials as parameters.
After their initial bot campaigns via POST requests on traditional login endpoints are shut down, bad actors will sign up for a valid account manually. Then, they will enumerate and reverse engineer the API calls that access seemingly benign data, such as a profile dashboard or shopping cart.
If they see that authentication is taking place through a susceptible method, they will begin to modify a tool to carry out an ATO. Some of the areas vulnerable to authentication schemes are:
- HTTP Basic Auth through the Authorization header
- Bearer Tokens & OAuth
- HTTP Digest Auth
- Custom headers and/or cookies that are app-specific
From POST to GET-based ATOs – a Customer Timeline
In one customer example, we observed more than 60+ million ATO attempts through POST requests every week. Upon enabling mitigation and stopping the ATOs, the bad actors shifted to GET-based ATOs against APIs within three weeks.
The GET-based ATO campaigns scaled quickly to 2.2 million requests per week, and now they continue to enumerate and probe dozens of APIs using the same logic. We are observing more than 50+ million GET-based ATO attempts per week. Additionally, ATOs using POST have dropped to a mere 500,000 attempts per week.
To provide additional context, GET-based ATOs saw a 2000% increase, while POST-based ATOs showed a 99.99% reduction. Those GET-based ATO campaigns attempted to hit more than 35 different APIs simultaneously as the campaign scaled. To an outsider, it may seem like this rapid, massive scaling up of attack volume via GET requests would be easily detectable. Still, there’s another reason an attacker would prefer to hide in plain sight among GET requests.