Back to Articles

API Attacks — Skills Assessment Spring 2025

API Attacks — Skills Assessment Spring 2025

Scenario

“After reporting all vulnerabilities in versions v0 and v1 of Inlanefreight E-Commerce Marketplace, the admin attempted to patch all of them in v2”

This will be a simple and brief guide to completing the Skill Assessment for this specific HTB module.

First, we use the provided (customer) credentials: “htbpentester@hackthebox.com” and password “HTBPentester

/swagger page, with sign-in endpoint

After spinning up the victim machine, I submit a POST request containing these credentials. The server responds with a JWT token, which I then use to authorize subsequent requests.

Authorized under htbpentester@hackthebox.com account

I go ahead and check my privileges with the role end-point, and it shows that I currently have two roles, "Suppliers_Get" & "Suppliers_GetAll"

This indicates we’re dealing with a Broken Function Level Authorization vulnerability. Essentially, a customer is able to access an endpoint that displays all supplier data, which they should not have permission to view. This points to inadequate authorization checks at the function level.

/api/v2/suppliers endpoint accessed

When I send the GET request, I can see details for various suppliers — such as their name, email, and company ID. The most interesting field I found was the "securityQuestion", which could potentially reveal sensitive information.

I created a Bash script that parses the JSON file and looks for any major differences or suppliers who have a security question set up:

#!/bin/bash
[[ $# -ne 1 ]] && { echo "Usage: $0 file.json"; exit 1; }
FILE="$1"
command -v jq >/dev/null || { echo "Error: jq required."; exit 1; }
defSQ="SupplierDidNotProvideYet"; defCV="SupplierDidNotUploadYet"
printf "%-25s %-35s %-30s %-30s\n" "Name" "Email" "Security Question" "CV File URI"
printf "%-25s %-35s %-30s %-30s\n" "------------------------" "-----------------------------------" "------------------------------" "------------------------------"
jq -c '.suppliers[]' "$FILE" | while read -r s; do
name=$(echo "$s" | jq -r '.name'); email=$(echo "$s" | jq -r '.email');
sq=$(echo "$s" | jq -r '.securityQuestion'); cv=$(echo "$s" | jq -r '.professionalCVPDFFileURI');
[[ "$sq" == "$defSQ" && "$cv" == "$defCV" ]] && continue;
[[ "$sq" == "$defSQ" ]] && sq=""; [[ "$cv" == "$defCV" ]] && cv="";
printf "%-25s %-35s %-30s %-30s\n" "$name" "$email" "$sq" "$cv"
done

When I run the script, it shows five accounts with a security question configured, and they all share the same question: “What is your favorite color?” This suggests a potential attack vector if the security question is used for password resets or account recovery.

Output from the bash script

I took note of those emails as a separate text file, because we’re going to be using them for brute forcing in later stages.

Because these email addresses might be used to pivot for password resets, I checked for any endpoints related to security question answers. Indeed, I discovered the following endpoint:

/api/v2/authentication/suppliers/passwords/resets/security-question-answers Endpoint

I would typically use ffuf or Hydra for authentication-based brute forcing. However, because this scenario involves guessing the security answer (which appears to be a single word, like a color), I decided to use Burp Suite instead. I intercepted a POST request for a sample password reset based on security questions and then forwarded it to Intruder, where I set up payload positions for the SupplierEmail and SecurityQuestionAnswer fields. The password field can be any valid string, assuming it meets complexity requirements (not in this case).

Intruder Tab for Burp Suite

Since the security question asks for a color, I wanted to generate a large list of possible color names. I asked ChatGPT to provide me with a comprehensive list — because I couldn’t find a suitable one on GitHub or Pastebin and used that list in Burp Intruder to brute force the answer.

Payload settings

However, if you’re using Burp Suite, be sure to set your Attack type to Cluster Bomb, which tests each email against the entire color list

As mentioned, Intruder is straightforward to configure but can take a few minutes to complete — especially with the Community Edition’s rate limits.

Results

After running Intruder for a while, one request stood out with a smaller response length. That response contained "successStatus": true, indicating that we successfully matched the correct email-security answer pair and reset the password.

Once the password was reset, I logged into the compromised supplier account and received a JWT token, granting me authenticated access to the application.

Supplier’s JWT token

Next, I examine the supplier’s account roles and capabilities. It appears the account has no assigned roles, which limits potential attack vectors.

/api/v2/roles/current-user endpoint on Supplier’s account

I then check the current-user endpoint for this supplier and notice a parameter named "professionalCVPDFFileURI". This parameter allows the user to specify a URI for their CV, which could potentially open the door to a Server-Side Request Forgery (SSRF) attack.

/api/v2/suppliers/current-user Endpoint

Finally, I upload a PDF test file via the /api/v2/suppliers/current-user/cv endpoint. The server responds with a 200 status code, confirming the upload was successful.

Response with Status Code 200, stating the upload was a success.

I then double-check the /api/v2/suppliers/current-user endpoint, which confirms that my file was successfully uploaded to the supplier’s account and now resides in the web server’s directory.

/api/v2/suppliers/current-user Endpoint

Now as we can see, there is a “api/v2/suppliers/current-user” PATCH endpoint, where it gives ability for the currently authenticated supplier to update their information accordingly, including the “ProfessionalCVPDFFileURI” input, which opens the door for me to reveal the contents of the “/flag.txt” file, as this was the original assessment’s objective.

I go ahead and change the “ProfessionalCVPDFFileURI” input from the default to “file:///flag.txt” and submit the PATCH request, which is successful

/api/v2/suppliers/current-user PATCH endpoint
Status Code 200 after PATCH request

Now I go ahead and access the “/api/v2/suppliers/current-user/cv” endpoint, which is expected to output any contents in Base64 format. I submit the GET request to get it’s details.

I take the Base64 data and decode it using an online tool base64decode.org Sure enough, it reveals the flag.txt contents. Submitting this flag completes the API Attacks Skill Assessment successfully.

/flag.txt decoded contents