This lab has a stock check feature which fetches data from an internal system.
To solve the lab, change the stock check URL to access the admin interface at http://localhost/admin and delete the user carlos.
The developer has deployed an anti-SSRF defense you will need to bypass.
Approach
Upon gaining access to the lab, I immediately focused on exploring the "stock check" functionality to understand its mechanics. As expected, this feature initiated a POST request to /product/stock, with a crucial parameter named stockApi, intended to fetch data from an external URL.
However, my attempt to redirect it to localhost was met with a "400 Bad Request" error, indicating that the external stock check host must be stock.weliketoshop.net. i do get this error
HTTP/2400 Bad RequestContent-Type: application/json; charset=utf-8X-Frame-Options:SAMEORIGINContent-Length:58"External stock check host must be stock.weliketoshop.net"
Determined to bypass this filter, I experimented with various techniques in the request. Initially, I attempted to embed credentials directly into the URL using the format http://USERNAME@HOSTNAME, leading to a Could not connect to external stock check service response.
It did get through, so now I will attempt to use the # character to indicate a URL fragment. Anything following the # is considered an element on that page, with the hostname preceding it. The URL format is as follows:
http://Hostname#element
so this trick is going to indicate that what comes after it is an element which is in our case the @stock.weliketoshop.net (we need the @ there because it is the reason that it is letting us write something gets accepted before the acquired hostname).
response:
This error suggests that the # isn't being processed, so I attempted to URL-encode it, but without success. However, when I double URL-encoded it, everything worked smoothly
However, I encountered another error, which was logical because at this stage, the system attempted to reach 'ichyaboy' as if it were a hostname, resulting in an error due to its nonexistence. Therefore, I adjusted it to 'localhost', which granted me access.
Now, I need to access the admin panel and delete the user 'Carlos'. To achieve this, all I need to do is send the following request:
It might appear perplexing to some of you why /admin is positioned at the end of the URL rather than directly following localhost. The trick lies in the fact that, as mentioned earlier, anything after the # symbol is interpreted as an element until it encounters a /, which is then analyzed as a path. Consequently, the server accesses that designated path.
Now, all that remains is to delete the user 'Carlos', and the pathway to do so becomes evident from the response when accessing the admin panel, which contains <a href="/admin/delete?username=carlos">
So, sending a GET request to /admin/delete?username=carlos will initiate the deletion process. Therefore, my request appears as follows:
This request successfully deleted the "Carlos" user, thereby resolving the lab.