Many security outsiders think data leaks result from diligent efforts by seasoned hackers. In reality, minor oversights and mistakes in code frequently cause data breaches. And with engineers pressured to release features quickly, it’s no wonder these mistakes are common.
Unsecured Application Programming Interfaces (APIs) are particularly dangerous because they’re synonymous with Broken Access Control, the highest of the OWASP top 10 web application security risks.
This blog will explain how Peloton’s unsecured APIs led to a data breach. We’ll use example code snippets to demonstrate what unsecured APIs look like and how to avoid them in your software.
Exfiltrating Sensitive Data from Unsecured APIs
If an API is internet-accessible and doesn’t include security measures, it’s ripe for exploitation. To recreate what happened with Peloton, we’ll need two APIs in our simplified sample application.
Generating a List of Users
The first API will be a POST route. It receives a workout ID and returns a list of all users registered for that workout.
For this example, I’m using dummy data with the IDs set to ascending integers to keep things simple. Here’s how the POST request looks using Insomnia.
You’ll notice that I didn’t pass my credentials, yet the server completed my request. That’s the lack of API authentication in action.
We see each user’s ID displayed in the returned values. We’ll note those IDs for the next step.
- IDs: [1, 3, 4]
You may wonder, “Why do some data fields show NULL?” The answer is that I’m using Object Mapping, which makes the Spring backend aware of all data fields. However, my SQL query isn’t retrieving those fields, so their values are a mystery.
We’ll need to exploit the second API to access the missing private information.
Extracting Private Information About Users
The second API is a GET route that allows us to view users’ personal information.
We’re starting with the authorization logic commented out, allowing free access. In the case of an attack, a hacker can write a short script to extract everyone’s personal data programmatically.
Next, we’ll input the user IDs from earlier into our script:
This script’s output (normally saved to a file) contains everyone’s data.
With this approach, an attacker can quickly gather the personal information of every user in the database and sell it on hacking forums.
Adding Security to APIs
When securing APIs, the first step is to add authentication.
Using Authentication to Validate API Access
Authentication means the software knows who requests data. For this application, only registered users should have access to these APIs. In this example, I’m relying on Spring Security’s built-in authentication framework.
Let’s add the Spring Security dependencies to our “pom.xml” file, then call the APIs.
The server responds to our request with a “401: Unauthorized” error. That’s a good start!
For simplicity, I’ll go into the “application.properties” file and set the master username and password to match one of the users in my database. In a real-world application, you’ll want unique credentials and tokens for each user. But for our example, the root user is sufficient.
The API accepts my request when I provide my username and password.
We’re getting closer – so let’s add authorization.
Use Authorization to Restrict Data Access
Authorization is synonymous with Access Control, arguably the most crucial security aspect. It’s essential to implement your authorization server-side so users cannot bypass your access controls.
We’ll handle authorization in the API route for this example. Keep in mind this code is nowhere near production-grade, so be sure to create a more robust authorization scheme in your app (you can create one in Spring Security or another protocol like OAuth 2.0).
The API is now validating the user privileges. This time, when I look up the users in the original workout, my data permissions are:
- Public: Available
- Private: Blocked
- My Own: Available
Now we’ve seen authorization in action.
Both authentication and authorization are crucial when building software. If you want to learn more, watch my 2-minute video on the Peloton hack to see how you can detect and prioritize unauthenticated APIs with Bionic: