Server Side Request Forgery

A web API is vulnerable to Server-Side Request Forgery (SSRF) (also known as Cross-Site Port Attack (XPSA)) if it uses user-controlled input to fetch remote or local resources without validation. SSRF flaws occur when an API fetches a remote resource without validating the user-supplied URL. This allows an attacker to coerce the application to send a crafted request to an unexpected destination (especially local ones), bypassing firewalls or VPNs.

Server-Side Request Forgery (SSRF)

The endpoint we will be practicing against is vulnerable to CWE-918: Server-Side Request Forgery (SSRF).

Scenario

The admin of Inlanefreight E-Commerce Marketplace has provided us with the credentials htbpentester10@pentestercompany.com:HTBPentester10, wanting us to assess what API vulnerabilities the user can exploit with their assigned roles.

After invoking /api/v1/authentication/suppliers/sign-in to sign in as a supplier and obtain a JWT, the /api/v1/roles/current-user endpoint shows that we have the roles SupplierCompanies_Update and SupplierCompanies_UploadCertificateOfIncorporation:

image-65.png

Checking the Supplier-Companies group, we notice that there are three endpoints related to these roles, /api/v1/supplier-companies, /api/v1/supplier-companies/{ID}/certificates-of-incorporation, and /api/v1/supplier-companies/certificates-of-incorporation:

image-66.png

/api/v1/supplier-companies/current-user shows that the currently authenticated user belongs to the supplier-company with the ID b75a7c76-e149-4ca7-9c55-d9fc4ffa87be:

image-67.png

Expanding the /api/v1/supplier-companies/certificates-of-incorporation POST endpoint, we notice that it requires the SupplierCompanies_UploadCertificateOfIncorporation role and allows the staff of a supplier-company to upload its certificate of incorporation as a PDF file. We will provide any PDF file for the first field and the ID of our supplier-company:

image-68.png

After invoking the endpoint, we will notice that the response contains three fields, with the most interesting being the value of fileURI:

image-69.png

The web API stores the path of files using the file URI Scheme, which is used to represent local file paths and allows access to files on a local filesystem. If we use the /api/v1/supplier-companies/current-user endpoint again, we will notice that the value of certificateOfIncorporationPDFFileURI now has the file URI of the uploaded file:

image-70.png

Expanding the /api/v1/supplier-companies PATCH endpoint, we notice that it requires the SupplierCompanies_Update role, that the update must be performed by staff belonging to the Supplier-Company, and that it allows modifying the value of the CertificateOfIncorporationPDFFileURI field:

image-71.png

Therefore, this endpoint is vulnerable to Improperly Controlled Modification of Dynamically-Determined Object Attributes, as the value of this field should only be set by the /api/v1/supplier-companies/certificates-of-incorporation POST endpoint. Let us perform an SSRF attack and update the CertificateOfIncorporationPDFFileURI field to point to the /etc/passwd file:

image-72.png

Because the web API's backend does not validate the path that the CertificateOfIncorporationPDFFileURI field points to, it will fetch and return the contents of local files, including sensitive ones such as /etc/passwd.

Let us invoke the /api/v1/supplier-companies/{ID}/certificates-of-incorporation GET endpoint to retrieve the contents of the file that CertificateOfIncorporationPDFFileURI points to, which is /etc/passwd, as base64:

image-73.png

When using CyberChef to decode the value of the base64Data field, we obtain the contents of the /etc/passwd file from the backend server:

image-74.png

We can further compromise the system by viewing the contents of other critical files, such as /etc/shadow.

Prevention

To mitigate the SSRF vulnerability, the /api/v1/supplier-companies/certificates-of-incorporation POST and /api/v1/supplier-companies PATCH endpoints must strictly prohibit file URIs that point to local resources on the server other than the intended ones. Implementing validation checks to ensure that file URIs only point to permissible local resources is crucial, which in this case is within the wwwroot/SupplierCompaniesCertificatesOfIncorporations/ folder.

Furthermore, the /api/v1/supplier-companies/{ID}/certificates-of-incorporation GET endpoint must be configured to serve content exclusively from the designated folder wwwroot/SupplierCompaniesCertificatesOfIncorporations. This ensures that only certificates of incorporation are accessible and that local resources or files outside this directory are never exposed. Additionally, this acts as a safeguard, if in case the validations performed by the /api/v1/supplier-companies/certificates-of-incorporation POST and /api/v1/supplier-companies PATCH endpoints fail.


Exercise

TARGET: 154.57.164.65:40991

Authenticate to target with username "htbpentester11@pentestercompany.com" and password "HTBPentester11"

Challenge 1

Exploit another Server Side Request Forgery vulnerability and submit the contents of the file '/etc/flag.conf'.

HINT: Focus on the POST /api/v1/products/current-user, the PATCH /api/v1/products endpoint, and the POST /api/v1/products/photo endpoint.

Remember the API testing UI is under the /swagger endpoint. Lets authenticate as a supplier this time with the given credentials:
image-75.png
This is the JWT we get:

eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6Imh0YnBlbnRlc3RlcjExQHBlbnRlc3RlcmNvbXBhbnkuY29tIiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjpbIlN1cHBsaWVyQ29tcGFuaWVzX1VwZGF0ZSIsIlN1cHBsaWVyQ29tcGFuaWVzX1VwbG9hZENlcnRpZmljYXRlT2ZJbmNvcnBvcmF0aW9uIiwiUHJvZHVjdHNfQ3JlYXRlQnlDdXJyZW50VXNlciIsIlByb2R1Y3RzX1VwZGF0ZSIsIlByb2R1Y3RzX1VwbG9hZFBob3RvIl0sImV4cCI6MTc5MjM0MTk0OSwiaXNzIjoiaHR0cDovL2FwaS5pbmxhbmVmcmVpZ2h0Lmh0YiIsImF1ZCI6Imh0dHA6Ly9hcGkuaW5sYW5lZnJlaWdodC5odGIifQ.nwILCcxJl2-e98gZTIqiAgHfRkjaQBalozR1uZh_O2siqGW0r9ki1l5v2kBLm-SibmA0ClmRbAJc-mt4Qng_9w

Since we are told we should check out the product-related API endpoints, I will start by using the /api/v1/products/current-user, which lets us create a new product. I will create a a new product called: "myprod" and will assign file:///etc/flag.conf to the FileURI parameter:
image-76.png
This returns a valid Product ID:
image-77.png

Now note that if we get this product using /api/v1/products/{ID} we will find that the PNGPhotoFileURI was not actually modified to what we set before, this is because we probably require a different role in order to modify this value.
image-78.png

I will now try the endpoint: /api/v1/products/photo, which takes a PNG file and a ProductID. I will put a random png file and set our product ID:
image-79.png
image-80.png
The response looks like this:
image-81.png

The next step is to employ the PATCH /api/v1/products endpoint to update our product and set the FileURI to what we want. First lets get our SupplierID with /api/v1/suppliers/current-user to list our user info:
image-82.png

Now we have all the info required for the /api/v1/products update endpoint:
image-83.png
image-84.png

Lets now try to see the contents of the file we indicated in the FileURI parameter. For this I will use the endpoint: api/v1/products/{ID}/photo (gets a product photo as base64):
image-85.png
image-86.png
So our base64 encoded flag is:

SFRCezNjOTQyMzJjNGYwYjBhNTQ0YWU0MDI0ODMzZWVmMGIzfQo=

If we use any base64 decoder tool we will reach the real flag:
image-87.png

flag: HTB{3c94232c4f0b0a544ae4024833eef0b3}