Rating: 5.0

# Web: SSRF 301


It's a harder version of [SSRF 101](./web_ssrf_101.md)

## Differences in source code

>## public.js
app.get('/ssrf', (req, res) => {
const path = req.query.path
if (typeof path !== 'string' || path.length === 0) {
res.send('path must be a non-empty string')
else {
const normalizedPath = path.normalize('NFKC')
const firstPathChar = normalizedPath.charAt(0)
if ('0' <= firstPathChar && firstPathChar <= '9') {
res.send('first chararacter of path must not normalize to a digit')
else {
const url = `http://localhost:${private1Port}${normalizedPath}`
const parsedUrl = new URL(url)
The only difference is that there is a check for the first character of the path parameter which cannot be a number. We can easily bypass this poor validation attempt.

## HTTP/HTTPS basic authentication URL with @

HTTP/HTTPS protocol accept authentication using @ symbol with username and password `https://username:password@URL`

We can use it to send request with server hostname and port as username and password. After @ we can enter new hostname, port and path we want to visit.
Server will see the request as `https://localhost:10011@locahost:10011/flag`


## CRLF injection - %0D%0A

The HTTP protocol uses the CRLF character sequence to signify where one header ends and another begins. In this case we can use it to bypass check for the first character.


## FLAG: wsc{url_synt4x_f0r_th3_w1n_hq32pl}

Original writeup (https://github.com/Dom0nS/ctf/blob/main/CTF_writeups/Wolvsec-ctf-2022/web_ssrf_301.md).