216 lines
8.4 KiB
Markdown
216 lines
8.4 KiB
Markdown
|
Sécuriser les alentours
|
||
|
-----------------------
|
||
|
|
||
|
Avant de commencer votre travail, il est important de mettre en place
|
||
|
un minimum de sécurités pour anticiper les menaces potentielles.
|
||
|
|
||
|
### Identifier les menaces
|
||
|
|
||
|
Il y a deux grandes catégories de menaces lorsque l'on rend visible
|
||
|
une machine sur Internet :
|
||
|
|
||
|
- les scans automatiques ;
|
||
|
- les individus/organisations.
|
||
|
|
||
|
Dès qu'une machine est accessible sur Internet, celle-ci est scannée
|
||
|
par des robots de nombreuses entités qui récoltent des informations ou
|
||
|
même tente des attaques classiques.
|
||
|
|
||
|
Voici des exemples :
|
||
|
|
||
|
- [Shodan](https://www.safetydetectives.com/blog/what-is-shodan-and-how-to-use-it-most-effectively/),
|
||
|
- [Wordpress/phpMyAdmin et autres scanner vulnérabilités](https://cirt.net/Nikto2),
|
||
|
- [installation de site Wordpress avant même que l'administrateur ait connaissance de l'adresse](https://portswigger.net/daily-swig/wordpress-sites-getting-hacked-within-seconds-of-tls-certificates-being-issued).
|
||
|
|
||
|
Généralement, notre machine ne sera pas ciblée directement par un individu ou
|
||
|
une entité, à moins d'avoir fait l'objet d'un scan rapportant des brèches
|
||
|
intéressantes (version de logiciel vulnérable, OS déprécié, port connu ouvert,
|
||
|
mots de passe par défaut, ...). Il est donc très important d'apparaître le plus
|
||
|
neutre possible sur les scans automatiques, en exposant le strict minimum
|
||
|
d'information et de services.
|
||
|
|
||
|
![Capture d'écran des informations relevées par Shodan pour nemunai.re](shodan-nemunai.re.png)
|
||
|
|
||
|
::::: {.warning}
|
||
|
|
||
|
Le site Shodan.io est une source d'information pertinente, mais il ne faut pas
|
||
|
se contenter de ces infections qui ne sont pas exhaustives. D'autres robots
|
||
|
peuvent récolter et tester bien plus en profondeur chaque service/port exposé.
|
||
|
|
||
|
:::::
|
||
|
|
||
|
|
||
|
### Réduire la surface d'attaque
|
||
|
|
||
|
Pour garantir qu'aucun service n'échappe à notre vigilance, nous allons mettre
|
||
|
en place un pare-feu.
|
||
|
|
||
|
Sur un serveur Linux fraîchement installé, aucune règle de filtrage n'est
|
||
|
appliquée. (Sur certaines version Desktop de distribution, un pare-feu est
|
||
|
configuré pour n'accepte aucune connexion entrante).
|
||
|
|
||
|
Avant de commencer notre filtrage, regardons quels programmes sont en écoute
|
||
|
sur notre machine :
|
||
|
|
||
|
```
|
||
|
ss --listen --numeric --processes --tcp
|
||
|
ss --listen --numeric --processes --udp
|
||
|
```
|
||
|
|
||
|
La commande `ss` affiche la liste des programmes qui écoutent (ont `bind(2)`
|
||
|
puis `listen(2)`). Chaque ligne affichée est une porte d'entrée pour de
|
||
|
potentielles vulnérabilités, on s'assure donc que l'on a une confiance absolue
|
||
|
envers chaque programme listé.
|
||
|
|
||
|
::::: {.exercice}
|
||
|
|
||
|
Si à ce stade vous avez plus qu'un serveur SSH, trouvez le fichier qui démarre
|
||
|
les autres daemons pour faire en sorte qu'ils ne soient pas lancés inutilement
|
||
|
|
||
|
:::::
|
||
|
|
||
|
### Atténuer les menaces
|
||
|
|
||
|
Avec `ss`, nous sommes en mesure de savoir précisément de quels ports nous
|
||
|
avons besoin d'ouvrir sur notre machine. Cependant, nous faisons face à 2
|
||
|
problèmes :
|
||
|
|
||
|
- on ne peut pas limiter facilement avec `bind(2)` les IP auxquelles on
|
||
|
voudrait autoriser l'accès du service (par exemple : tout Internet n'a pas
|
||
|
besoin d'accèder à notre serveur SSH, on en a seulement besoin pour
|
||
|
administrer notre serveur, on arrivera sans doute d'une IP connue d'avance),
|
||
|
- et si d'autres programmes se mettent à écouter sur des ports pendant le cycle
|
||
|
de vie d'un autre programme ?
|
||
|
|
||
|
Pour réduire les risques, nous devons mettre en place des règles de pare-feu.
|
||
|
|
||
|
Le pare-feu est un élément du noyau qui vient s'interposer dans les flux réseau
|
||
|
pour individuellement prendre une décision sur chaque paquet ou éventuellement
|
||
|
l'altérer. Il va par exemple être sollicité juste avant de transmettre à
|
||
|
l'espace utilisateur un paquet qui arrive d'une interface réseau (on parle de
|
||
|
paquet entrant).
|
||
|
|
||
|
Nous pourrions donc aisément filtrer le port 22 (utilisé par le serveur SSH)
|
||
|
pour limiter à certaines IP le droit d'accéder à ce port.
|
||
|
|
||
|
En fait, on utilise un pare-feu surtout en liste blanche. C'est-à-dire que l'on
|
||
|
interdit de base tout paquet entrant, SAUF ceux qui nous intéressent. On est
|
||
|
alors assuré que si un programme se met à écouter sur un port en dehors de
|
||
|
notre surveillance, il ne sera pas joignable car les paquets qui lui seront
|
||
|
destinés seront bloqués par le pare-feu du système.
|
||
|
|
||
|
|
||
|
### Mise en place du pare-feu
|
||
|
|
||
|
Le pare-feu du noyau Linux est `netfilter`. On interagit avec lui avec des
|
||
|
appels systèmes, et de nombreux logiciels permettent de gérer plus ou moins
|
||
|
facilement les règles.
|
||
|
|
||
|
Il y a 2 implémentations de référence :
|
||
|
|
||
|
- `iptables` : utilisé depuis 1998, il est aujourd'hui présent et utilisé par
|
||
|
la majorité des administrateurs système.
|
||
|
- `nftables` : stable depuis 2021, il tend à remplacer `iptables`, aux
|
||
|
fonctionnalités vieillissantes (séparation IPv4/IPv6, vitesse de traitement,
|
||
|
...).
|
||
|
|
||
|
Quelque soit la distribution, vous pourrez installer le paquet au nom de
|
||
|
l'implémentation que vous souhaitez utiliser. Dans la suite, nous allons
|
||
|
utiliser `nftables`, mais libre à vous d'utiliser l'implémentation de votre
|
||
|
choix.
|
||
|
|
||
|
Pour afficher la liste des règles actuellement appliquées, on utilise les
|
||
|
commandes suivantes :
|
||
|
|
||
|
```
|
||
|
nft list ruleset
|
||
|
```
|
||
|
|
||
|
ou avec `iptables` :
|
||
|
|
||
|
```
|
||
|
iptables -t $TABLE --list
|
||
|
ip6tables -t $TABLE --list
|
||
|
```
|
||
|
|
||
|
On remarque qu'avec `iptables` on ne peut pas avoir accès à toutes les règles, on
|
||
|
ne peut les afficher que par TABLE et selon la version IPv4 ou IPv6. La table
|
||
|
`filter` est la table par défaut et celle que l'on uti lisera le plus, mais il
|
||
|
y a aussi `nat`, `mangle`, ...\
|
||
|
|
||
|
::::: {.warning}
|
||
|
|
||
|
Faites attention lorsque vous changer les règles de pare-feu à distance, car
|
||
|
votre connexion passe par ce pare-feu. Si vous bloquez toutes les connexions
|
||
|
entrantes avant d'autoriser votre connexion SSH, vous vous retrouverez à la porte.
|
||
|
|
||
|
Dans le contexte de ce TP, vous avez accès à la console dans votre hyperviseur
|
||
|
pour remédier à la situation, mais parfois vous pouviez n'avoir comme solution
|
||
|
que le redémarrage (les règles ne sont pas persistantes), voire le déplacement
|
||
|
dans le datacenter, si vos règles sont chargées automatiquement au démarrage !
|
||
|
|
||
|
:::::
|
||
|
|
||
|
Avant d'interdire toutes les connexions entrantes, nous allons donc autoriser
|
||
|
notre connexion SSH ! On commence par créer une table :
|
||
|
|
||
|
```
|
||
|
nft add table inet <mytable>
|
||
|
```
|
||
|
|
||
|
Le paramètre `inet` indique que l'on souhaite créer une table qui agira sur le
|
||
|
trafic IPv4 et IPv6 à la fois ([voir les autres types de table
|
||
|
supportés](https://wiki.nftables.org/wiki-nftables/index.php/Nftables_families)).
|
||
|
|
||
|
Au sein de notre table, nous allons maintenant créer une chaîne de règle. C'est
|
||
|
ici que l'on va indiquer à quel `hook` du noyau on souhaite s'accrocher :
|
||
|
plutôt les paquets entrant, sortant, traversant, ...
|
||
|
|
||
|
```
|
||
|
nft add chain inet <mytable> <mychain> '{type filter hook input priority 0; }'
|
||
|
```
|
||
|
|
||
|
On va donc créer ici une chaîne nommée `mychain`, agissant en filtrage
|
||
|
(`filter`) sur tous les paquets entrant (`input`). On crée l'équivalent ici de
|
||
|
la chaîne `INPUT` de la table `filter` d'`iptables` et `ip6tables` mélangés.
|
||
|
Cela permet d'indiquer au noyau à quel niveau on souhaite appliquer ces
|
||
|
règles.
|
||
|
|
||
|
Ajoutons justement notre première règle pour autoriser les connections
|
||
|
SSH :
|
||
|
|
||
|
```
|
||
|
nft add rule inet <mytable> <mychain> tcp dport 22 accept
|
||
|
```
|
||
|
|
||
|
Au sein d'un chaîne, sauf rares exceptions, les règles sont évaluées
|
||
|
séquentiellement et la première décision qui valide les conditions est retenue.
|
||
|
Dans notre exemple ci-dessus, la décision est d'accepter (`accept`) le paquet :
|
||
|
si aucune règle n'existe avant, validant aussi les conditions, cette règle sera
|
||
|
la dernière d'un paquet TCP à destination du port 22, il sera ensuite délivré à
|
||
|
l'espace utilisateur.
|
||
|
|
||
|
Vous devriez prendre connaissance des [conditions possibles sur lesquelles
|
||
|
filtrer les
|
||
|
paquets](https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes#Matches)
|
||
|
et les [décisions possibles pour un
|
||
|
paquet](https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes#Statements).
|
||
|
|
||
|
Enfin, changeons la politique par défaut pour les paquets entrant pour lesquels
|
||
|
aucune décision n'a été prise, qui est d'accepter tous les paquets, vers la
|
||
|
politique `drop`, qui envoie vers un trou noir les paquets qui n'auront pas
|
||
|
étéacceptés dans la chaîne.
|
||
|
|
||
|
```
|
||
|
nft add chain inet <mytable> <mychain> '{ policy drop; }'
|
||
|
```
|
||
|
|
||
|
Eh voilà ! vous êtes en sécurité.
|
||
|
|
||
|
::::: {.exercice}
|
||
|
|
||
|
Faites en sorte maintenant de limiter les connexions SSH à votre IP ou à la
|
||
|
plage d'IP susceptible de se connecter, plutôt que d'accepter toutes les IP.
|
||
|
|
||
|
:::::
|