fwknop: proteggere servizi con Single Packet Authorization (SPA)

fwknop

Cos'è fwknop

fwknop è un software di port knocking che usa uno schema di autenticazione chiamato “Single Packet Authorization” ipotizzato e formalizzato dallo stesso autore per risolvere le debolezze più comuni del classico port-knocking.

  1. Cos'è fwknop
  2. Installazione client e server
  3. Configurazione client
    1. Generazione della sola chiave
    2. Generazione chiave + configurazione complessa
  4. Configurazione server
  5. Scenari
    1. Protezione di un servizio con SPA
      1. Configurazione lato server
      2. Configurazione lato client
    2. Ghost locale sullo spaserver
      1. Configurazione lato server
      2. Invocazione client
    3. SPA attraverso gateway NAT
      1. Configurazione lato server
      2. Invocazione client
    4. SPA Ghost Service
      1. Invocazione client
  6. E se volessi usare la crittografia asimmetrica?
  7. Osservazioni su access.conf
    1. Configurazione stanze con spa server come bastion host
    2. Alice
    3. Bob
    4. Carol

fwknop, come il port knocking, unisce la comunicazione passiva di informazioni di autenticazione al filtraggio di tutti i pacchetti che non rispettano le sequenze di knock.

Il classico approccio di port-knocking sfrutta le intestazioni dei pacchetti (2 byte) e non il loro payload, per cui è necessario mandare un certo numero di pacchetti per mappare una porta senza generare falsi positivi. Questo però comporta inevitabilmente almeno due problemi:

Il client fwknop (SPA Client) invia al server (SPA Server) un singolo pacchetto di dimensioni relativamente maggiori (possibile sfruttando il payload) per comunicare informazioni di accesso e interi comandi destinati al filtraggio dei pacchetti.

Il tutto viene protetto da una cifratura simmetrica con autenticazione (aes256-cbc + hmac-sha256, che sarà quella usata nel prosieguo perché più semplice da gestire) o asimmetrica che, al costo di una maggiore complessità di gestione, aggiunge la caratteristica di non ripudio alle caratteristiche di confidenzialità, integrità e autenticazione possedute anche dal primo schema di cifratura.

Installazione client e server

fwknop client e server sono pacchettizzati per ogni distro linux (su Mac OS è possibile ricorrere a brew). Sistemi rpm-based

# Installa il client (fwknop) e il server (fwknopd)
dfn install fwknop

Sistemi debian-based

# Installa il client (fwknop)
apt install fwknop-client

# Installa il server (fwknopd)
apt install fwknop-server

Configurazione client

La configurazione lato client viene conservata nel file .fwknoprc che può essere editato a a mano oppure attraverso il client fwknop salvando nel file .fwknoprc quelle che vengono definite “stanze”.

Nella configurazione è molto importante la generazione della chiave. Se la chiave è simmetrica, la si può generare con fwknop.

Di seguito, due esempi di creazione di stanze con fwknop, una minimale (che useremo nel resto del documento) e una più complessa.

Generazione della sola chiave

Genero la chiave usando il default: aes256-cbc + hmac-sha256.

fwknop -n test -k --use-hmac --save-rc-stanza

E in .fwknoprc troverò una nuova sezione [test]

[test]
KEY_BASE64                  dRYAH2O9FCUpNz1aMmlke9/AkGVdcLrnWxDy7jZC1wg=
HMAC_KEY_BASE64             0xRNOSrVTy6B7PmBHiZG5jzTLwxsPrOd6kUb5/p45VjFfWp3eXMG8hVz4JRjoP89JbtMDhghghco7pV9cdQzdw==
USE_HMAC                    Y

Generazione chiave + configurazione complessa

fwknop -n test -k -A tcp/80 -R -w /usr/bin/wget -D 107.23.186.49 -N 10.0.0.132:3306 --save-rc-stanza

che ha il corrispondente .fwknoprc:

[test]
ACCESS                      tcp/80
SPA_SERVER                  107.23.186.49
KEY_BASE64                  0d/VcRXnf2si7hvfDsPN3YIG4Q7aPLU9Ndd5Pe+eMIQ=
HMAC_KEY_BASE64             EEXu0VCPQKPGp8FC8tYS6I/p56nWlot93BV3CPVf3De9FkM04z1SBWTUEJejHpq45+at7VQirgTYvSxeLoZkKQ==
NAT_ACCESS                  10.0.0.132:3306
RESOLVE_IP_HTTPS            Y
WGET_CMD                    /usr/bin/wget

La spiegazione di questa configurazione specifica la troveremo più avanti nel par. 4. SPA Ghost Service. È solo per far vedere che il file di configurazione .fwknoprc può essere rimpiazzato in toto dall'invocazione via cli del client. Chiave compresa, se è il caso.

Affinché la “stanza” venga creata, deve necessariamente essere presente almeno uno fra valori dei flag -D e -n. Quest'ultimo costituirà anche il nome alla sezione corrispondente, altrimenti sarà il valore di -D .

Per usare il cient con le preimpostazioni di .fwinoprc, basterà indicare il nome della sezione:

fwknop -n test

Ne consegue che i nomi di sezione devono essere univoci.

Da ricordare che quando si usa il client quello che è importante specificare nel file .fwknoprc o nei parametri è:

Configurazione server

Il server si compone di due file:

Anche access.conf è un elenco di “stanze”, i punti d'accesso per i client contenenti come minimo la rete abilitata all'accesso e la chiave con cui si presenta l'utente, come visto in Configurazione client:

Altri parametri utili a rafforzare ulteriormente il legame con le richieste client, ma non obbligatori per l'avvio del servizio, sono:

Quando queste opzioni sono presenti sul server, dovranno essere obbligatoriamente specificate anche nel client. Dopo aver visto le configurazioni di client e server, vedremo fwknop in azione in alcuni casi “reali”.

Scenari

Grazie alla sua capacità sia di manipolare, anche in maniera piuttosto articolata, i firewall che concedono l'accesso alle risorse che ad eseguire interi comandi che fwknop mostra tutta la sua versatilità.

In particolare è col NAT che riesce ad andare oltre la sua natura di port knocking dove, grazie ad una combinazione di DNAT e SNAT, riesce a:

diventando a tutti gli effetti un bastion host per l'esposizione autenticata e sicura di servizi critici.

Riassumendo, fwknop può:

Gli scenari che andrò a mostrare, copriranno i casi più comuni:

  1. Protezione di un servizio con SPA
  2. Ghost locale sullo spaserver
  3. SPA attraverso Gateway NAT
  4. SPA Ghost Service

Lato client, fwknop si baserà sempre sulla configurazione minimale vista prima nel paragrafo “Configurazione client. Il resto delle configurazioni verrà passato via cli.

1. Protezione di un servizio con SPA

La cosa più semplice da fare è mettere lo spaserver a protezione diretta del servizio insieme ad un firewall che implementa una policy default-drop. Ipotizziamo ad es. di proteggere l'accesso in ssh sul nodo centrale (192.168.100.10) di una rete a stella.

fwknop spa server

Configurazione lato server

Configurazione lato client

Supponiamo adesso di voler proteggere l'accesso ssh di una macchina dove però il client , caso molto frequente, sia in una rete privata e nattato con un ip pubblico (rete domestica o rete mobile per es.).

Non possiamo sapere con certezza quale sarà l'ip del client per cui, lato server, dovrò essere disposto ad accettare qualunque sorgente e lato client lascerò che l'ip venga risolto dinamicamente.

fwknop con client nat

fwknop -n test -R -w /usr/bin/wget -A tcp/22 -D 107.23.186.49
ssh 107.23.186.49

L'opzione:

N.B. Non sapendo quale sarà l'ip richiedente, la clausola SOURCE nel file test.conf non potrà contenere un ip o una subnet, quanto piuttosto:

...
SOURCE                      ANY
...

2. Ghost locale sullo spaserver

Assumiamo che la topologia di rete sia semplice come quella del caso precedente ma ipotizziamo che il client che si autentichi con SPA, acceda ad un servizio protetto la cui porta sia associata contemporaneamente ad un altro servizio esposto pubblicamente.

In questo modo qualunque un altro client (anche attori malevoli) che volesse connettersi a quella porta, continuerebbe a vedere solo il servizio pubblico e non quello protetto.

Questa magia viene resa possibile grazie ad un DNAT locale che mappa temporaneamente, e solo per quell'ip, la porta pubblica con quella del servizio da proteggere.

Nel nostro esempio vogliamo accedere in ssh alla macchina ma sulla porta 80, corrispondente ad un servizio web esposto pubblicamente.

fwknop con server local nat

Configurazione lato server

Invocazione client

fwknop -n test -R -w /usr/bin/wget -A tcp/22 -D 107.23.186.49 --nat-local --nat-port 80
ssh 107.23.186.49 -p80

3. SPA attraverso gateway NAT

In questo caso lo spa server verrà usato come gateway per accedere a servizi posti sulla rete interna. ad es. un db mybsql su una macchina (10.0.0.132) posta dietro lo spa server.

Per ottenere tutto questo, bisogna abilitare il port forwarding e il SNAT nel file fwknopd.conf in modo che vengano create le regole DNAT e MASQUERADE su iptables affinché le richieste vengano inoltrate rispettivamente verso la macchina che eroga il servizio (mysql) e che i pacchetti di ritorno viaggino correttamente verso lo spa server e quindi verso il client. Il file access.conf rimane invariato

fwknop con gateway nat

Configurazione lato server

PCAP_INTF                   enp0s8;
ENABLE_IPT_FORWARDING       Y;
ENABLE_IPT_SNAT             Y;

Invocazione client

fwknop -n test -R -w /usr/bin/wget -A tcp/3306 -D 107.23.186.49 -N 10.0.0.132
mysql -h 107.23.186.49 -u <user> -p

4. SPA Ghost Service

Adesso vogliamo che l'accesso a mysql venga “nascosto” da un servizio legittimo esposto pubblicamente (un servizio http sulla porta 80).

fwknop con ghost service

La configurazione lato server (fwknopd.conf, access.conf) rimane invariata rispetto a prima.

Invocazione client

fwknop -n test -A tcp/80 -R -w /usr/bin/wget -D 107.23.186.49 -N 10.0.0.132:3306
mysql -h 107.23.186.49:80 -u <user> -p 

E se volessi usare la crittografia asimmetrica?

La crittografia asimmetrica usata con hmac costituisce un ulteriore enhancement di sicurezza.

Mentre con la crittografia simmetrica+hmac si ha una sorta di implicito mutuo riconoscimento, con la crittografia asimmetrica è sufficiente che il client sia riconosciuto dal server.

Affinché ciò avvenga, il client inva il pacchetto spa firmato con la sua chiave privata e lo cifra con la chiave pubblica dello spaserver. Lo spaserver riceve il pacchetto, verifica la firma con la chiave pubblica del client, lo decifra con la sua chiave privata, proseguendo poi col resto del processo di autorizzazione e accesso.

È consigliata la creazione di chiavi apposite per fwknop, non quelle personali. Per il client creeremo una chiave di sola firma e per il server una chiave completa. Le corrispondenti chiavi private possono anche essere lasciate prive di password. Se non lo fossero, dovranno essere inserite nel file di configurazione in mancanza delle quali, soprattutto lato server, finirebbero per richiedere a runtime una poco gestibile interazione con l'utente.

The last but not the least, bisogna tenere presente che, come riportato dalla documentazione (https://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html#fwknop-gpg) la scelta delle chiavi è un'operazione critica.

La cifratura asimmetrica, a differenza di quella simmetrica, tende a produrre dei payload decisamente più cicciotti. Quindi, per non correre il rischio di avere un payload che superi il default dell'MTU ethernet (1500 byte), bisogna “vincolare” la scelta della chiave del server (di cifratura) a quella del client (di firma).

Le chiavi a curva ellittica sarebbero una buona soluzione. Purtroppo funzionano solo per la firma, non per la cifratura. Quindi vanno bene per il client e non per il server.

Se client e server usassero chiavi rsa, sarebbe meglio per il server usare chiavi non superiori a 3072 bit (caso limite), consigliati 2048 bit. In questo modo un'eventuale chiave client di 4096 bit sarebbe tollerata. Altrimenti si rischierebbe un fault: fwknop: fko_spa_data_final: Error 59 - Args contain invalid data: FKO_ERROR_INVALID_DATA_ENCRYPT_GPG_RESULT_MSGLEN_VALIDFAIL

Nell'esempio che segue, prenderemo in esame lo scenario 4, ma con autenticazione GPG, con una chiave ECC per il client e una chiave rsa 3072 bit per il server (ma sarebbe tollerata anche una chiave a 4096 bit).

Creazioni delle chiavi su server e client

spa client

# Creazione chiave di sola firma
gpg --batch --passphrase '' --quick-gen-key "fwknop client (chiave del client fwknop) <fwknop@spaclient>" ed25519 cert,sign never`

# esporta chiave pubblica e invio a spaserver
gpg -o fwknop@spaclient.gpg --export fwknop@spaclient
scp fwknop@spaclient.gpg 107.23.186.49:

spa server

# Creazione chiave di firma e cifratura. Quella di cifratura è una rsa 3072 bit
gpg --batch --passphrase '' --quick-gen-key "fwknopd server (chiave del server fwknopd) <fwknopd@spaserver>" ed25519 cert,sign never
gpg --batch --passphrase '' --quick-add-key '2BCD6BEF564A54362F8242017C17EC045408C7DB' rsa3072 encr never

# esporta chiave pubblica e invio al client
gpg -o fwknopd@spaserver.gpg --export fwknopd@spaserver
scp fwknopd@spaserver.gpg 107.23.186.160:

Importazioni e firma delle chiavi

# importazione e firma della chiave
gpg --import fwknopd@spaserver.gpg
gpg --sign-key fwknopd@spaserver
# importazione e firma della chiave
gpg --import fwknop@spaclient.gpg
gpg --sign-key fwknop@spaclient

Configurazione access.conf.d/test.conf e .fwknoprc

Analogamente a quanto fatto con la cifratura simmetrica:

Test client

fwknop --verbose -n test_gpg -A tcp/80 -R -w /usr/bin/wget -D 107.23.186.49 -N 10.0.0.132:3306
mysql -h 107.23.186.49:80 -u <user> -p

N.B.: Gli scenari 2, 3 e 4 sono le riproposizioni di ciò che viene presentato da Michael Rash durante lo ShmooCon del 2013 in https://www.youtube.com/watch?v=GCGiI6DJuIc (scenario 2) e nel suo blog (https://www.cipherdyne.org/blog/categories/port-knocking-and-spa.html) in https://www.youtube.com/watch?v=tz-xK1BarKk (scenario 3 e 4)

Ghost Service e SPA across gateway NAT non sono chiarissimi negli esempi forniti, mancano alcuni dettagli per me, che non sono un esperto di reti, fondamentali come la giusta evidenza e l'importanza sull'uso corretto del local nat nel primo caso e di SNAT negli altri due.

Tutti gli esempi, in particolare 3 e 4, sono stati testati con un'infrastruttura speculare a quella usata nel 2° video, ottenuta non già attraverso AWS ma con il più modesto VirtualBox che ha comunque svolto egregiamente il suo compito.

Per chi volesse effettuare delle prove sul campo, spero, in futuro, di mettere a disposizione questo piccolo laboratorio attraverso Vagrant e di dare indicazioni sulle configurazioni degli apparati che si occupano di routing e nat.


Osservazioni su access.conf

access.conf permette di stabilire chi accede e su quali risorse.

Le porte specificate nella clausola ACCESS permetteranno al clent di accedere con la stessa chiave:

  1. a tutti i servizi relativi, se lo spaserver è installato sulla stessa macchina che li eroga;
  2. a tutti i server relativi (eroganti i servizi indicati in ACCESS) nattati dallo spaserver;
  3. ad uno solo dei servizi, e solo fra quelli “nattabili”, se nell'access.conf uso le clausole FORCE_NAT/SNAT, per quanto siano larghe le maglie della clausola ACCESS. Inoltre posso usare ACCESS per concedere o meno la possibilità di ghostare un servizio

Vediamo con un po' di esempi cosa possiamo fare

fwknop bastion host

Questo scenario riprende ed estende quello visto finora, dove si evidenzia il natting sia dei client che dei server, entrambi nelle loro lan private.

A differenza degli scenari precedenti, lo spaserver non è direttamente esposto ma è anch'esso nel backend. Gli altri server espongono un server web sulla porta 8080, un remote-desktop sulla 3389 e un db mysql sulla 3306.

Per mostrare quanto fwknop possa essere flessibile, supponiamo di avere 3 utenti, Alice, Bob e Carol, ognuno con privilegi differenti. fwknop sarà configurato come bastion host.

Supponiamo sempre che lo spaserver esponga pubblicamente un sito web sulla porta 80 (utile per un eventuale ghosting dei servizi) .

Configurazione stanze con spa server come bastion host

La configurazione delle stanze richiederà al client anche di specificare l'utente.

Alice

Con le stanze configurate in questo modo, alice, che ha una chiave gpg, può usare la stessa chiave da qualunque ip, per raggiungere uno qualunque fra i 3 server in backend. Es.

#webserver
fwknop -n alice -A tcp/8080 -R -w /usr/bin/wget -D 5.112.84.211 -U <username_alice> -N 192.168.100.112

o

# remote-desktop
fwknop -n alice -A tcp/3389 -R -w /usr/bin/wget -D 5.112.84.211 -U <username_alice> -N 192.168.100.25

o

# mysql
fwknop -n alice -A tcp/3306 -R -w /usr/bin/wget -D 5.112.84.211 -U <username_alice> -N 192.168.100.109

Alice può anche “ghostare” il servizio, ad es. mysql

# mysql
fwknop -n alice -A tcp/80 -R -w /usr/bin/wget -D 5.112.84.211 -U <username_alice> -N 192.168.100.109:3306

Bob

Bob può raggiungere il db o il server windows in remote desktop, non il webserver. Ad es.

# mysql
fwknop -n bob -A tcp/3306 -R -w /usr/bin/wget -D 5.112.84.211 -U <username_bob> -N 192.168.100.109

Carol

A Carol invece è consentito solo l'accesso al db mysql e solo da due subnet specifiche.

Ad es.

# mysql
fwknop -n carol -A tcp/3306 -a 154.23.162.99 -D 5.112.84.211 -U <username_carol> -N 192.168.100.109

Né Bob, né Carol possono ghostare servizi.

Riferimenti:

#fwknop #spa #crittografia