Fondamenti di Test di Sicurezza Etico con Python: Una Guida Pratica per Principianti
Capitolo 1 di 11 · aggiornato 08 lug 2026
Python per la sicurezza: Primi passi nella programmazione
Installazione di Python 3.12 e Verifica della Configurazione
Ricordo ancora la prima volta che ho provato a seguire un tutorial sulla sicurezza che dava per scontato che Python fosse già "semplicemente lì." Tre ore di risoluzione problemi con le variabili di percorso più tardi, ho abbandonato. Non ti faremo questo. Lab Wintermute non esiste ancora nella tua macchina—lo costruiamo pagina dopo pagina—ma ogni strumento che useremo in seguito, dagli script di scansione delle porte ai parser di log, gira su Python. Quindi iniziamo dalle fondamenta.
Scarica Python 3.12 da python.org. La navigazione esatta cambia, quindi cerca la versione stabile contrassegnata 3.12.x. Durante l'installazione, spunta la casella che aggiunge Python al PATH di sistema; senza questo, il tuo terminal sosterrà che python non esiste anche quando è proprio lì sul tuo disco. Sulle distribuzioni Linux, il tuo package manager probabilmente offre la 3.12 o vicino—controlla con i repository attuali del tuo sistema. Su macOS, l'installer da python.org o Homebrew funzionano entrambi; ho usato entrambi e preferisco l'installer per i principianti perché include IDLE, che usiamo qui sotto.
Apri un terminal—Command Prompt su Windows, Terminal su macOS, la tua shell preferita su Linux—e verifica:
python --version
oppure, su molti sistemi Linux dove python punta ancora a una release più vecchia:
python3 --version
Output illustrativo — verifica sul tuo target:
Python 3.12.xSe vedi 3.11 o 3.13, la maggior parte di questa guida funziona comunque, ma la 3.12 è quella su cui ho testato. Se vedi "command not found," il tuo PATH necessita attenzione o l'installazione non è stata completata.
IDLE, l'editor integrato di Python, viene fornito con l'installazione standard. Trovalo nel tuo menu applicazioni. Uso IDLE quando insegno perché mostra feedback immediato: digita 2 + 2, premi Invio, vedi 4. Nessuna compilazione, nessun mistero. Ma per il lavoro reale—tutto ciò che facciamo dalla pagina cinque in poi—scriviamo script in file di testo e li eseguiamo dal terminal. IDLE è il tuo supporto per l'equilibrio, non la tua bicicletta.
L'Interprete: La Tua Prima Conversazione con Python
Apri IDLE. Vedi una finestra con i prompt >>>. Questo è il REPL (Read-Eval-Print Loop): legge ciò che digiti, lo valuta, stampa il risultato, cicla all'infinito. Digita esattamente questo:
>>> print("Lab Wintermute initialized")
La stringa "Lab Wintermute initialized" appare sotto. print() è una funzione—un blocco di codice nominato che esegue un'azione. Le parentesi contengono il suo argomento, il valore su cui opera. Le stringhe (sequenze di caratteri di testo) richiedono virgolette in modo che Python sappia dove iniziano e finiscono.
Ora digita qualcosa che fallisce di proposito:
>>> print(Lab Wintermute initialized)
Ottieni un NameError: name 'Lab' is not defined. Python ha tentato di trattare Lab come nome di variabile, non come testo, e non ha trovato nulla assegnato ad esso. Questa è la tua prima traceback—il modo di Python di mostrare dove e perché si è rotto. Le traceback si leggono dal basso verso l'alto: l'ultima riga ti dice il tipo di errore e la lamentela leggibile dall'uomo; le righe sopra mostrano il file e il numero di riga dove l'esecuzione è fallita. Leggere le traceback non è lucidatura opzionale; è il modo in cui fai debug quando il tuo port scanner colpisce una porta chiusa e va in crash invece di gestirla con eleganza. Praticheremo questo deliberatamente.
Variabili: Contenitori Nominati per i Dati
Una variabile memorizza un valore sotto un nome che scegli tu. Nel lavoro di sicurezza, dai un nome al tuo host target, alla tua lista di porte, ai tuoi valori di timeout. Digita questi in IDLE:
>>> target_host = "192.0.2.20"
>>> target_port = 22
>>> scan_timeout = 3.5
>>> is_authorized = True
target_host contiene una stringa (str), dati di testo. target_port contiene un intero (int), un numero intero. scan_timeout contiene un float, un numero con precisione decimale. is_authorized contiene un booleano (bool), True o False. Il segno = assegna; qui non significa uguaglianza matematica.
Verifica ciò che hai memorizzato:
>>> type(target_host)
<class 'str'>
>>> type(target_port)
<class 'int'>
Python è a tipizzazione dinamica—non dichiari i tipi in anticipo, ma il tipo conta. Non puoi sommare una stringa a un intero direttamente; target_host + target_port solleva un TypeError. Questo frustra i neofiti ma ti protegge da bug sottili, come concatenare un numero di porta in un URL in modo errato.
Le liste memorizzano più valori in ordine. Le usiamo per intervalli di porte target:
>>> common_ports = [22, 80, 443, 3306, 8080]
>>> common_ports[0]
22
L'indicizzazione inizia da 0, non 1. common_ports[0] è il primo elemento. Questo inganna quasi tutti finché non diventa memoria muscolare.
Il Tuo Primo Script: hello_security.py
IDLE è per esperimenti. Gli script sono per conservare e condividere il lavoro. Apri qualsiasi editor di testo semplice—Notepad funziona, VS Code è meglio, evita Word perché aggiunge caratteri di formattazione invisibili che rompono Python.
Crea un nuovo file. Salvalo come hello_security.py in una cartella dedicata per questa guida. L'estensione .py dice al tuo sistema che questo è codice Python. Digita esattamente:
# hello_security.py
# Samuel Segato, DeafNews — Lab Wintermute training material
# My first security script: prints authorization reminder and target info target_host = "192.0.2.20" # Metasploitable2 server IP (authorized lab target)
target_role = "vulnerable server" # What this host represents in our scenario
is_authorized = True # CRITICAL: never run scans without written authorization print("=== Lab Wintermute Session ===")
print("Target:", target_host)
print("Role:", target_role)
print("Authorization confirmed:", is_authorized) if not is_authorized: print("ABORT: No authorization. Exiting.")
else: print("Proceeding with authorized reconnaissance only.")
Le righe che iniziano con # sono commenti. Python li ignora. Esistono per gli umani: il tuo futuro te stesso, il tuo compagno di lab, il revisore senior che controlla il tuo lavoro. Nella sicurezza, i commenti documentano lo stato dell'autorizzazione, i confini dello scopo e perché è stato selezionato un particolare target. Ho visto tester junior criticati più per commenti mancanti che per errori tecnici, perché il codice offensivo non commentato sembra sconsiderato.
Esegui il tuo script dal terminal. Naviga nella cartella del tuo script, poi:
python hello_security.py
o python3 hello_security.py come richiede il tuo sistema.
Output illustrativo — verifica sul tuo target:
=== Lab Wintermute Session === Target: 192.0.2.20 Role: vulnerable server Authorization confirmed: True Proceeding with authorized reconnaissance only.
Se vedi un SyntaxError o IndentationError, controlla di aver usato gli spazi in modo consistente—Python si interessa dell'indentazione, a differenza di molti linguaggi. Quattro spazi per livello è la convenzione. IDLE aiuta; il Notepad nudo no.
Funzioni: Blocchi di Codice Riutilizzabili
Copiare e incollare la stessa logica di scansione per dieci target è non manutenibile. Le funzioni avvolgono la logica riutilizzabile. Aggiungi questo al tuo script sopra il codice esistente, o crea check_port.py:
# check_port.py
# Stub for port connectivity check — full implementation in later pages import socket # Python's built-in networking module def test_target_connectivity(host, port): """ Attempt TCP connection to host:port. Returns True if connection succeeds, False otherwise. This is a stub — real timeout and error handling come later. """ try: # socket.AF_INET = IPv4 addressing # socket.SOCK_STREAM = TCP (connection-oriented) protocol s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) result = s.connect_ex((host, port)) # connect_ex returns error code, not exception s.close() return result == 0 # 0 means success except socket.error as e: print(f"Socket error for {host}:{port}: {e}") return False # Test against our authorized lab target
test_host = "192.0.2.20"
test_port = 22 print(f"Testing {test_host}:{test_port}...")
if test_target_connectivity(test_host, test_port): print("Port appears open (or accepting connections)")
else: print("Port closed, filtered, or host unreachable")
import socket porta il modulo della libreria standard di Python per le operazioni di rete. Il modulo socket, secondo il suo comportamento documentato, fornisce socket() restituendo un oggetto i cui metodi implementano chiamate di networking a livello di sistema. Per IPv4 (AF_INET), gli indirizzi sono coppie (host, port) con host come stringa e port come intero—esattamente il motivo per cui abbiamo definito test_port = 22 come numero, non "22".
⚠️ Solo per uso autorizzato e difensivo. Questo script si connette a una singola coppia host-porta. Eseguirlo contro indirizzi internet arbitrari senza permesso viola le leggi sulla frode informatica nella maggior parte delle giurisdizioni. Lab Wintermute esiste precisamente per farti imparare il meccanismo senza esposizione legale.
La struttura try / except cattura gli errori con eleganza. Senza di essa, una connessione rifiutata solleva un'eccezione e fa crashare il tuo script. Nell'automazione della sicurezza, i crash sono perdite di informazioni—rivelano la presenza del tuo strumento e fermano la tua raccolta dati. Gestire socket.error ti permette di registrare il fallimento e continuare.
Eseguilo:
python check_port.py
Output illustrativo — verifica sul tuo target:
Testing 192.0.2.20:22... Port appears open (or accepting connections)oppure, se il servizio SSH di Metasploitable2 è down o la tua rete è mal configurata:
Testing 192.0.2.20:22... Port closed, filtered, or host unreachable
Questo è intenzionalmente uno stub. Le pagine cinque e sei lo espandono con una gestione adeguata del timeout, iterazione su più porte e formattazione dei risultati. Ma lo scheletro conta: ora vedi come è strutturato uno strumento di sicurezza minimale—import, definisci la funzione, gestisci gli errori, esegui con dati di test.
Leggere le Traceback: L'Essenziale Abilità di Debugging
Rompi il tuo script di proposito. Cambia socket.socket(socket.AF_INET, socket.SOCK_STREAM) in socket.socket(socket.AF_INET, "SOCK_STREAM")—passando una stringa dove è attesa una costante intera. Eseguilo.
Traceback illustrativo — i tuoi numeri di riga esatti saranno diversi:
Traceback (most recent call last): File "check_port.py", line 24, in <module> if test_target_connectivity(test_host, test_port): File "check_port.py", line 13, in test_target_connectivity s = socket.socket(socket.AF_INET, "SOCK_STREAM") TypeError: 'str' cannot be interpreted as an integer
Leggi dal basso: TypeError ti dice la categoria—tipo di dato sbagliato usato. Il messaggio spiega. La riga sopra mostra il codice che fallisce. Le righe sopra quella mostrano lo stack di chiamata—chi ha chiamato chi per arrivare qui. Correggi l'errore, riesegui, conferma l'esecuzione pulita. Questo loop—rompi, leggi, correggi, verifica—è come sviluppi qualsiasi strumento non banale. Lo faccio ancora venti volte al giorno.
Struttura e Leggibilità per il Lavoro Collaborativo
La sicurezza è raramente un'attività solitaria. Il tuo script può essere revisionato da un senior, consegnato a un compagno di squadra, o presentato come lavoro di corso. La struttura conta tanto quanto la funzione.
Convenzioni che seguo e impongo nel mio lab:
- Commenti in cima: nome file, autore, scopo, stato autorizzazione
- Costanti in MAIUSCOLO se veramente costanti (raro negli script principianti; usiamo variabili normali)
- Le funzioni fanno una cosa sola:
test_target_connectivitytesta solo; non stampa report o scrive file - Esecuzione principale protetta: avvolgi le chiamate di test in
if __name__ == "__main__":così importare il tuo script come modulo non lo esegue accidentalmente
Aggiungi questa guardia a check_port.py indentando il codice di test in fondo:
if __name__ == "__main__": test_host = "192.0.2.20" test_port = 22 # ... rest of execution block
__name__ == "__main__" è True solo quando il file è eseguito direttamente, non quando importato. Questo previene sorprese quando riusiamo check_port.py come modulo in strumenti più grandi più avanti.
Checkpoint: Cosa Dovresti Avere Ora
| Artifact | Location | Purpose |
|---|---|---|
hello_security.py | La tua cartella guida | Promemoria autorizzazione; dimostra variabili, print, condizionale di base |
check_port.py | Stessa cartella | Primo stub di sicurezza; dimostra funzioni, import socket, gestione errori, struttura |
Entrambi gli script girano senza errori contro i target definiti di Lab Wintermute. Puoi modificare target_host in 192.0.2.30 (DVWA) e test_port in 80 per verificare che il web server risponde. Capisci perché 192.0.2.10 è la tua workstation Kali—non un target—e perché is_authorized esiste anche quando è sempre True nell'addestramento.
In termini semplici: hai imparato a far ricordare dati a Python, fare matematica e logica, parlare con le reti in sicurezza, e dirti quando si rompe. Queste quattro abilità si ripetono in ogni strumento di sicurezza che scriverai.
La pagina due copre più sintassi—cicli, dizionari, lettura file—poi li applica immediatamente al parsing di log di rete e alla costruzione di liste di target. Lo stub check_port.py ritorna lì, espanso in qualcosa che potresti effettivamente usare per la documentazione di ricognizione autorizzata.