Hardware
Posizionamento
Per prima cosa bisogna capire se il server lo si vuole posizionare in modo che possa essere spostato
facilmente oppure no. Nel caso è consigliato ancorare la struttura con cementi o supporti in acciaio
inox resistenti al calore, affinché possa garantire una protezione in caso di furto. Nel caso invece
lo si voglia mantenere portatile potrebbe essere conveniente metterlo in un supporto a valigetta,
assicurandosi un corretto ricircolo di aria.
Il cammuffaggio è altrettanto importante e seppur sia rilevabile in una stanza grazie a rilevatori di
emissioni elettromagnetiche, è importante dare la minor accessibilità possibile a terzi.
I dispositivi impiegabili per scovare il server Tutanum in questione sono gli analizzatori di spettro, i
dispositivi TEMPEST, i rilevatori RF e i rilevatori EMF.
È possibile inoltre rilevare tali informazioni per via acustica amplificando il segnale acustico emanato
dalle CPU o da altri componenti in funzione, filtrando tutti gli altri rumori che fungono da disturbo al
segnale, per poi ricostruire, solitamente tramite algoritmi di intelligenza artificiale e decifrare le
informazioni raccolte, quasi solitamente criptate. Il nome di questo tipo di attacco è Acoustical
Side-Channel Attack. Il metodo più semplice per trovare un server Tutanum rimane quello di verificare dove è
agganciato il router risalendo il cavo ethernet, ma a questo si potrebbe trovare rimedio usando un
ripetitore nascosto per casa, seppur sia soggetto agli attacchi di tipo elettromagnetico.
Pertanto il rimedio rimane quello di sorvegliare il possibile il server, di cammuffarlo, di non attirare
troppa attenzione per quanto riguarda i prossimi livelli e soprattutto di mantenere l'anonimato, così da
assicurare una buona continuità dei servizi.
Rete
Il server Tutanum in fase di installazione non deve essere collegato alla rete, in quanto
potrebbero esserci delle intercettazioni o delle fughe di dati per mezzo di qualche software spia (spyware)
presente sul dispositivo di installazione.
È consigliata infatti un'installazione completamente offline: basta visitare i siti che occorrono (usando un
altro dispositivo) e salvarli se necessario, così che l'installazione possa essere condotta in tutta
sicurezza.
È vero che Tutanum Lieve potrebbe presentare alcuni problemi per quanto riguarda la fase di installazione
essendo il più delle volte, soprattutto per i dispositivi embedded basati su ARM, e pertanto potrebbe
richiedere la connessione ad internet per proseguire, ma è importante una volta fatto il minimo
indispensabile, procedere ad effettuare le modifiche offline, così che alla prossima riconnessione si possa
garantire una migliore sicurezza in termini sia di privacy che di anonimato.
È fortemente sconsigliata la connessione wireless ed è consigliata la disabilitazione sia fisica che
virtuale dei dispositivi che vi permettano una connessione, in quanto potrebbero esserci degli spyware che
possono andare a sniffare il traffico reti, ricavando informazioni anche sensibili che potrebbero suggerire
a terzi sia la vostra posizione, che la possibilità di potere sfruttare qualche vulnerabilità per
compromettere il vostro router.
È importante utilizzare un router non fornito dai provider internet, come avviene nella maggior parte dei
casi, poiché potrebbero essere presenti dei malware, spyware o configurazioni di dirottamento o di censura
(come avviene su alcuni router), ma
acquistato dal fornitore o da un distributore fidato.
Per scrupolo potrebbe essere anche utile effettuare il reset del router, solitamente premendo il
tasto fisico per tot secondi, posto appositamente sul lato posteriore.
Ci sarebbe anche la possibilità di potere cambiare sistema operativo sul router al fine di garantire una
migliore sicurezza, usando per esempio BSDRP o pfSense, verificando comunque a priori la compatibilità con il
router
stesso, oppure ancora meglio OPNsense che ha meno interessi commerciali
e una community migliore. Una buona marca di router potrebbero essere quelli di Fritz!Box (prodotti
dall'azienda tedesca AVM),
in
quanto presentano delle buone prestazioni e funzionalità hardware, anche se purtroppo integrando del
firmware
proprietario, sostituibile tuttavia con BSDRP, pfSense, OpenWrt, DD-WRT, LibreCMC, o qualsiasi altro
firmware
funzionante ma libero o aperto (verificarne sempre la compatibilità).
L'alternativa sarebbe osare e andare su prodotti più aperti e liberi come un router autocostruibile: LibreRouter, con LibreRouterOS, distro GNU Linux basata su
OpenWRT.
Oppure ancora ci sarebbe l'alternativa di autocostruirsi un router in casa utilizzando un computer (meglio
se ARM o RISC-V come vedremo poi, con uno dei sistemi operativi citati in precedenza) dotato di scheda di
rete (le Intel sono migliori in quanto a compatibilità e prestazioni, per verificarne la compatibilità è
possibile consultare la documentazione della propria scheda madre) con almeno due porte ethernet: una da
collegare allo switch (per le connessioni ethernet) e l'altra da collegare al modem (per le connessioni
wireless). Un router in fin dei conti è un computer, uno switch e un modem messi insieme, no?
Lasciamo tuttavia aperto questo punto, sulla scelta del router, in quanto potrebbe presentarsi in futuro
come un ulteriore prodotto da aggiungere alla documentazione del progetto Tutanum.
Alimentazione
La soluzione più semplice ed efficace è quella di utilizzare, almeno per Tutanum Lieve, dei PC portatili con
la batteria facilmente sostituibile: molti PC ormai presentano delle difficoltà non banali per quanto
riguarda l'estrazione della batteria, con lo scopo di tenerli sempre accesi, questo è accaduto soprattutto
dal 2013 in poi.
In alternativa potrebbe essere fornita una batteria collegata in parallelo ad un banco elettrico attaccato
alla rete
elettrica di casa, in modo che così la batteria abbia sempre della corrente e funga da UPS, tuttavia è anche
vero che un sistema ideale sarebbe un sistema autoalimentato, ma sempre interrotto, di modo che la corrente
elettrica non possa essere interrotta. L'interruzione della linea elettrica se condotta da qualche
intelligence su aree locali, potrebbe portare per esclusione alla rivelazione della posizione geofisica del
server.
Tornando sul server, il tasto di accensione e di spegnimento è ormai, nella maggior parte dei casi,
digitale, come avviene per
esempio negli smartphone, così che esso funzioni sempre e possa tenere accesi moduli hardware o comunque
backdoor che possono compromettere la privacy e l'anonimato.
Tempo
Anche la batteria tampone in realtà fa la sua parte e potrebbe tenere attivi alcuni circuiti o presentare
alcune emissioni elettromagnetiche rilevabili esternamente, come presentato nella sezione "Rete", pertanto
consigliamo di toglierla e di usare moduli esterni come il DS1307 o il DS3231, alimentati esternamente o direttamente
dalla scheda madre o dalla GPIO in caso di single board computer per una maggiore precisione sul timestamp.
Le single board come il famoso Raspberry Pi scrivono il timestamp in un file prima di spegnersi e se è
connesso ad internet provvede ad aggiornarlo, altrimenti rimane indietro, cosa che richiede pertanto, per
progetti offline, un RTC esterno alimentato a batteria.
Altre modalità più precise e scientifiche per quanto riguarda la misurazione del tempo, calcoli scientifici
a parte da attuare su eventuali esperimenti o moduli da agganciare a Tutanum, riguardano l'implementazione
di orologi atomici: un secondo equivale alla durata di 9.192.631.770 oscillazioni della radiazione
elettromagnetica
emessa dall'atomo dell'isotopo del cesio-133 in ambiente isolato. Il cesio rimane pericoloso da gestire e da
maneggiare, pertanto vengono in alcuni casi preferite versioni meno precise ma più economiche, come quella
che fa uso del rubidio gassoso: le oscillazioni vengono rilevate
in
base a dei
rilevatori di fotoni, tenendo da conto anche delle latenze e al contempo viene misurato il feedback rispetto
ad
un oscillatore al quarzo. In altre parole questo sistema è quello di un orologio atomico e sul mercato si
possono reperire a cifre intorno ai €2000.
Citiamo per correttezza anche gli orologi a
frequenze ottiche (funziona con dei laser impiegati su celle di vapore di iodio) venduti dalla
Vector Atomic, più performanti dei più comuni orologi a microonde ma meno precisi degli orologi atomici.
Il tempo come vettore d'attacco
L'orologio non è solo una questione di precisione. La documentazione di Whonix dedica una pagina agli attacchi basati sul tempo e una alla sincronizzazione: un orologio che si sincronizza male, o che lascia trapelare la propria ora, espone il nodo a una famiglia intera di attacchi di deanonimizzazione.
- NTP è vecchio, in chiaro e non autenticato: un avversario sul percorso può falsificare le risposte, e i difetti dei client NTP sono stati sfruttati per eseguire codice da remoto. Usa UDP, quindi non può nemmeno passare da Tor.
- Replay: chi riporta indietro l'orologio del nodo può fargli accettare un consenso di Tor scaduto, oppure aggiornamenti e certificati vecchi e vulnerabili.
- Impronta dell'orologio: ogni quarzo deriva in modo proprio. Se l'ora del nodo trapela sia dal traffico anonimo sia da quello in chiaro, un osservatore passivo collega i due alla stessa macchina.
- Localizzare un onion service: il carico della CPU scalda il quarzo e ne altera la frequenza. Chi può caricare a comando il servizio nascosto e insieme osservare l'orologio di una macchina candidata, vede le due curve coincidere.
L'ora trapela da quattro punti precisi, e tutti si possono chiudere.
| Da dove trapela | Che cosa rivela | Contromisura |
|---|---|---|
| Timestamp TCP | Ora al millisecondo e tempo di accensione, in ogni pacchetto | Disattivarli, come in Attacchi
di rivelazione, oppure farli modulare da pf con scrub reassemble tcp |
| Timestamp ICMP | L'ora del nodo, a chiunque la chieda | Non rispondere e scartare la richiesta nel firewall |
| Numeri di sequenza iniziali TCP (ISN) | Il carico della CPU, attraverso il timer che li genera | Su Linux il modulo tirdad; su *BSD modulate state di pf,
che li riscrive con valori casuali |
| Client NTP | L'ora, e la presenza stessa del nodo, a ogni interrogazione | Nessun client NTP classico sul nodo |
# FreeBSD, /etc/sysctl.conf
net.inet.icmp.tstamprepl=0 # nessuna risposta alle richieste di timestamp ICMP
net.inet.tcp.rfc1323=0 # nessun timestamp TCP
# /etc/pf.conf
block in quick inet proto icmp icmp-type timereq
pass out on em0 proto tcp from (em0) to any modulate state # ISN casuali in uscita
Resta da decidere come regolare l'orologio senza NTP. Whonix usa sdwdate, che ricava l'ora
interrogando attraverso Tor, su TCP cifrato, alcuni server onion scelti da gruppi indipendenti, e
blocca la rete finché non ha finito. Su *BSD lo strumento non esiste, ma il principio si riproduce:
- Ora attraverso Tor: si legge l'intestazione
Datedi più onion service indipendenti e si prende la mediana. La precisione è di qualche secondo, e basta: Tor smette di funzionare solo se l'orologio è più di un'ora indietro o di tre ore avanti, e Whonix raccomanda di restare entro mezz'ora. - Ora autenticata: dove serve maggiore precisione,
ntpddi OpenBSD accetta un vincolo TLS (constraints from) che scarta le risposte NTP incompatibili con l'ora di un server HTTPS, echronysupporta NTS. Restano traffico UDP in chiaro, visibile al fornitore di rete. - Orologio hardware: il modulo RTC esterno descritto sopra riduce quanto spesso serve chiedere l'ora a qualcuno.
# ora da tre onion service, attraverso Tor: si usa la mediana, mai una fonte sola
for o in primo.onion secondo.onion terzo.onion; do
curl -sI --max-time 60 --socks5-hostname 10.0.0.2:59353 "http://$o/" | sed -n 's/^[Dd]ate: //p'
done
Lo script completo, che calcola la mediana e corregge l'orologio tenendo conto del securelevel, è in Tutanum Classico.
Sincronizzazione sicura: NTS, Roughtime e GPS
Il cenno fatto sopra a NTS merita di essere sviluppato, perché Network Time Security (RFC 8915) è oggi il modo più solido per prendere l'ora dalla rete in chiaro senza fidarsi del percorso: un primo scambio su TLS, il cosiddetto NTS-KE sulla porta 4460, autentica il server con un certificato e consegna al client alcune chiavi AEAD e dei cookie opachi, dopodiché lo scambio NTP vero e proprio prosegue su UDP, ma ogni risposta è firmata e verificabile, cosicché un avversario sul percorso riesce a ritardare o a bloccare il traffico senza però falsificare l'ora. Il contenuto resta visibile al fornitore di rete, quindi NTS si addice ai nodi che si affacciano sul web in chiaro, mentre per un nodo che esce solo da Tor, dove UDP non passa, resta valido l'approccio di sdwdate già descritto.
# /usr/local/etc/chrony.conf: ora autenticata da piu' fonti indipendenti
server time.cloudflare.com iburst nts
server nts.netnod.se iburst nts
server nts.sth1.ntp.se iburst nts
ntsdumpdir /var/db/chrony/nts
# verifica che le fonti siano davvero autenticate:
# chronyc -N authdata
# Type 15 = AEAD-AES-SIV-CMAC-256; la colonna Cook mostra i cookie residui
Ancora più vicino alla filosofia di Tutanum, che già per l'ora onion prende la mediana di più
fonti per non fidarsi di nessuna, è Roughtime (bozza IETF draft-ietf-ntp-roughtime):
il client invia un nonce casuale e il server risponde con un timestamp e un raggio di
incertezza firmati sulla radice di un albero di Merkle che include quel nonce, dimostrando così in
modo crittografico di aver risposto dopo la richiesta, e interrogando una catena di server
indipendenti, con la risposta di uno incatenata nel nonce del successivo, un server che mente viene
scoperto e lascia per giunta una prova firmata della propria malafede, il che trasforma la fiducia
cieca in una verifica distribuita.
Resta il caso dei nodi che ricavano ora e posizione da un ricevitore GPS, tipico delle single board e dei nodi radio con modulo GNSS: il segnale satellitare è debolissimo e privo di autenticazione, quindi un trasmettitore vicino lo sovrasta con un segnale falso e sposta a piacere sia l'orologio sia la posizione dichiarata, attacco che si lega direttamente alla localizzazione per differenza di arrivo vista nella sezione sulle reti radio, dove la marca temporale è tutto.
Mitigazione: non trattare mai il GPS come fonte unica. Un ricevitore che incroci più costellazioni e scarti i satelliti anomali con il T-RAIM, che verifichi l'autenticità del messaggio di navigazione dove è prevista (Galileo OSNMA, QZSS QZNMA) e che sorvegli il guadagno automatico e il rapporto portante/rumore riconosce gran parte degli inganni, mentre un oscillatore disciplinato dal GPS con tenuta autonoma, il GPSDO, continua a fornire l'ora attraverso un filtro di Kalman quando il segnale sparisce o diventa sospetto, e due oscillatori in tenuta che si controllano a vicenda smascherano quello corrotto. In pratica si combina il GPS con l'RTC esterno già descritto e con un'ora di rete autenticata via NTS, confrontando di continuo le fonti.
PoC di verifica: confrontare l'ora del GPS con quella disciplinata via NTS e allarmare quando divergono oltre il raggio atteso, nello stesso spirito del "mai una fonte sola".
#!/bin/sh
# Allarme se l'ora del GPS e quella di sistema (disciplinata da chrony/NTS) divergono oltre 2 secondi.
gps=$(gpspipe -w -n 5 | sed -n 's/.*"time":"\([^"]*\)".*/\1/p' | tail -1)
gps_s=$(date -j -f "%Y-%m-%dT%H:%M:%S" "${gps%.*}" +%s 2>/dev/null) || exit 0
sys_s=$(date +%s)
if [ "$(( gps_s > sys_s ? gps_s - sys_s : sys_s - gps_s ))" -gt 2 ]; then
logger -t tempo "divergenza GPS/NTS sospetta: possibile spoofing del segnale"
fi
Compromissione elettromagnetica
Al fine di proteggerlo da possibili attacchi elettromagnetici, è raccomandato ulteriormente instradare le
connessioni esclusivamente via cavo ethernet (possibilmente schermato) proteggendolo così da possibili
interferenze elettromagnetiche indesiderate.
La classificazione delle interferenze elettromagnetiche che possono compromettere l'elettronica si possono
così classificare:
- Un EMP (sia esso artificiale e dunque generato da una trasmittente, sia esso generato da un evento naturale come le tempeste solari o sia esso generato da un'esplosione nucleare, quindi un NEMP) è un impulso, quindi ha energia distribuita su un'ampia gamma di frequenze (nel campo delle microonde).
- Il NEMP è formato dall'interazione di elettroni veloci (provenienti dalla fonte) che interagiscono con il campo magnetico terrestre. L'altitudine ottimale per lo scoppio è di circa 100km, quindi presso il suolo non vanno a formarsi solo campi elettrici o magnetici, ma piuttosto un'onda elettromagnetica che si propaga. Questa onda indurrà correnti e tensioni nei conduttori, e le cose collegate a tali conduttori potrebbero sperimentare tensioni elevate o correnti di iniezione, motivo per cui bisognerebbe implementare un filtro ad hoc.
Per risolvere queste problematiche catastrofiche, si può impiegare una gabbia di Faraday, la quale dovrebbe
essere progettata assumendo come modello teorico lo scudo di Faraday. Questo schermo può avere una
superficie omogenea e perfettamente conduttiva, oppure può presentare dei fori. Tali fori (la dimensione
massima è più importante dell'area) agiscono come filtri passa-alto, quindi massimizzando la schermatura,
riducendo al minimo le aperture e le discontinuità dello schermo.
Poiché il NEMP arriva alla superificie di Faraday come un'onda EM che si propaga con un'impedenza nello
spazio libero di 377Ω, il componente principale della schermatura è la riflessione della prima superficie,
causata dalla massiccia discontinuità dell'impedenza sulla superficie di Faraday. Quindi, una lastra di rame
riflette meglio della gomma conduttiva e pertanto massimizza la conducibilità dello schermo. La profondità
di
penetrazione è altresì importante, ma quasi qualsiasi materiale conduttivo comune in grado di essere
fabbricato e di sostenersi avrà così tante profondità di penetrazione che l'assorbimento all'interno dello
schermo sarà un fattore di schermatura minore. È possibile costruire la superficie con una rete di bronzo o
con un tessuto di rame, ma è importante prestare particolare attenzione all'ossidazione dove ogni filo
incrocia
un altro: spesso la rete in acciaio (con incroci conduttivi) è una soluzione a lungo termine migliore. La
soluzione ulteriormente migliore sarebbe costruirla in acciaio saldato MIG continuo da 6,35mm.
Uno schermo di Faraday è un concetto ideale, mentre nel mondo reale si vanno a proteggere dispositivi fisici
che presentano impurità, imperfezioni o rumori di diversa natura. Ogni penetrazione della superficie di
Faraday ha il potenziale di potere compromettere completamente tutto lo schermo, quindi ogni penetrazione
deve essere progettata con le appropriate tecniche di controllo.
Se ciò che si vuole è una schermatura minimale ma decente per potere conservare qualche apparecchiatura come
il nostro server, si può ottenere dagli 80 ai 100 dB di schermatura, avvolgendolo in uno strato o due di
alluminio e piegando saldamente le cuciture, tenendo da conto comunque che dovrà essere garantito il
passaggio di calore per la refrigerazione del sistema. I modelli militari per NEMP hanno una forza di campo
elettrico pari a 50.000 V/m, quindi permettendo anche di raggiungere anche 80 dB di schermatura, producendo
solo 5 V/m all'interno dello schermo, e forse solo 0,5 V/m con 100 dB di schermatura elettromagnetica. La
maggior parte delle apparecchiature minimali dovrebbero resistere abbastanza bene. Le apparecchiature con
marchio CE hanno un po' più di possibilità rispetto alle apparecchiature senza marchio CE nel caso di
un'acquisto di gabbie di Faraday, poiché l'Europa richiede test di esposizione di 3 V/m, mentre nazioni come
gli Stati Uniti d'America non hanno tale requisito.
Calore e umidità
Al fine di proteggere il server da possibili incendi provenienti dall'esterno è necessario provvedere in
primis ad un estintore e in seconda istanza ad un possibile armadio ignifugo IP68 in modo che sia
resistente alla polvere, che possa essere immerso in acqua, garantendo oltretutto un sistema di aerazione
consistente.
Per raffreddare il sistema è possibile diverse soluzioni, tra cui:
- Ventola con filtro ai carboni attivi: prende aria dall'esterno ma non garantisce che essa sia fredda o calda e non garantisce che possa trattarsi per esempio di un gas infiammabile.
- Sistema refrigerante: necessiterebbe di essere alimentato autonomamente e potrebbe subire guasti più frequentemente.
- Isolamento all'azoto: il server potrebbe essere immerso in una scatola nella quale potrebbe essere ventilato dell'azoto prodotto al momento, così da evitare possibili problemi esplosivi e in modo da potere garantire una refrigerazione a circuito chiuso. L'unico problema è che l'azoto potrebbe portare all'asfissia saturando pertanto una stanza con tale gas a discapito dell'ossigeno, necessario per vivere.
- Raffreddamento a liquido: necessità che il calore venga asportato con una ventola e per le leggi della termodinamica funzionerebbe fintanto che la stanza nella quale è ospitato il server fosse più fredda rispetto ad esso. Pertanto si renderebbe necessario un sistema refrigerante.
Monitoraggio e difesa
Un nodo Tutanum va osservato di continuo per accorgersi di saturazioni, scansioni e tentativi di DoS prima che diventino un problema. Il monitoraggio si articola su tre livelli:
- Risorse e rete: uso di CPU, RAM, code e banda con strumenti di base (
top,systat,vnstat) e, per i servizi di anonimato,nyxper Tor e la console web di i2pd. - Log ed eventi: lettura dei log di sistema e dei contatori del firewall (
doas pfctl -s info), insieme ai ban di fail2ban, per distinguere il traffico legittimo dagli abusi. - Avvisi fuori banda: inoltrare le notifiche degli eventi critici (saturazione, crash di
toroi2pd, ban ripetuti) su un canale indipendente dal server. Una scelta comoda è XMPP (Jabber), federato e facilmente auto-ospitabile.
Monitoraggio e firewall lavorano insieme: il firewall blocca, il monitoraggio avvisa, e insieme costituiscono la base dell'EDR e del SIEM personalizzati previsti per Tutanum.
Una dashboard unificata
L'obiettivo è avere un unico punto da cui leggere lo stato del nodo. In linea con il software suckless e con la modularità che discende dal KISS, non si costruisce un monolite ma si compongono piccoli strumenti che fanno una cosa sola e la fanno bene, uniti in una sola vista.
- Metriche e risorse: oltre a
top,systatevnstat, per una vista web leggera vanno benecollectdconrrdtool, oppuremonit, che in un solo processo controlla i servizi, mostra una paginetta e sa avvisare. Chi vuole più dettaglio può usare netdata disattivandone la telemetria. - Log centralizzati:
syslogdraccoglie già tutto; per leggerli e correlarli senza uno stack pesante è ottimolnav, che naviga ed evidenzia i log. - Servizi di anonimato:
nyxper Tor e la console web di i2pd. - Composizione: invece di un cruscotto unico e chiuso, una pagina statica generata da uno script
periodico che unisce i numeri chiave, oppure una dashboard da terminale con
tmuxche affianca gli strumenti.
Un esempio minimale con monit, che controlla un servizio e invia un avviso, e una dashboard da terminale:
# /usr/local/etc/monitrc: controlla tor e avvisa se cade
check process tor matching "tor"
if not exist then alert
if cpu > 80% for 5 cycles then alert
set alert tutanum@localhost
# dashboard da terminale: tre strumenti affiancati in tmux
tmux new-session -d -s cruscotto "nyx"
tmux split-window -h "lnav /var/log/messages"
tmux split-window -v "top"
tmux attach -t cruscotto
Antivirus, EDR e XDR
Le tre sigle indicano tre generazioni della stessa idea: accorgersi che una macchina è stata
compromessa e fare qualcosa prima che il danno si allarghi. Su un nodo Tutanum la prima difesa resta la
prevenzione (pledge e unveil, securelevel, jail, partizioni noexec), perché riduce ciò che
un processo compromesso può fare. Ma la prevenzione prima o poi fallisce, e in quel momento servono due
cose: sapere subito che è successo e fermare subito ciò che sta succedendo. Questa sezione descrive come
ottenerle con software libero, locale e piccolo.
Prima di tutto, la prevenzione: ciò che si scrive non si esegue
Il rilevamento per firma o per comportamento è una rete di sicurezza, non la prima difesa: un file scritto apposta per non dare nell'occhio, o semplicemente nuovo, la attraversa. La difesa che non dipende dal riconoscere la minaccia è strutturale, ed è il vecchio principio W^X esteso dal singolo processo all'intero filesystem: ciò che un servizio può scrivere non deve poterlo eseguire, e ciò che esegue non deve poterlo scrivere. Un servizio compromesso che non può materializzare ed eseguire un secondo programma è contenuto molto prima che l'antivirus o la sentinella se ne accorgano.
Sull'host del nodo le aree scrivibili da tutti (/tmp, /var/tmp) sono già
noexec,nosuid. Nelle jail il principio va esteso a mano, e qui c'è un'insidia emersa
provando su FreeBSD 15.1: impostare exec=off sul dataset ZFS non basta, perché le
jail gestite da CBSD montano le proprie cartelle con nullfs in lettura-scrittura e senza
noexec, e attraverso quel secondo montaggio il file resta eseguibile. La soluzione è
dichiarare le opzioni giuste nel file dei montaggi aggiuntivi della jail (fstab.local), che
CBSD applica al posto delle righe predefinite:
# /jails/jails-fstab/<jail>/fstab.local: ciò che si scrive non si esegue
# eseguibili e configurazione: sola lettura (li cambia solo l'host, aggiornando i pacchetti)
/jails/jails-data/<jail>-data/etc /etc nullfs ro 0 0
/jails/jails-data/<jail>-data/usr/local /usr/local nullfs ro 0 0
/jails/jails-data/<jail>-data/compat /compat nullfs ro 0 0
# aree scrivibili dal servizio: mai eseguibili
/jails/jails-data/<jail>-data/tmp /tmp nullfs rw,noexec,nosuid 0 0
/jails/jails-data/<jail>-data/var /var nullfs rw,noexec,nosuid 0 0
/jails/jails-data/<jail>-data/home /home nullfs rw,noexec,nosuid 0 0
/jails/jails-data/<jail>-data/root /root nullfs rw,noexec,nosuid 0 0
# poi: cbsd jstop <jail> && cbsd jstart <jail>. Prova dall'interno della jail:
# cp /bin/echo /tmp/x && /tmp/x -> Permission denied (exit 126)
# touch /usr/local/x -> Read-only file system
Gli aggiornamenti dei pacchetti continuano a funzionare perché si fanno dall'host sulla cartella dei
dati (pkg -r /jails/jails-data/<jail>-data), che resta scrivibile; dentro la jail, in
esecuzione, quelle stesse cartelle sono in sola lettura. Un servizio che ha bisogno di eseguire file da
una sua sottocartella scrivibile (per esempio un ambiente virtuale Python) fa eccezione mirata: quella
cartella torna eseguibile ma diventa di sola lettura. I file che arrivano dall'esterno (scaricati
dall'esca, ricevuti da altri nodi) atterrano solo nella quarantena, anch'essa
noexec, e restano dati. Resta un limite onesto: un interprete già installato
(sh, o Python nella jail dell'esca) può ancora leggere ed eseguire uno script che trova in
un'area scrivibile; per questo l'eliminazione vera degli eseguibili non previsti richiederebbe
veriexec, assente nel kernel GENERIC, e nel frattempo ci si appoggia ai flag
schg e al securelevel per gli eseguibili legittimi.
Tre sigle, tre generazioni
- Antivirus: confronta i file con un elenco di cose già viste (firme e hash). Guarda l'identità di un oggetto: è rapido e preciso, ma cieco davanti a tutto ciò che non è ancora in elenco.
- EDR (Endpoint Detection and Response): osserva di continuo che cosa fanno i processi (esecuzioni, connessioni, modifiche ai file), riconosce i comportamenti anomali e soprattutto risponde: isola la macchina, ferma il processo, conserva le prove per l'indagine.
- XDR (Extended Detection and Response): estende la correlazione oltre il singolo endpoint e mette insieme rete, autenticazioni, honeypot e più nodi, così che segnali deboli e separati diventino un unico allarme forte.
I prodotti commerciali fanno bene queste cose, ma a un prezzo che Tutanum non può pagare. Sono chiusi e quindi non verificabili. Inviano la telemetria (processi, nomi di file, connessioni) al cloud del fornitore, che equivale a consegnare a un terzo il diario completo del nodo. E girano nel kernel con i privilegi massimi: sono essi stessi superficie d'attacco e punto singolo di guasto, come ha mostrato l'aggiornamento difettoso di CrowdStrike che il 19 luglio 2024 ha bloccato circa 8,5 milioni di macchine Windows nel mondo. La difesa dell'endpoint, in Tutanum, si costruisce invece componendo strumenti che il sistema possiede già.
Che cosa insegna Whonix
Il progetto Whonix, con la sua base Kicksecure, discute da anni se un sistema votato all'anonimato debba dotarsi di antivirus e di rilevamento delle intrusioni. Le conclusioni, raccolte nella pagina Malware and Firmware Trojans e in alcune discussioni del forum, qui valgono come vincoli di progetto.
- Uno scanner è superficie d'attacco, e non in teoria: gira con privilegi alti e per mestiere
analizza input ostile. Nella discussione
Installation
of Antivirus Scanners by Default si ricordano exploit che ottenevano i privilegi massimi
colpendo proprio l'antivirus. Il criterio che ne esce è netto: uno scanner è accettabile solo se
non riferisce a un server remoto, non gira come root e non pesa in modo inaccettabile. Per questo
in Tutanum
clamdgira come utente non privilegiato in una jail propria, riceve i file per descrittore e scarica le firme attraverso Tor. - Meglio chiudere un meccanismo che inseguire le firme: un elenco di file malevoli è la prima cosa contro cui un attaccante prova i propri strumenti. Il controllo d'integrità (AIDE) e la protezione del kernel a runtime (LKRG) eliminano invece intere classi di attacco. Nella discussione su AIDE si riporta che la loro combinazione ha rilevato 14 rootkit su 15 provati. Da qui il peso che questa sezione dà all'allowlist e all'integrità rispetto alle firme.
- L'integrità senza disciplina è solo rumore: la stessa discussione osserva che dopo un aggiornamento AIDE elenca centinaia di file cambiati, e nessuno sa più distinguere il legittimo dall'ostile. Il controllo va quindi eseguito subito prima di ogni aggiornamento e la base di riferimento rigenerata subito dopo, nella stessa operazione.
- Su un server l'IDS ha senso, ma non sul traffico: nella discussione su IDS e IPS si nota che questi strumenti si addicono ai server più che ai client, ma che il traffico cifrato o instradato su Tor non si può ispezionare. Su un nodo Tutanum quasi tutto il traffico è Tor o I2P: il rilevamento va fatto sull'host, osservando i processi.
- Chi osserva sta fuori da chi è osservato: uno scanner dentro la macchina sorvegliata è comodo ma può essere spento dal malware che dovrebbe trovare. In Tutanum la sentinella e le scansioni girano sull'host, fuori dalle jail, che non possono né vederle né fermarle.
- Nessuno strumento certifica che un sistema è pulito: la pagina di Kicksecure cita Joanna Rutkowska: non esiste un metodo affidabile per stabilire che un sistema non è compromesso. Il malware mirato evita di lasciare tracce evidenti. Il silenzio dell'EDR non è una prova, e dopo una compromissione accertata si ricostruisce, non si ripulisce.
Rilevamento a hash
Il rilevamento a hash risponde alla domanda "questo oggetto è già noto?". Si calcola l'impronta crittografica del file (SHA-256) e la si cerca in un elenco. È il metodo con meno falsi positivi che esista: se l'impronta coincide, il file è quello, senza interpretazioni. Le fonti utili per un nodo Tutanum sono quattro.
- Firme di ClamAV: il database ufficiale, aggiornato da
freshclam. Non è uno scudo per il sistema operativo ma un controllo per ciò che transita: caricamenti, repository, allegati, pacchetti scaricati. - Indicatori di compromissione (IOC): gli hash pubblicati dai feed di threat intelligence (MISP,
MalwareBazaar) e quelli raccolti dal proprio honeypot. ClamAV li accetta
come firme personalizzate, in un file
.hsb. - Regole YARA: non sono hash ma schemi sul contenuto, e reggono alle piccole variazioni che un hash non tollera. ClamAV le carica dalla stessa cartella delle firme.
- Allowlist: l'uso inverso, e su un server il più potente. L'insieme degli eseguibili legittimi
è piccolo e noto (il sistema di base descritto da
mtree, i pacchetti verificabili conpkg check -s): tutto ciò che non vi compare è sospetto per definizione. Su FreeBSDmac_veriexecporta l'idea fino in fondo e rifiuta nel kernel l'esecuzione di ciò che non è in un manifesto firmato, ma richiede un sistema compilato conWITH_VERIEXEC.
Il limite è strutturale: basta cambiare un byte perché l'hash sia un altro. Il malware ricompilato,
impacchettato o generato apposta per un bersaglio non è in nessun elenco, e un attacco che usa solo
programmi già presenti (una shell, fetch, nc: la tecnica detta living off the
land) non introduce alcun file da riconoscere. Contro un avversario mirato, che è quello del
modello di minaccia di Tutanum, l'hash da
solo ferma i passanti e non chi è venuto apposta.
Rilevamento comportamentale
Il rilevamento comportamentale risponde a un'altra domanda: "questa azione è normale per chi la compie?".
Non importa che cosa sia il file, importa che cosa fa il processo. Un server è il terreno ideale, perché
il comportamento legittimo è ripetitivo e stretto: un web server legge file e risponde sulla rete, non
lancia shell e non scrive in /etc. Le sorgenti degli eventi cambiano con il sistema.
- FreeBSD:
auditd(OpenBSM) registra esecuzioni, connessioni e modifiche, e il dispositivo/dev/auditpipele offre in tempo reale. DTrace copre ciò che l'audit non vede. - Linux:
auditdoppure eBPF, con Falco (solo rilevamento) o Tetragon, che può anche uccidere il processo direttamente nel kernel. A questi si affianca LKRG, che verifica a runtime l'integrità del kernel e termina il processo le cui credenziali risultano alterate. È aggirabile per ammissione dei suoi stessi autori, ma costringe a exploit più complessi. - OpenBSD: non ha un sottosistema di audit, ma pledge e unveil sono già un blocco
comportamentale: il processo che esce da quanto ha promesso viene terminato dal kernel e la
violazione finisce nei log. Si aggiunge la contabilità dei processi (
accton,lastcomm).
Le regole che valgono per quasi ogni nodo Tutanum sono poche, e ciascuna corrisponde a una tecnica del catalogo MITRE ATT&CK:
- Shell da servizio (T1059): l'utente di un demone (
www,_tor,i2pd,git,iop) esegue un interprete o uno strumento di rete. - Esecuzione da cartelle scrivibili: un programma parte da
/tmpo/var/tmp. - Persistenza (T1543, T1053, T1098.004): modifiche a
rc.d, a cron o ai fileauthorized_keysda parte di chi non è l'amministratore. - Moduli del kernel (T1547.006): un
kldloadfuori dall'avvio. - Uscita in chiaro (T1048): una jail di servizio tenta una connessione che non passa da Tor o I2P. La registra il firewall, non l'audit.
- Cancellazione delle tracce (T1070): troncamento o rimozione dei log.
Il limite qui è opposto a quello dell'hash: il metodo vede anche ciò che è nuovo, ma sbaglia più spesso. Un amministratore che fa manutenzione somiglia a un intruso, e una regola troppo larga genera falsi positivi fino a essere ignorata. Per scrivere regole portabili conviene il formato libero Sigma.
Perché servono entrambi
I due metodi sbagliano in modi diversi, quindi si correggono a vicenda. L'hash dà certezza sull'identità, il comportamento dà copertura sull'ignoto, e la loro combinazione decide quanto energica deve essere la risposta.
| Hash del file | Comportamento | Verdetto | Risposta automatica |
|---|---|---|---|
| Malevolo noto | Qualsiasi | Critico: nessun dubbio sull'identità | File in quarantena e jail congelata |
| Sconosciuto | Sospetto | Alto: probabile malware nuovo | Jail congelata, file in quarantena |
| Legittimo | Sospetto | Alto: abuso di strumenti di sistema | Jail congelata, il file non si tocca |
| Sconosciuto | Normale | Medio: su un server non dovrebbe esistere | Solo avviso |
| Legittimo | Normale | Nessuno | Nessuna |
La soluzione proposta
L'EDR di Tutanum è fatto di quattro pezzi piccoli, ciascuno sostituibile: un motore a hash (ClamAV con
gli IOC locali), un motore comportamentale (uno script che legge il flusso di audit), un punto in cui i
due verdetti si incontrano e un unico comando, tutanum-edr, che contiene e rilascia.
Quattro principi tengono insieme il disegno.
- La jail è l'unità di contenimento: ogni servizio vive in una jail con un proprio indirizzo. Così "bloccare la minaccia" ha un significato preciso (fermare quella jail e tagliarle la rete) e non costringe a spegnere il nodo.
- In automatico solo ciò che è reversibile: congelare, isolare e mettere in quarantena si possono annullare senza perdite, quindi possono scattare da soli e subito. Cancellare, uccidere e ricostruire non si annullano, quindi li decide una persona.
- I due motori condividono gli eventi: ogni esecuzione vista dall'audit passa anche dal controllo dell'hash, e ogni file segnalato dall'hash viene messo in relazione con la jail che lo ha scritto.
- Tutto resta in casa: nessuna telemetria esterna. Gli eventi vanno al collettore, l'avviso parte sul canale fuori banda descritto in Alerting.
Contenimento immediato
Appena il verdetto è alto o critico, la risposta parte senza attendere nessuno. Le azioni sono quattro e ognuna ha una ragione precisa.
- Congelare, non uccidere: a tutti i processi della jail viene inviato
SIGSTOP, che non può essere intercettato né ignorato. Un processo fermo non cifra, non cancella e non esfiltra, ma la sua memoria resta intatta: chiavi, impianti residenti solo in RAM e connessioni aperte sono ancora lì per l'analisi. Unkilldistruggerebbe proprio le prove migliori. - Isolare la rete: l'indirizzo della jail entra nella tabella
quarantenadi ipfw, che esamina ogni pacchetto e quindi taglia subito anche le connessioni già aperte. Anche se un processo sfuggisse al congelamento, non avrebbe dove andare. La tabella è di ipfw e non di pf perché dal securelevel 2 FreeBSD 15 non accetta più indirizzi nelle tabelle di pf né chiude le connessioni; e perché pf, a differenza di ipfw, lascerebbe proseguire le connessioni stabilite. - Fotografare: un'istantanea ZFS del dataset della jail fissa lo stato del disco in quell'istante. È insieme una prova forense e un punto di ritorno.
- Mettere in quarantena i file: il file segnalato viene spostato in un dataset montato con
exec=off, con permessi azzerati e accanto una scheda che ne ricorda percorso, proprietario, permessi, hash e motivo. Non può più essere eseguito, ma non è perduto.
Va detto con onestà che su FreeBSD questa risposta arriva dopo l'evento: l'audit registra una
chiamata di sistema già avvenuta, e tra l'evento e il blocco passano alcuni millisecondi. Per questo la
prevenzione non è sostituibile: /tmp montata noexec rende impossibile ciò che
la regola dovrebbe altrimenti inseguire. Su Linux il blocco può invece precedere l'esecuzione, con
clamonacc in modalità OnAccessPrevention o con fapolicyd, entrambi
basati su fanotify.
Rilascio dei falsi positivi
Un sistema che blocca subito sbaglierà, ed è accettabile solo se l'errore costa poco. Il contenimento reversibile serve a questo: un falso positivo provoca una pausa, non una perdita. Il percorso è sempre lo stesso.
- L'avviso arriva con un identificativo: ogni contenimento apre un caso, con la sua scheda.
tutanum-edr elencomostra quelli in attesa. - Si guarda prima di decidere: la scheda dice quale regola è scattata, l'istantanea permette
di ispezionare i file senza toccare la jail,
procstatmostra i processi fermi. - Rilascio: se era un falso positivo,
tutanum-edr rilasciarimette tutto come prima. Per una jail toglie l'indirizzo dalla tabella e inviaSIGCONT: i processi riprendono dal punto esatto in cui erano. Per un file verifica che l'oggetto in quarantena non sia stato alterato, lo riporta al suo percorso con proprietario e permessi originali e ne aggiunge l'hash all'allowlist locale (tutanum.sfp), così che non venga segnalato di nuovo. - Eradicazione: se la minaccia è reale,
tutanum-edr eliminadistrugge la jail, che va poi ricreata da un modello pulito. L'istantanea resta per l'analisi. I segreti che la jail custodiva si considerano bruciati: se era quella di Tor, la chiave dell'onion service va sostituita. L'analisi si svolge dall'host, sull'istantanea, senza mai riavviare la jail compromessa: è la regola che Kicksecure dà per le macchine intere (spegnere, e leggere il disco da un sistema fidato). Se il sospetto riguarda l'host stesso, vale alla lettera: si reinstalla, sapendo che un impianto nel firmware sopravvive anche a quello.
Ogni rilascio è anche una correzione: la regola che ha sbagliato va ristretta con un'eccezione precisa,
mai allargata con un'esenzione generica. Per i verdetti di gravità media si può prevedere il rilascio a
tempo: ogni voce porta come valore l'ora di inserimento, e un compito di cron toglie quelle
più vecchie di un'ora (lo stesso schema delle esche, più sotto). I
casi chiusi non si cancellano: restano come registro di chi ha rilasciato che cosa e quando.
Se è compromesso l'host
Il contenimento descritto sopra presume che l'host sia sano e che a cadere sia una jail. Se cade l'host non c'è più nessuno di cui fidarsi, e si applica la procedura di ripristino di Whonix, che parte da un principio: l'hardware è sacrificabile, i dati no.
- Tutto ciò che era collegato è compromesso: la macchina, i dischi, le periferiche. Si dà per scontato che ogni dato sia stato copiato e possa essere stato alterato.
- La macchina non torna più in rete: si usa soltanto per recuperare i dati, letti da un sistema pulito.
- Si riparte da hardware nuovo: acquistato in contanti, perché un impianto nel firmware sopravvive alla reinstallazione.
- Si cambia ciò che la macchina conosceva: chiavi degli onion service e delle destinazioni I2P, chiavi SSH, password, e la password della rete locale.
- I dati recuperati sono sospetti: riportarli senza precauzioni su un sistema pulito rischia di infettarlo di nuovo. Si recuperano solo i dati, mai gli eseguibili, e si controllano contro le copie di backup precedenti alla compromissione.
Whonix distingue poi il caso in cui a cadere è solo il gateway di Tor: chi lo controlla legge il traffico onion e toglie l'anonimato, ma per entrare negli altri compartimenti gli serve una seconda vulnerabilità. È lo stesso ragionamento che giustifica una jail separata per Tor.
In pratica su FreeBSD
Quanto segue è uno scheletro funzionante da adattare, non un prodotto: poche decine di righe di shell
che si leggono in dieci minuti, ed è questo il loro pregio. I percorsi presumono le jail sotto
/jails, con i dataset in zroot/jails.
1. Attivare l'audit
# /etc/security/audit_control: cosa registrare
dir:/var/audit
flags:lo,aa,ex,pc,nt,fm # login, autenticazione, exec, processi, rete, modifica attributi
naflags:lo,aa
policy:cnt,argv # argv: anche gli argomenti dei comandi eseguiti
minfree:5
filesz:2M
expire-after:10M
# /etc/security/audit_user: più dettaglio sugli utenti dei servizi (creazione e cancellazione di file)
www:ex,nt,fc,fd:no
_tor:ex,nt,fc,fd:no
sysrc auditd_enable=YES && service auditd start
praudit -l /dev/auditpipe # il flusso in tempo reale, un evento per riga
2. Il motore a hash
FreeBSD non ha la scansione all'accesso, quindi il controllo avviene in due punti: ai confini, con una scansione frequente delle cartelle in cui entrano file dall'esterno, e all'esecuzione, dentro la sentinella del passo 5.
pkg install clamav jq torsocks
sysrc clamav_clamd_enable=YES # niente clamav_freshclam_enable: il demone uscirebbe senza Tor, e pf lo ferma
# /usr/local/etc/tor/torsocks.conf: il SOCKS della jail tor
TorAddress 10.0.0.2
TorPort 59353
torsocks freshclam # firme ufficiali (firmate), senza rivelare quando ci si aggiorna
# clamd gira come utente "clamav", mai come root: --fdpass gli passa i file già aperti
# IOC locali: un hash SHA-256 per riga (feed MISP, MalwareBazaar, payload raccolti dall'honeypot)
# convertiti in firme ClamAV. "*" = dimensione qualsiasi, 73 = livello minimo del motore.
# Con l'elenco vuoto il file non si scrive: clamd rifiuta un .hsb vuoto ("Malformed database",
# provato) e non parte.
sort -u -o /var/db/ioc/sha256.txt /var/db/ioc/sha256.txt
if [ -s /var/db/ioc/sha256.txt ]; then
awk '{ print $1 ":*:Tutanum.IOC." NR ":73" }' /var/db/ioc/sha256.txt > /var/db/clamav/tutanum.hsb
else
rm -f /var/db/clamav/tutanum.hsb
fi
service clamav_clamd restart # dopo un "clamdscan --reload" le firme nuove valgono solo a ricarica finita
# /usr/local/sbin/tutanum-scansione: i punti d'ingresso, da cron ogni pochi minuti
clamdscan --fdpass --multiscan --infected --no-summary /jails/*/var/upload /jails/forge/var/db/repo |
grep ' FOUND$' |
while IFS= read -r riga; do # formato: "/percorso/file: Nome.Firma FOUND"
tutanum-edr quarantena "${riga%%: *}" "hash: ${riga#*: }"
done
3. Quarantena e regole del firewall
# dataset della quarantena: ciò che contiene non può essere eseguito
zfs create -o exec=off -o setuid=off -o mountpoint=/var/quarantena zroot/quarantena
chmod 700 /var/quarantena && mkdir -m 700 /var/quarantena/chiusi
# /etc/ipfw.rules (già presente): prima di qualsiasi "allow"
ipfw -q table quarantena create type addr
ipfw -q add 50 deny log ip from 'table(quarantena)' to any not layer2
ipfw -q add 51 deny log ip from any to 'table(quarantena)' not layer2
Le regole valgono per ogni interfaccia, quella delle jail compresa. Provato su FreeBSD 15.1: una connessione già aperta tra due jail continua a passare dopo l'inserimento nella tabella di pf, e si ferma all'istante dopo quello nella tabella di ipfw.
4. Contenere e rilasciare: tutanum-edr
#!/bin/sh
# /usr/local/sbin/tutanum-edr: contenimento reversibile, rilascio, eradicazione
set -eu
Q=/var/quarantena
nota() { logger -p security.alert -t tutanum-edr "$*"; }
val() { sed -n "s/^$1=//p" "$Q/$id/caso"; }
nuovo() { id=$(date -u +%Y%m%dT%H%M%SZ)-$$; mkdir -m 700 "$Q/$id"; }
case "${1:-}" in
congela) # congela <jail> <motivo>
jail=$2; motivo=$3
ip=$(jls -j "$jail" ip4.addr)
ipfw table quarantena lookup "$ip" >/dev/null 2>&1 && exit 0 # già contenuta: nessun doppione
nuovo
pkill -STOP -j "$jail" || true # 1. processi fermi (SIGSTOP non si intercetta)
ipfw -q table quarantena add "$ip" "$(date +%s)" # 2. niente rete, connessioni aperte comprese
zfs snapshot -r "zroot/jails/$jail@caso-$id" # 3. istantanea: prova e punto di ritorno
printf 'tipo=jail\njail=%s\nip=%s\nmotivo=%s\n' "$jail" "$ip" "$motivo" > "$Q/$id/caso"
nota "CONTENUTO id=$id jail=$jail motivo=$motivo" ;;
quarantena) # quarantena <file> <motivo>
f=$2; motivo=$3; nuovo
printf 'tipo=file\npercorso=%s\nproprietario=%s\nmodo=%s\nsha256=%s\nmotivo=%s\n' \
"$f" "$(stat -f %u:%g "$f")" "$(stat -f %Lp "$f")" "$(sha256 -q "$f")" "$motivo" > "$Q/$id/caso"
mv "$f" "$Q/$id/oggetto"; chmod 000 "$Q/$id/oggetto"
nota "QUARANTENA id=$id file=$f motivo=$motivo" ;;
elenco) # i casi aperti, in attesa di una decisione
for c in "$Q"/2*/caso; do [ -e "$c" ] && { echo "== ${c%/caso}"; cat "$c"; }; done ;;
rilascia) # rilascia <id>: era un falso positivo, si torna allo stato di partenza
id=$2
if [ "$(val tipo)" = file ]; then
[ "$(sha256 -q "$Q/$id/oggetto")" = "$(val sha256)" ] || { echo "oggetto alterato" >&2; exit 1; }
mv "$Q/$id/oggetto" "$(val percorso)"
chown "$(val proprietario)" "$(val percorso)"; chmod "$(val modo)" "$(val percorso)"
echo "$(val sha256):*:Tutanum.Rilasciato.$id:73" >> /var/db/clamav/tutanum.sfp # allowlist
grep -v "^$(val sha256)\$" /var/db/ioc/sha256.txt > /var/db/ioc/sha256.tmp || true
mv /var/db/ioc/sha256.tmp /var/db/ioc/sha256.txt
clamdscan --reload
else
ipfw -q table quarantena delete "$(val ip)"
pkill -CONT -j "$(val jail)" || true
fi
nota "RILASCIATO id=$id da=${SUDO_USER:-${DOAS_USER:-root}}"
mv "$Q/$id" "$Q/chiusi/$id.rilasciato" ;;
elimina) # elimina <id>: minaccia confermata. Irreversibile, quindi mai automatico.
id=$2
if [ "$(val tipo)" = file ]; then rm -f "$Q/$id/oggetto"
else jail -r "$(val jail)"; fi # l'istantanea resta per l'analisi
nota "ELIMINATO id=$id da=${SUDO_USER:-${DOAS_USER:-root}}"
mv "$Q/$id" "$Q/chiusi/$id.eliminato" ;;
*) echo "uso: tutanum-edr congela|quarantena|elenco|rilascia|elimina" >&2; exit 64 ;;
esac
5. La sentinella: comportamento e hash sullo stesso flusso
#!/bin/sh
# /usr/local/sbin/tutanum-sentinella: regole di comportamento sul flusso di audit,
# con il controllo dell'hash su ogni eseguibile lanciato dagli utenti dei servizi.
MODO=${MODO:-avviso} # "avviso" finché le regole non sono rodate, poi "blocco"
IOC=/var/db/ioc/sha256.txt
# stdbuf: in una pipe praudit scrive a blocchi di 4 KB, e senza un flusso intenso di eventi
# la sentinella li riceverebbe con minuti di ritardo (provato)
stdbuf -o L praudit -l /dev/auditpipe | awk -F, '
{ utente = ""; pid = ""; file = ""; regola = ""
for (i = 1; i <= NF; i++) if ($i ~ /^subject/) { utente = $(i+2); pid = $(i+6); break }
for (i = 1; i <= NF; i++) if ($i == "path") file = $(i+1) # ultimo "path": percorso risolto
servizio = (utente ~ /^(www|_tor|_i2pd|git|iop|gestore|cowrie)$/) # i2pd gira come _i2pd
if ($4 ~ /^execve/) {
if (file ~ /^\/(tmp|var\/tmp)\//) regola = "exec-da-tmp"
else if (servizio && file ~ /\/(sh|csh|tcsh|nc|fetch|ftp)$/) regola = "shell-da-servizio"
else if (servizio) regola = "exec"
}
else if ($4 ~ /^kldload/) regola = "modulo-kernel"
else if (servizio && $4 ~ /^(chmod|fchmod|chflags)/ && file ~ /\/(etc|rc\.d|\.ssh)\//)
regola = "persistenza"
if (regola != "" && pid != "") { print regola, pid, file; fflush() }
}' | while read -r regola pid file; do
jail=$(ps -o jid= -p "$pid" 2>/dev/null | tr -d ' ')
[ -n "$jail" ] || continue # processo già terminato
# nell'audit il percorso è già quello visto dall'host (/jails/jails/web/bin/sh, provato):
# la radice della jail si antepone solo se il file così non esiste
f=$file; [ "$jail" != 0 ] && [ ! -e "$f" ] && f=$(jls -j "$jail" path)$file
noto=0 # motore a hash: l'eseguibile è un IOC?
hash=$(sha256 -q "$f" 2>/dev/null) || hash=""
[ -n "$hash" ] && grep -qxF "$hash" "$IOC" && noto=1
[ "$regola" = exec ] && [ "$noto" = 0 ] && continue # esecuzione ordinaria: nessun verdetto
logger -p security.alert -t tutanum-edr \
"RILEVATO regola=$regola hash_noto=$noto pid=$pid jail=$jail file=$file"
[ "$MODO" = blocco ] || continue
if [ "$jail" = 0 ]; then kill -STOP "$pid" # sull'host si ferma il solo processo
else tutanum-edr congela "$(jls -j "$jail" name)" "$regola"; fi # il nome, non il JID
[ "$noto" = 1 ] && tutanum-edr quarantena "$f" "hash noto: $hash"
done
La sentinella parte in modalità avviso. Si lascia girare qualche settimana, si
restringono le regole che scattano a vuoto e solo allora si passa a MODO=blocco.
PoC di verifica: Si provano i due motori e il rilascio senza usare malware vero.
# 1. Motore a hash: un file innocuo il cui hash viene dichiarato malevolo
echo "prova tutanum" > /jails/web/var/upload/prova.bin
sha256 -q /jails/web/var/upload/prova.bin >> /var/db/ioc/sha256.txt
# si rigenera tutanum.hsb come sopra, poi:
tutanum-scansione
ls /jails/web/var/upload/prova.bin # -> No such file: è in quarantena
tutanum-edr elenco # -> tipo=file, percorso, sha256, motivo
# 2. Motore comportamentale: l'utente del web server lancia una shell
MODO=blocco tutanum-sentinella &
jexec -U www web /bin/sh -c 'sleep 300'
ipfw table quarantena list # -> l'indirizzo della jail web
ps -J web -o pid,state,command # -> stato T: processi fermi, non terminati
zfs list -t snapshot | grep caso- # -> l'istantanea del momento
# 3. Rilascio: entrambi i casi erano prove, quindi falsi positivi
tutanum-edr rilascia 20261004T101500Z-4242
ps -J web -o pid,state,command # -> di nuovo in esecuzione
grep Rilasciato /var/db/clamav/tutanum.sfp
Da EDR a XDR
L'XDR non è un altro prodotto: è la stessa logica applicata a più sorgenti. In Tutanum le sorgenti esistono già e confluiscono nel collettore, quindi basta scrivere le regole che le incrociano. Ogni riga qui sotto unisce due segnali che da soli direbbero poco.
- Rete ed endpoint: pf registra un tentativo di uscita in chiaro da una jail di servizio. La jail viene congelata anche se l'audit non ha visto nulla di strano.
- Honeypot ed endpoint: l'esca viene toccata da un indirizzo interno. Nessun processo legittimo ha motivo di farlo, quindi la jail da cui parte il contatto è compromessa.
- Honeypot e autenticazione: un indirizzo già visto dall'esca completa un accesso su un servizio reale. È l'allarme più grave: le credenziali sono in mano a chi stava scandagliando.
- Integrità ed endpoint: AIDE o
mtreesegnalano un binario di sistema cambiato fuori da un aggiornamento. Il suo nuovo hash entra tra gli IOC e ogni jail che lo esegue viene contenuta. - Più nodi: in una federazione Tutanum gli IOC raccolti da un nodo (hash, indirizzi) si distribuiscono agli altri come commit firmati, senza alcun server centrale: è il compito di iop, descritto qui sotto.
La prima regola, per esempio, si realizza leggendo l'interfaccia di log di pf:
# /etc/pf.conf: le jail dei servizi parlano solo con la jail di Tor, mai con l'esterno
block drop log quick on em0 from <jail_servizi> to any
# /usr/local/sbin/tutanum-uscite: un tentativo di uscita in chiaro congela la jail che lo compie
tcpdump -nli pflog0 'src net 10.0.0.0/24' 2>/dev/null |
awk '{ sub(/\.[0-9]+$/, "", $3); print $3; fflush() }' |
while read -r ip; do
jail=$(jls | awk -v ip="$ip" '$2 == ip { print $1 }')
[ -n "$jail" ] && tutanum-edr congela "$jail" "uscita-in-chiaro"
done
Integrare iop
iop non è un forge: è lo strumento che permette di farne a meno. Condivide tra i nodi, attraverso I2P, qualunque insieme di file tracciato con git, senza alcun server di repository (è presentato in Forge proprio come alternativa ai server centrali). La divisione dei compiti è semplice. Il server di repository resta la scelta giusta per i dispositivi della propria rete, che da lì si aggiornano. iop serve dove quel server non arriva: tra server ridondati che stanno su reti diverse, per i dispositivi che si portano fuori casa e, più in generale, come alternativa a BitTorrent quando ciò che si distribuisce deve essere versionato e tracciato. Poiché trasporta file e non soltanto codice, in questo disegno entra in tre ruoli diversi.
- Come servizio da sorvegliare: il demone gira in una jail propria con l'utente
iope ricade nelle stesse regole degli altri. La sua politica fail-closed semplifica il lavoro: conforce_i2pattivo iop non parla mai in chiaro, quindi qualunque uscita in chiaro dalla sua jail è un'anomalia senza eccezioni.iop doctoresce con un codice di errore se un controllo critico fallisce, e va eseguito a intervalli. - Come sensore: il demone registra i propri eventi di rete in
monitor.jsone solleva avvisi a soglia: un picco di messaggi rifiutati (sondaggio o flood), connessioni da destinazioni non seguite (scansione), bridge SAM perso più volte, panic contenuti. Per scelta osserva e non blocca, quindi è una sorgente ideale per il collettore. Quel file elenca però le destinazioni dei pari: è materiale di correlazione e non deve lasciare il nodo. - Come canale: l'elenco degli IOC è un file tracciato con git, quindi diventa un progetto iop come qualunque altro, e lo stesso vale per le regole della sentinella e le configurazioni condivise. Ogni aggiornamento è un commit firmato con la chiave ed25519 del nodo che lo pubblica, viaggia nei tunnel I2P e ogni oggetto ricevuto viene verificato ricalcolandone l'identificativo. Nessun nodo vede l'indirizzo IP degli altri, e non esiste un server che possa essere sequestrato o spento. Un progetto con visibilità privata non viene annunciato e viene servito solo ai suoi delegati, cioè ai nodi il cui did il proprietario ha aggiunto a mano al documento del progetto.
# sensore: gli eventi del demone iop entrano nel collettore
iop monitor --follow | logger -p security.notice -t iop-monitor &
# crontab: controllo periodico della configurazione, esce con 1 se un controllo critico fallisce
*/30 * * * * iop doctor >/dev/null 2>&1 || logger -p security.alert -t iop-doctor "controllo critico fallito"
# canale: nodo A, che pubblica gli IOC in un progetto privato
iop project init ~/.iop/storage/ioc --name ioc --description "IOC della federazione" --private
cp /var/db/ioc/sha256.txt ~/.iop/storage/ioc/
iop project commit ~/.iop/storage/ioc -m "IOC del 2026-10-04" # commit firmato
iop daemon # privato: non viene annunciato
# nodo B, che li riceve: comunica ad A il proprio did, fuori banda
iop id
# nodo A: aggiunge il did di B in coda a "delegates" in ~/.iop/storage/ioc/.iop/project.json
# (il primo elemento resta il did di A, da cui deriva l'id del progetto; non serve un commit)
# e passa a B, sempre fuori banda, la propria destinazione e il tip:
iop i2p destination
git -C ~/.iop/storage/ioc rev-parse HEAD
# nodo B: "iop project clone" vale solo per i progetti pubblici, quindi la copia vuota si prepara a mano
mkdir -p ~/.iop/storage/ioc/.iop
git init -q ~/.iop/storage/ioc
# ~/.iop/storage/ioc/.iop/project.json con "delegates": ["<DID_A>"] e "visibility": "private"
iop project fetch aB3f...xyz.b32.i2p ioc --tip 4c1e9a... # poi, da cron, a ogni nuovo tip
# allowlist locale: gli hash di tutto ciò che il nodo esegue legittimamente
find /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin -type f -exec sha256 -q {} + \
| sort -u > /var/db/ioc/allowlist.txt
# un IOC ricevuto da un altro nodo non può mai colpire ciò che è nell'allowlist
grep -vxF -f /var/db/ioc/allowlist.txt ~/.iop/storage/ioc/sha256.txt >> /var/db/ioc/sha256.txt
La visibilità privata va presa per quello che è. Il nodo che serve il progetto riconosce un delegato dal did che questi dichiara aprendo la connessione, e quella dichiarazione non è firmata: chi conoscesse il did di un delegato, il nome del progetto e il tip potrebbe presentarsi al suo posto. Per gli IOC il danno è contenuto, perché non sono segreti e la loro autenticità non dipende da chi li scarica ma dalla firma dei commit e dalla verifica di ogni oggetto. Resta la regola: in un progetto privato non si mettono segreti.
L'ultima riga conta più delle altre. Un nodo della federazione può essere compromesso e pubblicare come
"malevolo" l'hash di /bin/sh: senza il filtro, ogni nodo metterebbe in quarantena la propria
shell. Gli indicatori ricevuti sono dati di terzi, e non possono mai prevalere sull'allowlist
locale.
Limiti
- Il silenzio non è una prova: come ricorda la documentazione di Kicksecure, nessuno strumento può dimostrare che un sistema è pulito. Un avversario mirato prova i propri strumenti contro queste stesse regole prima di usarli. L'EDR alza il costo dell'attacco e accorcia il tempo di scoperta, non di più.
- Chi controlla il kernel acceca l'EDR: tutto questo gira in spazio utente. Contro un rootkit nel kernel valgono il securelevel, l'avvio verificato e l'invio dei log fuori dal nodo, non la sentinella.
- I processi brevi sfuggono: la sentinella risale alla jail dal PID, e un processo che termina in pochi millisecondi non c'è già più. L'evento resta nel registro di audit, ma il blocco non scatta. Dove ogni utente di servizio vive in una sola jail, si può risalire alla jail dall'utente.
- Il formato a righe di praudit è ambiguo: percorsi e argomenti contenenti virgole possono
confondere l'analisi e un intruso può sfruttarlo. Per un uso serio si legge l'uscita XML
(
praudit -x) o il formato binario con libbsm. - Il blocco automatico è un'arma a doppio taglio: chi sa quali regole scattano può provocarle apposta per fermare un servizio. Perciò il contenimento agisce sulla singola jail, mai sull'host o sull'accesso di amministrazione, e i falsi positivi si rilasciano con un comando.
- L'EDR è software, quindi superficie d'attacco: va tenuto piccolo, leggibile e sotto controllo d'integrità come tutto il resto.
Honeypot
Un honeypot è un'esca: una risorsa che non ha alcun motivo legittimo di essere toccata. Il suo valore sta tutto in questa proprietà. Un IDS deve distinguere il traffico ostile in mezzo a quello normale e quindi sbaglia; l'esca non ha traffico normale, perciò ogni contatto è già un segnale, quasi senza falsi positivi. È il sensore con il miglior rapporto tra informazione e rumore che un nodo possa avere, ed è anche quello che più facilmente si ritorce contro chi lo installa male.
Tipi di esca
Le esche si distinguono per quanto lasciano fare all'intruso: più interazione significa più informazione, ma anche più rischio e più manutenzione.
| Tipo | Che cosa fa | Strumenti | Per Tutanum |
|---|---|---|---|
| Honeytoken | Un dato finto (chiave, file, account) che avvisa quando viene usato | Nessuno: bastano SSH, audit e pf | Sempre: costo quasi nullo |
| Tarpit | Non emula nulla, fa solo perdere tempo ai bot | endlessh | Sì: minuscolo e in stile suckless |
| Bassa interazione | Apre porte finte e registra chi bussa | OpenCanary, honeyd, dionaea | Utile sulla rete interna |
| Media interazione | Emula una shell e registra credenziali, comandi e file scaricati | cowrie | Sì, in una jail isolata |
| Alta interazione | Un sistema vero lasciato compromettere | Macchine virtuali dedicate | No: è un mestiere a tempo pieno |
| Suite | Decine di honeypot orchestrati in container | T-Pot | No: pesante e non verificabile, contro il KISS |
Dove collocarla
La stessa esca dà risposte diverse a seconda di dove la si mette, e la scelta dipende da che cosa si vuole sapere.
- Verso l'interno (rete delle jail, LAN domestica): è la collocazione che vale di più. Qui il rumore di fondo è zero, quindi un contatto significa che qualcosa dentro il perimetro sta esplorando: un servizio compromesso o un dispositivo infetto in casa. È un allarme di compromissione, non una statistica.
- Verso Internet in chiaro: raccoglie migliaia di contatti al giorno, quasi tutti di bot. Serve a costruire liste di blocco e a raccogliere IOC, non ad accorgersi di un attacco mirato. Ha un costo che per Tutanum pesa: un indirizzo domestico che risponde sulla porta 22 è più visibile di uno che scarta tutto in silenzio, e i motori di scansione catalogano gli honeypot riconoscibili. Un nodo che vuole restare invisibile può legittimamente rinunciarvi.
- Dietro un onion service: qui le connessioni arrivano tutte dal demone Tor locale, quindi non esiste un indirizzo sorgente da bloccare. L'esca resta utile per ciò che registra (credenziali tentate, comandi, strumenti), ma la risposta non può essere una tabella di pf: è un avviso, e la difesa è quella anti-DoS del servizio.
- Su I2P: il servizio vede la destinazione crittografica di chi si connette, che non si può falsificare ma si può rigenerare a costo zero. Bloccare le destinazioni ostili serve dunque a poco, mentre funziona il contrario: ammettere solo quelle note. È ciò che fa iop, il cui monitor segnala come possibile scansione ogni connessione da una destinazione non seguita. Su una rete di soli pari conosciuti, il nodo stesso è già un'esca per chiunque altro.
Architettura
Le regole sono poche e non negoziabili.
- Una jail tutta sua: nessun file, chiave o volume in comune con i servizi reali, securelevel
massimo, limiti di risorse imposti con
rctl. - Nessuna uscita: l'esca risponde, non chiama mai. Chi riesce a evaderne l'emulazione non deve poterla usare come trampolino verso Internet o verso le altre jail.
- I log si leggono da fuori: l'host legge i file della jail dal proprio filesystem. Non serve alcun canale di rete tra esca e collettore.
- L'SSH vero sta altrove: raggiungibile solo dalla LAN di gestione o come onion service, come descritto in SSH. La porta 22 pubblica appartiene all'esca.
Rischi
- È software esposto di proposito: cowrie è un programma Python che elabora input ostile. Un difetto nel suo codice è un ingresso nella jail, ed è per questo che la jail non deve contenere né poter raggiungere nulla.
- Si riconosce: le configurazioni predefinite sono note (nome host, utenti, versione dichiarata, filesystem finto di cowrie). Un'esca riconosciuta non inganna nessuno e segnala che dietro c'è qualcuno attento. Vanno cambiati tutti i valori predefiniti.
- Il blocco automatico si può rivolgere contro il nodo: un pacchetto SYN ha un mittente
falsificabile. Se ogni tentativo su una porta esca finisse in una tabella di blocco, un avversario
potrebbe far bloccare al nodo il proprio guard di Tor o il proprio resolver. Si blocca in
automatico solo dopo una connessione TCP completata, che non si falsifica, e mai gli indirizzi
della tabella
<mai_bloccare>. - Registra dati di terzi: indirizzi e credenziali tentate sono dati raccolti su altre persone. Vedi Livello legale e giurisdizione.
In pratica su FreeBSD
1. La jail e il firewall
# /etc/jail.conf
esca {
path = /jails/esca;
host.hostname = srv-backup; # un nome credibile, non "honeypot"
ip4.addr = "lo1|10.0.0.66/32";
securelevel = 3;
enforce_statfs = 2;
mount.devfs; devfs_ruleset = 4;
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
}
# limiti di risorse: l'esca non deve poter affamare il nodo (kern.racct.enable=1 in loader.conf)
rctl -a jail:esca:memoryuse:deny=512m
rctl -a jail:esca:maxproc:deny=100
rctl -a jail:esca:pcpu:deny=20
# /etc/pf.conf
esca = "10.0.0.66"
# solo da fuori della LAN: dalla LAN la porta 22 resta quella dell'sshd vero
rdr on em0 inet proto tcp from ! $lan to (em0) port 22 -> $esca port 2222 # cowrie
rdr on em0 inet proto tcp from ! $lan to (em0) port 2222 -> $esca port 2223 # endlessh
block drop log quick from $esca to any # l'esca non apre mai connessioni
pass in on em0 inet proto tcp to $esca port { 2222 2223 } keep state (max-src-conn 4)
# le jail raggiungono l'esca: una jail compromessa che la tocca si tradisce
pass quick on lo1 proto tcp from { $j_tor, $j_i2p, $j_web, $j_iop } to $esca port { 2222, 2223 } keep state
# /etc/ipfw.rules (già presente): le tabelle che cambiano a sistema avviato stanno in ipfw
ipfw -q table esche create type addr
ipfw -q table mai_bloccare create type addr # riempita da /etc/ipfw.mai_bloccare:
# guard di Tor, resolver, computer di amministrazione
ipfw -q add 53 allow tcp from 'table(esche)' to any 22,2222,2223 in via em0 not layer2 # vede solo l'esca
ipfw -q add 54 deny log ip from 'table(esche)' to any in via em0 not layer2
2. Il tarpit: endlessh
Prima che il server SSH invii la propria versione, il protocollo gli consente di mandare righe di
testo arbitrarie. endlessh ne manda una ogni dieci secondi, per sempre: il bot resta
appeso per ore e nel frattempo non scansiona altro. Non emula nulla, quindi non ha nulla da
sbagliare.
# dall'host: la jail esca non esce su Internet (vedi Tutanum Classico, livello 4)
doas pkg -C /usr/local/etc/pkg.conf -r /jails/jails/esca install endlessh
doas jexec esca service ldconfig start
# /usr/local/etc/endlessh.config (nella jail)
Port 2223
Delay 10000 # una riga di banner ogni 10 secondi
MaxLineLength 32
MaxClients 512 # oltre questo numero i nuovi client vengono rifiutati
LogLevel 1
BindFamily 4
# lo script rc legge endlessh_config (predefinito: endlessh.conf), non i flag (provato)
doas jexec esca sysrc endlessh_enable=YES endlessh_config=/usr/local/etc/endlessh.config
doas jexec esca service endlessh start
doas sockstat -4l -j esca # -> endlessh su 10.0.0.66:2223
3. La shell finta: cowrie
cowrie accetta le credenziali che decide di accettare, presenta una shell emulata e registra ogni
comando e ogni file scaricato. Si installa nella jail come utente non privilegiato seguendo la
documentazione ufficiale. Ciò che conta è togliere i valori
predefiniti: nome host, versione dichiarata, elenco degli utenti (etc/userdb.txt) e
filesystem finto. Il pacchetto di FreeBSD (cowrie 3.0.14, provato su FreeBSD 15.1 a ottobre 2026)
non parte così com'è (TypeError: type 'ClientFactory' is not subscriptable): cowrie
richiede Twisted 26.4, treq 26.7 e pyasn1-modules 0.4.2, mentre i port forniscono versioni più vecchie.
La via provata usa il pacchetto per le dipendenze già compilate (cryptography, bcrypt) e aggiunge in un
ambiente virtuale soltanto le librerie in Python puro che mancano, scaricate dall'host attraverso Tor:
la jail non esce, e nell'ambiente si installa da una cartella locale. Il tarpit endlessh,
dai pacchetti, non ne dipende.
# dall'host: le dipendenze compilate dai pacchetti, nella jail
doas pkg -C /usr/local/etc/pkg.conf -r /jails/jails/esca install cowrie
doas jexec esca service ldconfig start
doas jexec esca pw useradd cowrie -m -s /usr/sbin/nologin
doas jexec -U cowrie esca python3.12 -m venv --system-site-packages /home/cowrie/cowrie-env
doas jexec -U cowrie esca mkdir /home/cowrie/wheels
# dall'host, attraverso Tor: le sole librerie in Python puro che servono
doas pkg install py312-pip py312-pysocks
doas python3.12 -m pip download --proxy socks5h://10.0.0.2:59353 --no-deps \
-d /jails/jails-data/esca-data/home/cowrie/wheels \
"cowrie==3.0.14" "twisted[conch]>=26.4" "treq>=26.7" "pyasn1-modules>=0.4.2" multipart setuptools
doas pkg delete -y py312-pip py312-pysocks
# nella jail, senza rete
doas jexec -U cowrie esca /home/cowrie/cowrie-env/bin/pip install --no-index --find-links /home/cowrie/wheels \
"twisted[conch]>=26.4" "treq>=26.7" "pyasn1-modules>=0.4.2"
doas jexec -U cowrie esca /home/cowrie/cowrie-env/bin/pip install --no-index --find-links /home/cowrie/wheels \
--ignore-installed --no-deps "cowrie==3.0.14" # il plugin di twistd deve stare nell'ambiente
# avvio, dalla cartella che contiene etc/cowrie.cfg e var/
doas jexec -U cowrie esca mkdir -p /home/cowrie/cowrie/etc /home/cowrie/cowrie/var/log/cowrie \
/home/cowrie/cowrie/var/run /home/cowrie/cowrie/var/lib/cowrie/downloads /home/cowrie/cowrie/var/lib/cowrie/tty
doas jexec -U cowrie esca sh -c 'cd /home/cowrie/cowrie && /home/cowrie/cowrie-env/bin/twistd \
--umask=0022 --pidfile=var/run/cowrie.pid --logfile=var/log/cowrie/cowrie.log cowrie'
# a ogni avvio della jail: /etc/rc.local (nella jail)
su -m cowrie -c 'cd /home/cowrie/cowrie && /home/cowrie/cowrie-env/bin/twistd --umask=0022 \
--pidfile=var/run/cowrie.pid --logfile=var/log/cowrie/cowrie.log cowrie'
# etc/cowrie.cfg (nella jail, utente non privilegiato "cowrie")
[honeypot]
hostname = srv-backup
[ssh]
listen_endpoints = tcp:2222:interface=10.0.0.66
version = SSH-2.0-OpenSSH_10.0 FreeBSD-20250801 # quello di un FreeBSD 15.1 vero: un banner datato tradisce l'esca
[telnet]
enabled = false
[output_jsonlog]
enabled = true
logfile = ${honeypot:log_path}/cowrie.json
4. Dai log alle difese
È il passo che trasforma l'esca da curiosità in sensore. Lo script distingue i due casi del diagramma: la sorgente esterna viene tagliata fuori da tutti i servizi reali, la sorgente interna fa scattare il contenimento dell'EDR.
#!/bin/sh
# /usr/local/sbin/tutanum-esca: dai log dell'esca alle difese. Gira sull'host, non nella jail.
BASE=/jails/esca/home/cowrie/cowrie/var
tail -F "$BASE/log/cowrie/cowrie.json" |
jq --unbuffered -r 'select(.eventid == "cowrie.session.connect") | .src_ip' |
while read -r ip; do
[ "$ip" = 10.0.0.66 ] && continue # l'esca stessa (prove dall'host)
ipfw table mai_bloccare lookup "$ip" >/dev/null 2>&1 && continue # mai tagliarsi fuori da soli
jail=$(jls ip4.addr name | awk -v ip="$ip" '$1 == ip { print $2 }') # il nome, non il JID:
if [ -n "$jail" ]; then # congela ne ricava il dataset
tutanum-edr congela "$jail" "contatto-con-esca" # sorgente interna: compromissione certa
else
ipfw -q table esche add "$ip" "$(date +%s)" # sorgente esterna: fuori da tutto il resto
fi
logger -p security.alert -t tutanum-esca "CONTATTO ip=$ip jail=${jail:-esterna}"
done
# crontab di root
# i blocchi scadono dopo una settimana: gli indirizzi cambiano proprietario
# (il valore di ogni voce è l'ora di inserimento)
0 * * * * ipfw table esche list | awk -v l=$(( $(date +\%s) - 604800 )) '$2 < l { print $1 }' | xargs -n1 ipfw -q table esche delete
# i payload scaricati dagli intrusi (cowrie li salva con il loro SHA-256 come nome) diventano IOC
*/10 * * * * ls /jails/esca/home/cowrie/cowrie/var/lib/cowrie/downloads >> /var/db/ioc/sha256.txt
5. Honeytoken: l'esca senza honeypot
Per un nodo singolo sono lo strumento con il miglior rendimento: nessun servizio in più, nessuna superficie d'attacco, e scattano solo quando qualcuno è già dentro.
# 1. Chiave esca. La parte privata si lascia dove un intruso la cercherebbe:
ssh-keygen -t ed25519 -N "" -C "backup@srv-backup" -f /root/esca
install -m 600 /root/esca /jails/web/root/.ssh/id_ed25519_backup && rm /root/esca
# quella pubblica autorizza un account che non serve a nulla, con un comando forzato:
pw useradd backup -m -s /bin/sh -c "Backup operator"
# ~backup/.ssh/authorized_keys
restrict,command="logger -p security.alert -t tutanum-esca CHIAVE-ESCA-USATA da=${SSH_CONNECTION%% *}" ssh-ed25519 AAAA... backup@srv-backup
# 2. File esca: nessun processo legittimo lo apre mai.
# Linux:
auditctl -w /root/backup-chiavi.kdbx -p r -k esca
# FreeBSD (DTrace, percorso assoluto):
dtrace -qn 'syscall::open:entry /copyinstr(arg0) == "/root/backup-chiavi.kdbx"/,
syscall::openat:entry /copyinstr(arg1) == "/root/backup-chiavi.kdbx"/
{ printf("ESCA-APERTA pid=%d uid=%d exe=%s\n", pid, uid, execname); }' | logger -p security.alert -t tutanum-esca
# 3. Destinazione esca su I2P: un indirizzo che non è pubblicato da nessuna parte, tranne che in
# un file lasciato nella jail da sorvegliare (per esempio tra i pari "seguiti" di iop).
# Chi vi si connette ha letto quel file. /usr/local/etc/i2pd/tunnels.conf:
[esca]
type = server
host = 10.0.0.66
port = 2222
keys = esca.dat
# 4. Porta esca senza alcun software: basta pf. Solo avviso, mai blocco automatico (vedi sotto).
block drop in log quick on em0 proto tcp to port { 23 445 3389 5900 }
Se la chiave esca viene usata, chi la usa ha letto i file della jail in cui era nascosta: quella jail va trattata come compromessa anche se nessun'altra regola è scattata.
PoC di verifica: Si controlla che l'esca registri, che il blocco scatti, che dall'esca non si esca e che il contatto interno congeli la jail giusta.
# da una macchina esterna (o da un indirizzo di prova)
ssh root@nodo.example # qualsiasi password: si entra nella shell finta
# sul nodo
tail -1 /jails/esca/home/cowrie/cowrie/var/log/cowrie/cowrie.json | jq '.eventid, .src_ip'
ipfw table esche list # -> l'indirizzo di prova
nc -zv nodo.example 443 # dall'esterno: ora il servizio reale non risponde più
ipfw table esche delete 203.0.113.7 # rilascio manuale
# l'esca non deve poter uscire
jexec esca nc -zv -w 3 1.1.1.1 443 # -> timeout, e una riga in pflog0
# contatto interno: da una jail di servizio
jexec web nc -z 10.0.0.66 2222
tutanum-edr elenco # -> jail=web motivo=contatto-con-esca
Che cosa fare dei dati
- Liste di blocco: la tabella
eschedi ipfw protegge i servizi reali da chi ha già mostrato le proprie intenzioni. Le voci scadono, perché gli indirizzi cambiano proprietario. - IOC per il motore a hash: i file che gli intrusi scaricano nell'esca sono campioni autentici. I loro hash alimentano l'elenco usato dall'EDR, che così riconosce quegli stessi file se compaiono su un servizio vero.
- Segnali di fuga: se tra le credenziali tentate compare un nome utente che esiste solo sul proprio nodo, o una password realmente in uso, quel dato è uscito da qualche parte. Il confronto va fatto sugli hash, senza mai scrivere le proprie password in un file di confronto.
- Condivisione: gli indicatori raccolti si possono pubblicare verso una comunità MISP o tra i nodi di una federazione, come descritto in MISP e SIEM.
Tutto finisce nel collettore e nell'hub dei servizi, e il contatto interno è uno dei pochi eventi che merita un avviso di gravità massima, immediato e fuori banda.
MISP e SIEM
Un SIEM raccoglie e correla log ed eventi. Non è essenziale, ma è utile. Gli stack completi (Wazuh, lo stack Elastic, Graylog) sono potenti ma pesanti: in ottica KISS spesso basta un syslog centrale (rsyslog o syslog-ng) con regole di correlazione semplici e un instradatore leggero come fluent-bit o Vector, archiviando in un piccolo indice. Il SIEM pieno si adotta solo se serve davvero.
MISP è una piattaforma di threat intelligence per condividere indicatori di compromissione (IOC). Per un nodo domestico ospitare l'intero MISP, una grande applicazione, è sovradimensionato: conviene piuttosto consumarne i feed, convertendo gli IOC nelle forme che il nodo già usa, cioè tabelle di pf per gli IP malevoli, liste di blocco per DNSCrypt per i domini e regole per un IDS come Suricata o Zeek. Così i feed alimentano automaticamente le difese, gli eventi del firewall e degli honeypot alimentano il collettore, e la dashboard mostra mentre l'alerting avvisa.
Alerting
Gli avvisi vanno recapitati su un canale fuori banda e indipendente dal server, con due vincoli che
discendono dai valori del progetto: niente servizi push di terzi (Google, Apple, un server ntfy
pubblico), per non consegnare a un estraneo il fatto stesso che esista un nodo e che qualcosa sia
successo; e nessuna porta in più aperta verso il mondo sul nodo, che resta dietro il firewall
default-deny. Le soluzioni classiche (XMPP, Matrix, ntfy, posta via Tor o I2P) spingono
invece il nodo a connettersi a un server esterno o a riceverne connessioni.
Il disegno adottato rovescia la direzione: il nodo pubblica, il telefono controlla. Un piccolo notificatore sull'host del nodo raccoglie a intervalli regolari i tre flussi che contano: gli allarmi di sicurezza dai log (EDR, sentinella, esca), gli esiti dei controlli di stato e le issue aperte dai servizi di analisi. Vi aggiunge le metriche correnti, e scrive un unico file di stato. Quel file viene servito come servizio nascosto I2P (o onion) in sola lettura, e un'app sul telefono lo scarica attraverso il router I2P del telefono stesso. Nessuno dei due apre connessioni verso l'altro al di fuori di questo: il nodo non conosce il telefono, il telefono raggiunge il nodo solo dentro la rete anonima.
Tre proprietà rendono il canale affidabile anche di fronte a un avversario:
- Autenticità per firma, non per trasporto. Il file di stato è firmato con una chiave Ed25519 che vive sull'host del nodo, fuori dalle jail; la jail che lo serve lo vede in sola lettura e non può falsificarlo. L'app verifica la firma prima di leggere il contenuto, e un file alterato diventa esso stesso l'allarme «firma non valida». Così il servizio esposto può anche essere compromesso senza che si possano iniettare avvisi falsi o sopprimere quelli veri a monte della firma.
- Segnale di vita (heartbeat). Il file porta un contatore che cresce a ogni pubblicazione. L'app misura da quanto tempo quel contatore non avanza con l'orologio del telefono, non con quello del nodo: così un nodo spento, isolato o sequestrato produce silenzio, e il silenzio oltre una soglia è un allarme critico. Misurare il tempo sul telefono impedisce che un file vecchio, rimesso in circolo da un intermediario, venga scambiato per un segno di vita.
- Livelli e deduplica. Gli eventi hanno un livello (critico, informativo, issue); i problemi di stato si annunciano una volta sola per episodio, con un messaggio di ritorno alla normalità quando rientrano, così non si viene sommersi da avvisi ripetuti fino a ignorarli.
Il prezzo di questo disegno è la latenza: il sistema operativo del telefono esegue i controlli in secondo piano non più di una volta ogni quindici minuti circa, e meno spesso in risparmio energetico, quindi un allarme arriva con qualche minuto di ritardo e un silenzio dopo la soglia più un giro. In cambio non c'è nessun intermediario fidato, nessun account, e nessuna porta in ascolto sul nodo. Chi vuole il recapito immediato può aggiungere, in parallelo e non in sostituzione, un XMPP auto-ospitato per i soli eventi critici, accettandone il costo in esposizione.
L'app del telefono è un client minimo: su Android richiede soltanto l'app del router I2P
(i2pd) in esecuzione e il permesso di mostrare notifiche; su iOS il disegno non è
realizzabile, perché il sistema non lascia girare un router I2P in secondo piano. La configurazione
(indirizzo del nodo, chiave pubblica di verifica, soglia del silenzio) si trasferisce una volta con un
codice QR, e l'app chiede conferma mostrando la chiave, da confrontare con quella annotata dal nodo.
SYNwall
SYNwall è un firewall trasparente e senza configurazione che inserisce una one-time password (OTP) dentro i pacchetti TCP e UDP, calcolata da una chiave precondivisa (PSK), dall'orario corrente e, in modalità anti-spoofing, dagli indirizzi IP. Tutto il traffico privo dell'OTP corretta viene scartato in silenzio prima di raggiungere l'applicazione. Usa l'hashing leggero Quark, è pensato per dispositivi a basse risorse ed è un modulo del kernel Linux.
Casi d'uso su Tutanum:
- Servizi di amministrazione invisibili: SSH, la dashboard e l'hub non rispondono, e non si fanno nemmeno rilevare dalle scansioni, a chi non presenta l'OTP. È più robusto del port knocking.
- Collegamenti tra nodi fidati: in una federazione Tutanum (sincronizzazione del mirror dei repository, runner distribuiti) una PSK condivisa fa sì che solo i nodi che la possiedono si parlino.
- Strato di invisibilità: davanti ai pochi servizi che devono restare in ascolto, sopra il firewall default-deny.
Integrazione nei valori del progetto: è software libero, decentralizzato (l'OTP è autosufficiente, non serve un server di autenticazione centrale) e leggerissimo. I limiti vanno detti con onestà: è un modulo del kernel Linux, quindi si applica ai dispositivi client Linux della rete domestica e ai nodi Linux; sul server *BSD, preferito per Tutanum, l'equivalente si ottiene con pf (knocking e overload) già visto nel firewall. Richiede inoltre orologi sincronizzati, il NAT può rompere l'anti-spoofing e l'OTP su UDP vuole il modulo a entrambi i capi.
Un hub dei servizi
Accanto alla dashboard serve un hub: una singola pagina minima che raccoglie e collega tutte le
funzionalità auto-ospitate, cioè metriche, log, nyx per Tor, console di i2pd, forge, avvisi
degli honeypot, stato del collettore e dell'alerting. In linea con suckless e con il KISS è una pagina
statica, o generata da un piccolo script, dove ogni strumento mantiene la propria interfaccia minima e
l'hub si limita ad aggregarne i collegamenti e qualche indicatore di stato, non una piattaforma
monolitica. Si espone come eepsite I2P o onion service e, dove serve, dietro SYNwall. È modulare per
costruzione: ogni tassello è indipendente e sostituibile, e se uno cade gli altri restano.
Estensioni
A livello di memoria di archiviazione sono consigliate le SSD in quanto essendo memorie flash sono anche più
resistenti dei comuni Hard Disk funzionanti invece meccanicamente a dischi magnetici. Le marche consigliate
sono Corsair, WD, Sandisk, Kingston e Samsung. Evitare l'uso di USB e
di microSD per la memoria di archiviazione, in quanto potrebbero corrompersi velocemente a seguito della
ripetuta scrittura di dati, soprattutto se si utilizza un filesystem ZFS, usato di default su sistemi
operativi come FreeBSD. Le SSD NVMe sono buone ma meno affidabili di una SSD, in quanto sprovviste
dell'attacco SATA, che ad oggi rimane il più sicuro, gestibile, scalabile e veloce.
In caso di installazioni da live è consigliato pertanto l'utilizzo di un CD-ROM o di un DVD-R, così che
essendo esenti da sovrascrittura si possa mitigare la possibilità che venga applicato qualche malware. Per
questo motivo potrebbe rendersi utile se non necessario un lettore CD/DVD.
Per una maggiore consistenza dei dati, nelle banche o in organizzazione dove i dati non si devono
cancellare, vengono usati dei nastri magnetici conservati in cassaforti isolate da possibili interferenze
che potrebbero comprometterne i dati; tali nastri in lettura sono lenti, ma offrono un supporto migliore per
quanto riguarda la stesura dei dati. La carta ad ogni modo rimane il metodo più longevo, cui succedono
metodi molto più grezzi, come l'incisione fisica in materiali come il metallo (negli ultimi tempi si parla
di incisioni laser nel quarzo o di strutture utilizzanti il DNA, ma rimangono tutt'oggi soluzioni
sperimentali).
CPU
La maggior parte delle CPU presenta attualmente ancora oggi le vulnerabilità Meltdown o Spectre; esse sono
dovute principalmente ad una cattiva progettazione hardware e software, trascinando il problema anche a
livello del sistema operativo.
Meltdown colpisce principalmente i processori Intel e ARM,
mentre Spectre principalmente sia ARM, che Intel
che AMD ma è più difficile da sfruttare rispetto a Meltdown.
Ad oggi ci sono delle mitigazioni software ma potrebbero non essere sufficienti, per questo sarebbe
meglio
optare per processori con mitigazioni di sicurezza già implementate architetturalmente.
Per sapere se il vostro processore è impattato consultate questa
lista in
formato json (fonte).
Per verificare se sono presenti tali vulnerabilità è possibile utilizzare questo bash script.
Per maggiori informazioni è possibile visitare questo
sito, oppure consultare le documentazioni
ufficiali:
Meltdown e Spectre.
FPGA
Un'FPGA (Field-Programmable Gate Array) è un circuito integrato la cui logica si programma dopo la fabbricazione: invece di eseguire istruzioni come una CPU, se ne descrive direttamente l'hardware con un linguaggio di descrizione (HDL) e lo si configura come si vuole. Per Tutanum è interessante perché permette di costruire logica personalizzata e verificabile senza dipendere solo da CPU generaliste chiuse, con i loro motori di gestione nascosti.
Come è fatta
Un'FPGA è una matrice di blocchi logici configurabili (CLB) collegati da un'interconnessione programmabile (una rete di canali e matrici di commutazione), con blocchi di I/O sul bordo che la connettono ai piedini del chip.
L'elemento base dentro un CLB è la cella logica: una look-up table (LUT), cioè una piccola memoria che realizza qualsiasi funzione booleana dei suoi ingressi, seguita da un flip-flop che ne registra il risultato a ogni colpo di clock. Combinando migliaia di queste celle e instradandole fra loro si ottiene qualunque circuito digitale. Le FPGA moderne aggiungono blocchi dedicati: memorie interne (block RAM), moltiplicatori per il calcolo (DSP) e gestione del clock (PLL).
Dal codice al circuito
Il flusso parte da una descrizione in HDL (Verilog o VHDL). La sintesi la traduce in una rete di celle logiche; il place and route decide quali celle usare e come collegarle sulla matrice; infine si genera il bitstream, il file che configura l'FPGA.
Nelle FPGA più comuni la configurazione vive in celle SRAM ed è volatile: va ricaricata a ogni accensione da una memoria flash esterna, che per questo è un componente da proteggere al pari del resto del sistema.
FPGA e sicurezza per Tutanum
Il vantaggio per un nodo Tutanum è la possibilità di eseguire logica aperta e verificabile: un processore soft core open come un RISC-V (ad esempio NEORV32), acceleratori crittografici dedicati (AES, SHA, generatori di numeri casuali) e isolamento realizzato nell'hardware, senza il motore di gestione nascosto di molte CPU commerciali. Progetti come OpenTitan mostrano la direzione di un hardware di fiducia aperto.
Restano però delle cautele. La fiducia nel silicio non è assoluta: l'FPGA è comunque un chip proprietario e un trojan hardware non è escluso a priori. Inoltre i toolchain e il formato del bitstream sono spesso chiusi (AMD/Xilinx Vivado, Intel/Altera Quartus), il che contrasta con i valori di software libero di Tutanum. Dove possibile conviene quindi scegliere FPGA supportate dai toolchain aperti (Yosys e nextpnr, con Project IceStorm per le Lattice iCE40 e Project Trellis per le ECP5), che rendono l'intera catena ispezionabile, usare soft core open, proteggere il flash di configurazione e, se supportate, attivare cifratura e autenticazione del bitstream.
Smartphone come server Tutanum
È sconsigliato l'utilizzo di dispositivi mobili/embedded come gli smartphone in quanto nella stragrande
maggioranza dei casi si tratta di dispositivi proprietari, senza interruttori hardware, sempre accesi (anche
da spenti),
con la batteria irrimovibile (l'apertura viene fatta solitamente con strumenti specifici e da tecnici
specializzati) e con la capacità di offrire
una possibile triangolazione a causa dei segnali
inviati ai ripetitori telefonici, anche senza SIM.
I telefoni smart sono stati costruiti per raccogliere quanti più dati biometrici possibile, evitare di
usarli come server, il sistema operativo non sarebbe nemmeno ottimizzato: iOS seppur sia molto più prestante
di Android a causa dell'adozione di un microkernel anziché di un kernel monolitico, rimane una scatola nera,
nel senso che seppur possa essere svuotato dagli spyware più conosciuti (questo discorso vale più per
Android che per iOS essendo che è molto più facile farlo per il primo sistema operativo che per il secondo)
non si ha mai la sicurezza di averli rimossi totalmente. Il firmware inoltre è quasi sempre proprietario e
difficilmente risulta modificabile.
Librem e Pinephone potrebbero essere una buona scelta per Tutanum Lieve, seppur siano molto limitati a
livello
di risorse; ciò nonostante presentano interruttori hardware che permettono di disabilitare moduli come il
microfono, il modem del telefono, la fotocamera, la SIM, etc., cosa che li rende i dispositivi mobile del
futuro.
Single Board Computer
Il single board computer più famoso è Raspberry Pi, un piccolo computer che con la versione 5 ha presentato
caratteristiche che lo rendono adatto come piccolo server.
Tuttavia, come riportato dalla FSF, la
board è basata sulla famiglia Broadcom VideoCore 4 e fa utilizzo di driver
proprietari per lo startup.
Nel repository ufficiale è possibile
trovare nella cartella boot 8 firmware ARM in formato ELF senza
alcun
riferimento ad una documentazione o codice che possa permettere di poterne replicare i risultati: start.elf,
start4.elf, start4cd.elf, start4db.elf, start4x.elf, start_cd.elf, start_db.elf e start_x.elf.
Di seguito un'analisi del contenuto di start.elf attuata con
binwalk:
In base ai dati del 2015 (1,
2)
la soluzione migliore rimarrebbe mangOH, ma non risulta ad oggi più
reperibile in quanto deprecato.
Ci sarebbero delle schede con processori RISC-V,
un'architettura open source che ad oggi sta trovando sempre più sviluppatori, ma per un utilizzo
stabile è forse troppo presto per poterne parlare, seppur sviluppi futuri potranno vederla impiegata
per un'implementazione ufficiale anche su Tutanum.
Ad oggi inoltre RISC-V manca di una community italiana, di una documentazione consistente e di una
metodologia di sviluppo consolidata, andando pertanto contro i principi elencati all'inizio.
In termini di sviluppo dei processori, ci si potrebbe dedicare alle CPU FPGA come ZipCPU, ma in giro attualmente non è possibile
trovare alcun prodotto finito.
Progetti come ZipCPU sono ancora in fase embrionale e di per sé il progetto attualmente si propone
solo sulla carta e al massimo tramite emulazione virtuale.
Vi sono poi delle CPU costruire proprio da zero che integrando la documentazione su come poterle
autoprodurre, ad esempio il processore di Sam
Zeelof e il processore di Robert
Elder.
Per chi volesse dedicarsi allo sviluppo delle CPU lascio qui di seguito del materiale di riferimento:
- Per un'introduzione allo studio dei computer: "Architettura dei calcolatori", Andrew Tanenbaum.
- Per iniziare a studiare l'architettura delle CPU consultare questa playlist.
- Riguardo alle reti logiche.
- Riguardo alla progettazione descrittiva delle CPU: Verilog
- Per iniziare con RISC-V: documentazione ufficiale, Wikipedia.
- Soft core RISC-V minimale
A livello pratico, la scelta dell'architettura della CPU risulta ad oggi ardua ed è pertanto necessario
andare per compromessi, soprattutto per quanto riguarda la compatibilità con i sistemi operativi.
Per una scelta della CPU, delle loro possibili evoluzioni future e relativamente alle vulnerabilità note,
consultare questo thread.
Ad oggi non sono molte le soluzioni libere, supportate e con una decente capacità di calcolo.
Tuttavia proponiamo qua una lista di dispositivi clusterizzabili, per potere aumentarne almeno la
capacità
computazionale:
- Banana Pi.
- Pine Rock 64 (potrebbe avere binari nel boot loader).
- Libre-Board Renegade.
- Marvells EspressoBin
Queste sono soluzioni che sono sì libere ma che purtroppo scemano in termini di risorse o potenza di calcolo.
L'unica azienda ad oggi competitiva per la potenza di calcolo, le risorse e l'open source risulta ad oggi
essere Banana Pi.
Qui di seguito vi è l'elenco delle soluzioni più compatibili con il progetto Tutanum:
- Banana Pi BPI-M7 con Rockchip RK3588, con una selezione tra 8, 16 e 32GB RAM e 64 o 128GB eMMC. Rimane ad ora la soluzione più appropriata. In base ad AliExpress, in data 12 marzo 2024, il modello con 8GB di RAM (64GB interni di memoria, gli altri ne hanno 128GB) costa €208,10, quello con 16GB costa €252,76 e quello con 32GB di RAM costa €335,05.
- StarFive VisionFive JH7100 RISC-V Single Board Computer. Come sappiamo l'architettura RISC-V è ancora in fase di sviluppo, pertanto utilizzarla in produzione è attualmente un rischio, seppur possa mitigare a molte vulnerabilità presenti e diffuse oggi nei più comuni processori. Ha dai 4 agli 8 GB di RAM.
- Tutta la serie BPI-M*: BPI-M5, BPI-M6, BPI-M7, BPI-M2S.
Attacchi hardware delle intelligence
Le agenzie di intelligence non si fermano al software: attaccano l'hardware stesso. Le loro tecniche sono in parte pubbliche, grazie alle fughe di notizie del Vault 7 della CIA e del catalogo ANT della NSA, oltre che alla ricerca accademica. Tutanum assume questo avversario e si difende di conseguenza. Qui sotto le tecniche documentate e, per ciascuna, le difese concrete da applicare, con l'atteggiamento più paranoico possibile: dare per scontato che l'avversario abbia già provato, o possa provare, ad arrivare al ferro.
Intercettazione nella catena di fornitura
La tecnica dell'interdiction consiste nell'intercettare l'hardware durante la spedizione, aprirlo, impiantarvi una modifica e richiuderlo, in modo che arrivi al destinatario già compromesso. È una pratica documentata dell'unità TAO della NSA.
Difesa: acquistare di persona e localmente, da fornitori scelti a caso e non riconducibili, evitando consegne tracciabili al proprio indirizzo; preferire l'autoproduzione (single board computer, FPGA con toolchain aperti); usare imballi a prova di manomissione e ispezionare, pesare e fotografare ogni componente alla ricezione, confrontandolo con le specifiche ufficiali.
PoC di verifica: creare una "fotografia" dell'hardware come ricevuto (foto delle schede, peso, seriali e hash dei firmware) da conservare fuori banda per confronti futuri:
doas flashrom -p internal -r bios-iniziale.bin # dump del firmware
sha256 bios-iniziale.bin > bios.sha256 # impronta di riferimento
Impianti nel firmware
Un impianto nel firmware vive sotto il sistema operativo e sopravvive alla reinstallazione. Il catalogo ANT elenca impianti BIOS per server (DEITYBOUNCE, IRONCHEF); il Vault 7 descrive impianti EFI per Mac (DerStarke, Sonic Screwdriver); l'Equation Group è arrivato a riprogrammare il firmware degli hard disk e degli SSD, rendendo l'impianto invisibile e non rimovibile dal sistema.
Difesa: usare firmware aperto e verificabile (coreboot e libreboot, vedi anche la sezione BIOS e UEFI); attivare la protezione in scrittura hardware della SPI flash; usare boot misurato con TPM e attestazione (per esempio Heads); cifrare l'intero disco, così che il firmware del drive non veda mai dati in chiaro; verificare periodicamente il firmware confrontandolo con l'impronta di riferimento.
PoC di verifica: ridumpare il firmware e confrontarlo con il riferimento, e leggere i registri del TPM del boot misurato:
doas flashrom -p internal -r bios-oggi.bin
sha256 -c bios.sha256 # deve corrispondere al dump iniziale
doas tpm2_pcrread sha256:0,1,2,3,4,7 # valori del boot misurato
Impianti sulle interfacce
Molti impianti si nascondono nei connettori e nei cavi. La famiglia COTTONMOUTH del catalogo ANT è fatta di connettori e cavi USB che integrano un ricetrasmettitore radio; la classe di attacchi BadUSB sfrutta periferiche USB che si fingono tastiere. Esistono anche impianti dedicati a tastiera e video, trattati nella sezione sulle radiofrequenze.
Difesa: disabilitare o riempire con resina le porte inutilizzate; non collegare mai dispositivi non fidati; adottare una allowlist dei dispositivi USB con usbguard; usare data blocker quando serve solo l'alimentazione; ispezionare fisicamente cavi e connettori, preferendo cavi schermati e corti.
PoC di verifica: elencare i dispositivi USB autorizzati e accorgersi di quelli nuovi:
doas usbguard list-devices # dispositivi noti e loro stato
lsusb # confronto con l'inventario atteso
Esfiltrazione via radiofrequenza
Gli impianti più insidiosi sono i retroriflettori RF passivi: non emettono nulla da soli, quindi sono quasi invisibili a un controllo radio, ma illuminati da un radar esterno rimandano indietro un segnale modulato con i dati. Il catalogo ANT ne elenca diversi (RAGEMASTER sul cavo video, SURLYSPAWN sulla tastiera, TAWDRYYARD come beacon), illuminati da radar come CTX4000 o PHOTOANGLO. Così si può esfiltrare schermo e tasti anche da una macchina non collegata in rete.
Difesa: schermatura elettromagnetica dell'apparato (una gabbia di Faraday o un armadio schermato), filtri sulle linee di alimentazione, e ispezione fisica alla ricerca di impianti. Vale tutto quanto già visto nella sezione Compromissione elettromagnetica: ridurre le emissioni e impedire che un radar esterno possa illuminare l'apparato.
Il WiFi come radar e le backdoor nei router
Le onde WiFi non servono solo a trasmettere dati: rimbalzano sui corpi e sugli oggetti, e analizzando come il segnale viene perturbato (il Channel State Information, CSI) si può rilevare la presenza di persone, contarle, seguirne i movimenti e perfino stimarne la posizione del corpo, anche attraverso i muri e senza telecamere. È un filone di ricerca consolidato (da RF-Pose del MIT fino a DensePose From WiFi) e sta persino diventando uno standard (IEEE 802.11bf, "WLAN Sensing").
Il punto di osservazione naturale per questo sensing è il router: ha la radio WiFi e vede il CSI di tutto ciò che gli sta intorno. Un router con una backdoor, cosa tutt'altro che rara nei firmware proprietari dei router consumer e di quelli forniti dagli ISP, e prevista negli impianti di rete del catalogo ANT (NIGHTSTAND), diventa quindi uno strumento potente: può intercettare il traffico, dirottare il DNS e, con la stessa radio, trasformarsi in un sensore di presenza. Le intelligence potrebbero raccogliere questi dati su larga scala all'insaputa delle persone.
È esattamente il motivo per cui si rende necessario il software libero: l'unico modo per fidarsi di un router è poterne ispezionare e ricompilare il firmware. Un firmware chiuso può nascondere backdoor e funzioni di sensing senza che nessuno se ne accorga; un firmware aperto e verificabile (OpenWrt, libreCMC) permette di controllare cosa fa davvero la radio e di rimuovere telemetria e funzioni indesiderate. Vale lo stesso ragionamento fatto per i firmware delle CPU e dei BIOS: ciò che non si può ispezionare non si può dire sicuro.
Difesa: usare cavo Ethernet invece del WiFi per l'infrastruttura e spegnere la radio quando non serve; installare firmware aperto e verificabile (OpenWrt o libreCMC) su un router che lo supporti, evitando i router bloccati dell'ISP; schermare il locale (gabbia di Faraday, vedi Compromissione elettromagnetica) per ridurre le emissioni e ostacolare il sensing dall'esterno, tenendo presente che anche il WiFi di un vicino o di un avversario può "vedere" attraverso i muri; mantenere il controllo del DNS e monitorare il router.
Attacchi con accesso fisico
Con un accesso fisico anche breve, un avversario dispone di tutta una serie di tecniche documentate.
Evil maid
Manomissione del bootloader o del firmware durante una breve assenza (il nome è di Joanna Rutkowska). Difesa: sigilli a prova di manomissione, anche artigianali come lo smalto glitter sulle viti fotografato in anticipo; cifratura dell'intero disco con autenticazione pre-boot; boot misurato con attestazione (Heads con un codice TOTP mostrato all'avvio); non lasciare mai il server incustodito.
Cold boot
La RAM trattiene i dati per qualche secondo dopo lo spegnimento: raffreddandola e riavviando da un supporto esterno se ne possono estrarre le chiavi di cifratura (attacco descritto in Lest We Remember). Difesa: RAM saldata, azzeramento della memoria allo spegnimento, disabilitare il boot da supporti esterni nel firmware (protetto da password), e non lasciare la macchina accesa o sospesa in un luogo accessibile.
Attacchi DMA
Interfacce come Thunderbolt, FireWire e PCIe permettono l'accesso diretto alla memoria (DMA) e quindi la lettura della RAM senza passare dalla CPU (attacco Thunderclap). Difesa: abilitare l'IOMMU (VT-d o AMD-Vi) e la protezione DMA del kernel; disabilitare Thunderbolt e FireWire e l'hotplug PCIe non necessario.
Porte di debug (JTAG e UART)
Le interfacce di debug lasciate accessibili permettono di leggere e riscrivere memoria e firmware. Difesa: disabilitare o bruciare i fuse JTAG dove previsto, rimuovere o proteggere fisicamente gli header di debug sulla scheda.
PoC di verifica: controllare che l'IOMMU sia attivo (prima difesa contro il DMA):
doas dmesg | grep -i -E 'DMAR|IOMMU|AMD-Vi' # deve risultare abilitato
doas sysctl hw.iommu # FreeBSD
Console, sospensione e memoria
La pagina di Kicksecure sulla protezione dagli attacchi fisici e quella sul cold boot aggiungono alcune misure pratiche a quelle già viste.
- Le console restano aperte: una sessione lasciata su una console testuale non scade e non
viene bloccata da nulla. Si chiude sempre con
exit, e si imposta la disconnessione automatica della shell per inattività. - Mai la sospensione: in sospensione le chiavi del disco restano in RAM. Un nodo è acceso oppure spento.
- Pulire la RAM allo spegnimento: Kicksecure azzera la memoria durante l'arresto. Funziona solo se lo spegnimento è regolare, quindi non ferma chi stacca la corrente ed estrae i moduli, ma toglie di mezzo il caso più comune.
- Dopo lo spegnimento: staccare l'alimentazione (e la batteria, se c'è) e non lasciare la macchina incustodita nei primi minuti, quando la memoria conserva ancora il contenuto.
- Moduli saldati e memoria cifrata: la RAM saldata sulla scheda non si può trasferire su un'altra macchina, e la cifratura della memoria rende inutile leggerla.
- Password su firmware e boot loader: impediscono di avviare da un altro supporto o di cambiare i parametri del kernel senza lasciare traccia.
Canali laterali fisici
Un calcolatore non elabora soltanto dati: consuma corrente, scalda, emette onde elettromagnetiche, fa rumore e impiega tempi diversi a seconda di ciò che calcola. Tutte grandezze fisiche che dipendono dai segreti trattati e che un avversario può misurare senza toccare il software. Sono i canali laterali, tra gli strumenti preferiti delle intelligence proprio perché aggirano una crittografia altrimenti solida.
Analisi dei consumi (SPA e DPA)
Misurando l'assorbimento di corrente durante un'operazione crittografica si risale alla chiave: l'analisi semplice (SPA) legge il consumo di una singola esecuzione, quella differenziale (DPA) correla statisticamente migliaia di tracce. È la tecnica che svuota smart card e token hardware. Difesa: implementazioni a tempo e consumo costanti, mascheramento dei dati intermedi con valori casuali, filtraggio e disaccoppiamento dell'alimentazione, e preferenza per algoritmi e librerie progettati come resistenti ai canali laterali.
Analisi elettromagnetica e acustica
Le stesse informazioni dei consumi trapelano dalle emissioni elettromagnetiche del chip e persino dal rumore dei componenti: è dimostrata l'estrazione di chiavi RSA dal ronzio ad alta frequenza dei condensatori (ricerca di Genkin, Shamir e Tromer) o dal LED di un hard disk. Si lega al tema TEMPEST già visto nella compromissione elettromagnetica. Difesa: schermatura e distanza, generazione di rumore di copertura, componenti di qualità, ed evitare di eseguire operazioni sensibili con microfoni, fotocamere o sensori nelle vicinanze.
Rowhammer
Accedendo ripetutamente e molto rapidamente a una riga di celle DRAM si inducono per disturbo elettrico inversioni di bit nelle righe adiacenti, senza mai accedervi. Da qui si ottengono scalate di privilegi e manomissione di dati altrui, anche da codice non privilegiato o da JavaScript in un browser. Difesa: RAM con ECC e, meglio ancora, con Target Row Refresh; evitare la condivisione fisica della memoria con codice non fidato (niente tenant ostili sullo stesso ferro, coerente con l'air-gap per i nodi sensibili); kernel e microcodice aggiornati.
Esecuzione speculativa (Spectre e Meltdown)
Le CPU moderne eseguono istruzioni in anticipo e in modo speculativo, lasciando tracce nella cache che permettono di leggere memoria di altri processi o del kernel. Sono vulnerabilità della microarchitettura, non del codice. Difesa: microcodice e kernel aggiornati, isolamento dei processi sensibili su core o macchine dedicate, e per i nodi più critici la rinuncia alla condivisione della stessa CPU con carichi non fidati.
PoC di verifica: controllare quali canali laterali della CPU il sistema dichiara mitigati:
# Linux: stato delle mitigazioni note (Spectre, Meltdown, etc.)
grep -r . /sys/devices/system/cpu/vulnerabilities/
La postura paranoica
Nessuna singola misura basta: conta la combinazione. In sintesi, Tutanum riduce al minimo la superficie fisica (meno radio, meno porte, meno interfacce), preferisce hardware aperto e autoprodotto, applica tamper-evidence in modo sistematico (foto, impronte dei firmware, sigilli), unisce boot misurato e cifratura del disco, schermatura RF e, per i nodi più sensibili, l'isolamento fisico dalla rete (air-gap). Il presupposto di fondo è sempre lo stesso: dare per scontato che l'avversario possa aver avuto accesso al ferro, e costruire in modo che anche in quel caso resti il più possibile cieco.