Ethical Hacker con AI

Scanning Porte

Scansione Porte, Script Python

Scansione porte e Banner Grabbing con Python: guida pratica per Ethical Hacking

Nel campo della cybersecurity e dell'ethical hacking, conoscere quali porte sono aperte su un sistema e quali servizi sono attivi e fondamentale per prevenire attacchi e mitigare rischi di vulnerabilita.

In questo articolo trovi due strumenti pratici in Python: uno per vedere le connessioni attive sul tuo PC e uno per scansionare le porte piu comuni con cattura del banner. Spieghiamo anche cos e un banner e perche conviene effettuare la scansione.

💻 Script Python per vedere connessioni attive

Questo script mostra le connessioni di rete attive sul sistema locale. E utile per capire quali porte locali sono in uso e verso quali servizi remoti per esempio IMAPS, HTTPS stai comunicando.

Codice Python richiede psutil

import psutil
from datetime import datetime

print("=== Connessioni di rete attive ===")
print(f"Ora: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
print(f"{'Proto':<6} {'Indirizzo Locale':<25} {'Indirizzo Remoto':<25} {'Stato'}")
print("-" * 80)

for conn in psutil.net_connections(kind='inet'):
    laddr = f"{conn.laddr.ip}:{conn.laddr.port}" if conn.laddr else ""
    raddr = f"{conn.raddr.ip}:{conn.raddr.port}" if conn.raddr else ""
    proto = "TCP" if conn.type == 1 else "UDP"
    state = conn.status
    print(f"{proto:<6} {laddr:<25} {raddr:<25} {state}")
      
Come interpretare i risultati
  • Proto: protocollo TCP o UDP.
  • Indirizzo Locale: IP e porta locale del tuo PC spesso porta effimera alta.
  • Indirizzo Remoto: server di destinazione per esempio imap.example.com:993.
  • Stato: ESTABLISHED connessione attiva, LISTEN porta in ascolto, TIME_WAIT, ecc.

🚩 Che cos e un banner e perche effettuare la scansione

Quando ti connetti a un servizio su una porta di rete, molti server restituiscono un messaggio di benvenuto o intestazione chiamato banner. Il banner puo contenere informazioni su tipo e versione del software per esempio OpenSSH, Apache, MySQL e talvolta dettagli del sistema.

Perche il banner e utile nell'ethical hacking
  • Identificazione rapida del servizio e della versione.
  • Valutazione vulnerabilita confrontando la versione con eventuali CVE note.
  • Verifica configurazioni troppo verbose che espongono informazioni non necessarie.

Avvertenza: esegui scansioni solo su sistemi di tua proprieta o con permesso esplicito.

🔧 Script Python per la scansione delle porte piu comuni

Questo script chiede l'IP da scansionare, controlla un insieme di porte comuni spesso esposte o target di attacchi, rileva se sono aperte o chiuse e prova a catturare un banner. Alla fine stampa una tabella riassuntiva in console.

Codice Python scansione porte comuni con banner

import socket
import ssl
from datetime import datetime

COMMON_PORTS = {
    21:  "FTP",
    22:  "SSH",
    23:  "Telnet",
    25:  "SMTP",
    53:  "DNS",
    80:  "HTTP",
    110: "POP3",
    143: "IMAP",
    389: "LDAP",
    443: "HTTPS",
    445: "SMB",
    465: "SMTPS",
    587: "SMTP-Submission",
    993: "IMAPS",
    995: "POP3S",
    1433: "MSSQL",
    1521: "Oracle",
    3306: "MySQL",
    3389: "RDP",
    5432: "PostgreSQL",
    6379: "Redis",
    8080: "HTTP-alt",
    8443: "HTTPS-alt",
    9200: "Elasticsearch",
    11211: "Memcached",
}

TIMEOUT = 1.0

def safe_decode(b):
    try:
        return b.decode("utf-8", errors="ignore").strip()
    except:
        return repr(b)

def recv_try(sock, nbytes=4096, timeout=TIMEOUT):
    sock.settimeout(timeout)
    try:
        data = sock.recv(nbytes)
        return safe_decode(data) if data else ""
    except socket.timeout:
        return ""
    except Exception:
        return ""

def http_head_banner(sock, host, use_tls=False):
    req = b"HEAD / HTTP/1.0\r\nHost: " + host.encode() + b"\r\nUser-Agent: banner-grabber\r\n\r\n"
    if use_tls:
        ctx = ssl.create_default_context()
        ctx.check_hostname = False
        ctx.verify_mode = ssl.CERT_NONE
        try:
            with ctx.wrap_socket(sock, server_hostname=host) as ssock:
                ssock.sendall(req)
                return recv_try(ssock)
        except Exception as e:
            return f"Errore TLS: {e}"
    else:
        try:
            sock.sendall(req)
            return recv_try(sock)
        except Exception as e:
            return f"Errore HTTP: {e}"

def connect(host, port):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(TIMEOUT)
    code = s.connect_ex((host, port))
    return s, code

def grab_banner(host, port):
    s, code = connect(host, port)
    if code != 0:
        try:
            s.close()
        except Exception:
            pass
        return "closed", ""

    banner = ""
    try:
        if port in (21, 22, 23, 25, 110, 143, 3306, 1433, 6379, 11211):
            banner = recv_try(s)
            if not banner and port == 6379:
                try:
                    s.sendall(b"PING\r\n")
                    banner = recv_try(s)
                except Exception:
                    pass
            if not banner and port == 11211:
                try:
                    s.sendall(b"version\r\n")
                    banner = recv_try(s)
                except Exception:
                    pass
        elif port in (80, 8080):
            banner = http_head_banner(s, host, use_tls=False)
        elif port in (443, 8443):
            banner = http_head_banner(s, host, use_tls=True)
        elif port in (389,):
            banner = recv_try(s) or "Nessun banner (LDAP potrebbe richiedere bind)"
        else:
            banner = recv_try(s)
    except Exception as e:
        banner = f"Errore durante banner grab: {e}"
    finally:
        try:
            s.close()
        except Exception:
            pass

    banner_one_line = (banner or "").replace("\r", " ").replace("\n", " ").strip()
    if len(banner_one_line) > 200:
        banner_one_line = banner_one_line[:200] + "..."
    return "open", banner_one_line

# MAIN
target = input("Inserisci l'IP o hostname da scansionare: ").strip()

print("")
print("=== Scansione Porte Comuni ===")
print(f"Target: {target}")
print(f"Porte totali: {len(COMMON_PORTS)}")
print(f"Inizio: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("")
print(f"{'Porta':<6} {'Servizio':<14} {'Stato':<10} Banner")
print("-" * 100)

for port, service in sorted(COMMON_PORTS.items()):
    status, banner = grab_banner(target, port)
    banner_short = (banner[:80] + "...") if banner and len(banner) > 80 else (banner or "")
    print(f"{port:<6} {service:<14} {status:<10} {banner_short}")
      
Esempio di tabella riassuntiva porte comuni

Questa tabella elenca alcune porte frequentemente esposte con il servizio tipico associato. Serve come riferimento rapido.

Porta Servizio Descrizione
22 SSH Accesso remoto sicuro per shell e amministrazione
80 HTTP Servizio web non cifrato
443 HTTPS Servizio web cifrato con TLS
3306 MySQL Database relazionale MySQL
6379 Redis Data store in memoria; spesso vulnerabile se esposto
11211 Memcached Cache distribuita; non dovrebbe essere pubblica

⚠ Note su ethical hacking

Esegui scansioni solo su sistemi di tua proprieta o per i quali hai consenso scritto. L'uso non autorizzato di tecniche di scanning puo violare leggi e policy.

Questo articolo e stato generato da ChatGPT.

Livio Bollini
Walter Livio Bollini

Matematico & Informatico · Intelligenza Artificiale · Sviluppo Web