Cheerio
Challenge
A page that previews a link. You POST a url and an element, the server fetches the URL with the request library and returns the contents of that element. The error you get from an empty request gives away exactly how it works:
| |
So the body is url=<address>&element=<selector>, and whatever the server fetches gets parsed for the element you name. Server-side request forgery.
Approach
The server makes the request, not the browser, so the url can point anywhere the server can reach. Pointing it at internal hosts and scanning ports turned up service responses that the front end was never meant to show.
There is an /admin page, but it is gated to internal callers. Credentials for it came from a sibling challenge: a base64 blob in an image that decoded to ROT13, which in turn gave a set of logins.
Joker:LeBlancForever123
Akechi:PancakesAreLife!!
Morgana:AnnIsBae<3
You can carry HTTP basic auth in the URL itself with the user:pass@host form, so the SSRF can authenticate on the way in:
| |
Solution
The reliable target was the cloud metadata address. Setting url to http://169.254.169.254 and asking for the body element pulls the metadata response straight back through the preview:

POST /title HTTP/1.1
Host: 10.1.10.50:3000
Content-Type: application/x-www-form-urlencoded
url=http%3A%2F%2F169.254.169.254&element=body
HTTP/1.1 200 OK
X-Powered-By: Express
This is not AWS. d4rks1d3r
The server happily fetched the internal-only metadata IP and reflected the response back.