Écrit par Jérôme Flesch pour debian-fr.org
Ce document est sous license FDL.
Cet article a été écrit au moment où le dernier noyau Linux stable en date était le 2.4.21 (9/8/2003) et pour GrSecurity 1.0.
Cet article se base essentiellement sur la documentation officielle (http://www.grsecurity.org/gracldoc.htm) ainsi que sur l'aide proposée lors de la configuration du noyau.
Si vous souhaitez installer GrSecurity 2.0, vous pouvez déja jeter un oeil sur cet article qui vous donnera les principaux changements.
Le principe de GrSecurity, appelé aussi GrSec, est simple: accroître la sécurité d'un système informatique basé sur le noyau Linux.
Vous me direz, GNU/Linux est un système stable, utilisé un peu partout, etc, alors pourquoi chercher à le sécuriser encore plus ? Déjà parce-que GNU/Linux n'a jamais été totalement infaillible, et quoiqu'on en dise, des failles de sécurité sont régulièrement trouvées dans certains serveurs. De plus, les utilisateurs ayant un compte sur une machine GNU/Linux peuvent facilement obtenir des informations en tout genre sur celle-ci, facilitant le récolement d'informations qui est toujours la première phase de l'attaque d'un pirate. Un des autres problèmes de Linux sont les cages "chroot" (cf man chroot), qui laisse un peu trop facilement échapper leurs occupants.
GrSecurity a donc pour but de remédier à tout ces problèmes (ce qui ne rendra sans doute pas votre Linux-Box invulnérable, mais qui y contribuera sûrement).
GrSecurity offre différentes protections, telles que:
Bref, vous l'avez compris, si vous avez un serveur GNU/Linux (ou même juste un poste de travail), GrSec est ce qu'il vous faut !
Bon, il ne faut pas se leurrer, si vous voulez installer grsec, vous êtes bon pour patcher et recompiler votre noyau (Profitez-en pour mettre le votre à jour ?)
* Préliminaires:
Vous devez avoir les librairies et les exécutables nécessaires à la compilation de votre noyau, et vous devez savoir comment en compiler un. Pour tout ce qui va suivre, vous devrez être en root, donc tacher de prendre vos précautions (genre: alias 'rm -rf /'='echo Arrête de boire')
* 1ère étape: Récupérer les sources du noyau
Contrairement à ce qu'on pourrait penser, apt-get n'est pas vraiment votre ami dans ce cas-là, je m'explique: Il semblerait que les responsables du projet Debian ont choisit de patcher les sources du kernel qu'ils distribuent et ceci depuis la version 2.4.20. Quoiqu'il en soit, le patch GrSec ne marchant pas sur ces versions tatouées Debian (ou sinon c'est que j'ai raté une option quelque part ?), il ne vous reste plus qu'à vous rendre chez notre ami http://kernel.org/ pour y prendre la dernière version en date. Pour me faciliter la vie, je pars du principe que vous avez opté pour un 2.4.21 flambant neuf (évidement, si ce n'est pas le cas, je pense qu'il vous suffira d'ajuster les chiffres).
* 2ème étape: Récupérer GrSecurity
Là par contre, apt-get fait tout à fait l'affaire:
apt-get install kernel-patche-2.4-grsecurity
Il est possible que "gradm", vous serve par la suite, mais pour l'instant on s'en cogne.
* 3ème étape: Installer et patcher tout ça
(Je vais détailler un peu les opérations au cas où vous seriez un peu fatigué)
- Mettre les sources que vous avez téléchargées (normalement "linux-2.4.21.tar.bz2") dans le /usr/src
cd /usr/src ; tar -xjf linux-2.4.21.tar.bz2
Là j'ai eu un petit problème avec le script chargé d'appliquer le patch, donc j'ai choisi d'utiliser la méthodedonnée dans la documentation officielle de grsec pour patcher les sources (maj: personnellement, j'ai plutôt tendance à prendre carrément le dernier patch en date sur http://grsecurity.org et à l'appliquer comme indiquer ci-dessous):
cd /usr/src/kernel-patches/all/grsecurity-2-4
(c'est normalement là que ce trouve les patches)
cp grsecurity-*-2.4.21.patch.gz /usr/src
(on copie le patch dans /usr/src)
cd /usr/src/; gunzip grsecurity-*-2.4.21.patch.gz
(On sort le patch de sa boite)
patch -p0 <grsecurity-*-2.4.21.patch
(On patche: Il faut savoir que le patch considère les sources du noyau comme étant dans ./linux-2.4.21)
* 4ème étape: Configurer et compiler votre kernel
make menuconfig
ou
make xconfig
, au choix
Le paramétrage des 9/10ème de votre kernel n'étant pas du ressort de ce document, je vais directement passer à la section concernant GrSecurity qui a du apparaître si le patch a été correctement appliqué.
Je vais donc tacher de décrire au mieux chacune des options proposées dans cette section (Il est possible que l'aide fournie lors de la configuration du noyau vous donne plus de précisions).
# GrSecurity (Y/N):
Évidemment vous mettez ceci sur Y, sinon je me demande bien pourquoi vous avez fait tout ça
# Security level (Low/Medium/High/Customized):
Comme vous vous en doutez, il s'agit de choisir le niveau de sécurité appliqué par GrSec.
Je vais donc vous décrire les caractéristiques de chaque niveau de sécurité, mais je vous recommande fortement de prendre "Customized" qui vous permettra de choisir dans le détail les options que vous souhaitez.
Si vous choisissez "customized", il faut savoir que certaines options pourront être (dés)activées à partir du /proc (ce qui n'est pas le cas en "low", "medium" ou "high" !): Il s'agit des options dont j'ai fait suivre le nom par leur nom dans le /proc/sys/kernel/grsecurity/.
C'est dans "customized" que j'explique le détail de chaque fonctions.
Low :
Linking restrictions
Fifo restrictions
Random pids
Enforcing RLIMIT_NPROC on execve()
Restricted dmesg
Random ip ids
Enforced chdir("/") on chroot
Medium :
Random tcp source ports
Altered Ping ids
Failed fork logging
Time change logging
Signal Logging
Deny mounts in chroot
Deny double chrooting
Deny sysctl writes in chroot
Deny mknod in chroot
Deny access to abstract AF_UNIX out of chroot
Deny pivot_root in chroot
Denied writes of /dev/kmem, /dev/mem, and /dev/port
/proc restrictions with special gid set to 10
address space layout randomization
High:
additional /proc restrictions
chmod restrictions in chroot
no signals, ptrace, or viewing processes outside of chroot
capability restrictions in chroot
deny fchdir out of chroot
priority restrictions in chroot
segmentation-based implementation of PaX
mprotect restrictions
removal of /proc/<pid>/[maps|mem]
kernel stack randomization
mount/unmount/remount logging
kernel symbol hiding
Customized:
Il faut savoir que la plus part des options en rapport avec la gestion de la mémoire proviennent du projet PaX qui a été inclus à GrSecurity. Ces options fonctionnent en partie avec 'chpax' (apt-get install chpax) qui n'est pas traité dans cet article, mais qui fera sans doute l'objet d'un prochain article.
Address Space Protection:
Enforce non-executable pages:
Il arrive que sur certaines machines, la protection des pages mémoires soit indisponible ou que Linux ne l'utilise tout simplement pas. Cela peut donc laisser la porte ouverte à des attaques du genre buffer overflow, etc. Cette options permet donc de choisir différentes protections pour y remédier.
NDR:<!-- U --> J'utilise une carte vidéo Nvidia GeForce 4 440Mx (avec le pilote fourni par nvidia), et il semblerait que cette option empêche XFree86 et le pilote de fonctionner correctement. Si vous aussi avez ce genre de problèmes avec GrSecurity et votre GeForce, merci de me prévenir pour que je sois sûr que ce n'est pas une spécificité de ma machine)
Re-NDR:<!-- U --> Des possesseurs de GeForce 2 et de carte Ati Rage m'ont signalé avoir eût des problèmes similaires avec cette option. Il semblerait donc que ce soit un problème commun à tout les utilisateurs de XFree (à vérifier). Je me suis aussi rendu compte que cette option rendait impossible la compilation des locales sur les Debian. Dans le cas des locales, ceci est peut-être simplement dû à une des options suivantes dépendantes de celle-ci (étant flemmard par nature, je vous avouerais ne pas trop avoir cherché).
Paging based non-executable pages:
L'aide du kernel ne décrit pas très clairement en quoi consiste cette option, cependant, d'après les explications que j'ai obtenu (merci Dave` :), cette option aurait pour but d'utiliser de manière plus efficaces les permissions d'accès sur les différentes pages mémoires (ceci grâce au MMU: Memory Management Unit), retirant notament l'attribut exécutable à certaines pages où cet attribut est rarement néccessaire.
L'aide du kernel dit que cela peut avoir des incidences variables sur le CPU et recommande une certaine précaution avec. Cependant je l'ai testé sur un Pentium I et un Pentium III sans que cela semble poser de problème ni de ralentissement majeur.
Segmentation based non-executable pages:
Encore une fois l'aide du kernel reste assez flou, mais on peut penser qu'elle a une utilité similaire à la précédente. Cependant ils précisent qu'elle a peu d'impactes sur les performances et précisent qu'elle limitera aussi l'espace d'adressage à 1.5Gb au lieu de 3Gb.
Emulate trampolines:
Certains programmes ont besoin d'exécuter des petits bouts de code dans des pages mémoires rendues non-exécutables par les options précédentes. Celle-ci sert donc à remédier à ce problème (Cette option est même nécessaire sur les Parisc et les ppc). Mais pour faire correctement fonctionner ces programmes, en plus de cette option, il faut utiliser le programme 'chpax' (non traité dans ce document, désolé).
Les concepteurs de grsec précisent cependant que cette option *peut* servir à un attaquant et conseillent donc, plutôt que de l'utiliser, d'éviter les programmes nécessitant cette option (souvent ces programmes sont en rapport avec la libc5).
Automatically emulate sigreturn trampolines:
Il s'agit d'une option dans la continuité de la précédente. C'est une solution temporaire pour les utilisateurs bloqués avec une libc5, une glibc 2.0 ou je-ne-sais-quoi-encore-de-Mal(tm).
Comme la précédente, elle est nécessaire si vous avez un parisc ou un ppc, et comme la précédente, elle offre une faille pour un attaquant.
Restrict mprotect()
Cette option empêche les programmes de:
- rendre exécutable une page mémoire qui ne l'était pas
- rendre accessible en écriture une page mémoire exécutable qui était en lecture seule
- créé une page exécutable sur une mémoire quelconque.
Disallow ELF text relocations (DANGEROUS):
Certains types de librairies ELF sont sujets à des attaques. Ce genre d'attaque peut être empêcher en poussant le système à n'utiliser que des librairies PIC ELF. Cependant cela peut poser problème dans le cas où certains composants de votre OS utiliseraient une de ces librairies non-PIC. Donc à moins d'être sûr de savoir ce que vous faites, il est recommandé de ne pas activer cette option.
Enforce non-executable kernel pages:
Options équivalente à "Paging based non-executable pages" et à "Restrict mprotect()" rendant plus dur l'injection d'un code étrangé dans la mémoire du noyau.
Address Space Layout Randomization:
Beaucoup d'attaques se basent sur la connaissance de certaines adresses mémoire dans le programme cible. Cette option permet donc au kernel de choisir les adresses mémoires au hasard, empêchant l'attaquant de les deviner. Or ce genre d'attaques lancées au hasard va plus probablement planter le programme cible que causer de réels dégâts, ce qui permettra au noyau de détecter chaque tentative et de réagir.
PaX précise ne pas fournir de mécanisme de réaction, mais GrSecurity, dans le cadre des ACLs en propose un. Une autre alternative pouvant fournir un mécanisme de réaction est " Nergal's segvguard " ( ftp://ftp.pl.openwall.com/misc/segvguard/ ).
Randomize kernel stack base:
Cette option utilise le même principe que la précédente, mais l'applique sur chaque mémoire tampon des différentes taches du kernel.
Les concepteurs de grsec mettent en garde sur le fait que le fait de rendre les adresses de ces piles aléatoires peut causer des "stacks overflow" (surcharge de ces mémoires tampons) et recommandent donc de tester très attentivement votre système.
Randomize mmap() base:
Même principe qu'avant, mais pour les requêtes mmap() (sauf celles qui précisent une adresse). Cela s'appliquera donc notamment au librairies chargées dynamiquement.
Randomize ET_EXEC base:
Toujours le même principe, mais pour l'adresse de base des exécutables lancés.
Cependant cette option peut causer une dégradation des performances et la détection des attaques peut causer de fausses alertes.
Deny writing to /dev/kmem, /dev/mem, and /dev/port:
Comme vous vous en doutez, cette option empêche l'écriture dans /dev/kmem, /dev/mem et /dev/port, diminuant ainsi beaucoup les risques d'attaques. Cependant, même si cette protection n'empêche pas le fonctionnement d'XFree, certains pilotes pour les cartes vidéos ont besoin d'écrire dans le BIOS (notamment les cartes Savage), et donc ne peuvent pas marcher avec cette option activé. Cette option empêche aussi le fonctionnement d'applications telles que VMWare.
Disable privileged I/O:
Cette options rendra les fonctions ioperm() et iopl() inopérantes. Malheureusement, XFree86 a besoin de ces fonctions et ne pourra donc pas fonctionner si cette option est activée (Il est probable que cela soit aussi le cas d'autres programmes).
Remove addresses from /proc/pid/[maps|stat]:
Cette option a pour but de rendre moins bavard le /proc au sujet des adresses mémoire des processus.
Hide kernel symbols:
Cette option empêche tout utilisateur n'ayant pas le CAP_SYS_MODULE, d'accéder aux informations sur les modules chargés et d'afficher les symbols du noyau.
(Le CAP_SYS_MODULE est une capacité, ceci étant expliqué ultérieurement dans le chapitre III sur les ACLs)
Cette option n'est réellement efficace que si d'autres fichiers tels que l'image du noyau, le System.map et le /proc/kcore sont inaccessibles aux utilisateurs.
ACL options
ou
Role based Access Control Options
Hide kernel processes:
Cette option permet de cacher aux utilisateurs tout les processus propres au noyau ou ayant le mode "h" (hidden), sauf pour l'utilisateur authentifié en tant qu'admin (pas root, mais administrateur sauce " gradm ") ou pour les processus ayant le droit de les voir (mode "v").
Cette option est à utiliser avec "gradm" qui est traité dans la IIIème partie de ce document.
Maximum tries before password lockout
Cette option permet de fixer le nombre de fois qu'un utilisateur peut tenter de s'authentifier en temps qu'administrateur avec " gradm " avant de se voir empêcher de se connecter en tant que tel pendant un certains temps.
Time to wait after max password tries, in seconds
Il s'agit du temps qu'un utilisateur doit attendre avant de pouvoir retenter de se connecter en administrateur par " gradm " après raté le nombre d'essais maximal de connexion.
Filesystem Protections
Proc restrictions:
Cette option permet de cacher aux utilisateurs tout les processus ne leur appartenant pas.
Restrict to user only:
Cette option spécifie que tout les utilisateurs sauf root sont concernés par la précédente option. Cette option les empêche aussi de voir les informations relatives au réseau et de voir les symboles du noyau, ainsi que les informations sur les modules.
Allow special group:
Permet à un groupe d'utilisateurs en particulier d'échapper à la règle.
Additional restrictions:
Empêche les utilisateurs normaux de voir les informations du CPU et des périphériques.
Linking restrictions: (linking_restrictions)
Ceci empêchera les utilisateurs de suivre des liens symboliques aboutissants sur des fichiers qui ne sont pas les leurs à moins qu'ils possèdent le répertoire contenant le fichier de destination.
FIFO restrictions: (fifo_restrictions)
Ceci empêche l'utilisateur d'écrire dans un FIFO qui ne lui appartient pas, à moins que cet utilisateur ne possède le répertoire contenant le FIFO.
Pour ceux qui ne le savent pas (c'était mon cas il y a un peu plus de 30secondes), FIFO signifie First In, First Out. Il s'agit en fait d'un fichier se comportant comme un tube et n'ayant donc pas de véritable existence sur le disque. Il permet notamment à des processus de communiquer entre eux (cf man fifo)
Chroot jail restrictions:
Permet d'accéder aux différentes options permettant de bloquer un processus dans une cage chroot.
Deny mount: (chroot_deny_mount)
Interdiction de monter une partition à l'intérieur du chroot.
Deny double-chroots: (chroot_deny_chroot)
Interdiction d'effectuer un chroot à l'intérieur d'un autre chroot, ceci étant le moyen le plus couramment utilisé pour sortir d'un chroot.
Deny pivot_root in chroot: (chroot_deny_pivot)
pivot_root() est une fonction similaire à chroot. Cette option permet donc d'interdire cette fonction.
Enforce chdir("/") on all chroots: (chroot_enforce_dir) Le super-utilisateur (root) peut facilement sortir d'une cage chroot avec la simple commande "cd ..". Cette option a pour but d'empêcher le root de descendre de l'arborescence en dessous du chroot().
Deny (f)chmod +s: (chroot_deny_chmod)
Empêche tout programme dans un chroot de mettre les bits suid ou sgid à un fichier.
Deny fchdir out of chroot: (chroot_deny_fchdir)
Fchdir() fonctionne comme la fonction chdir(), sauf qu'il utilise un pointeur de fichier à la place du path pour savoir où aller. Donc si cette fonction a un pointeur sur un répertoire hors du chroot, elle peut permettre au programme de sortir.
Cette option permet donc d'empêcher cela.
Deny mknod: (chroot_deny_mknod)
Mknod permet de créer des entrées de périphériques (comme celle dans le /dev), et peut donc permettre à un programme dans un chroot d'accéder tout de même à certaines périphériques dont les partitions. Cette option permet donc d'interdire l'usage de mknod dans un chroot.
Deny shmat() out of chroot: (chroot_deny_shmat)
Empêche le processus d'accéder à des segments de mémoire partager qui ont été créé en dehors du chroot.
Deny access to abstract AF_UNIX sockets out of chroot: (chroot_deny_unix)
Empêche le processus de ce connecter à des "sockets" de domain Unix.
Il s'agit de sockets servant à la communication entre processus sur une même machine.
Protect outside processes: (chroot_findtask)
Empêche le processus enfermé dans le chroot d'envoyer un quelconque signal (par ex un kill) à des processus externes au chroot.
Restrict priority changes: (chroot_restrict_nice)
Rend le processus interne au chroot incapable de changer la priorité d'un processus externe au chroot, et incapable d'augmenter la priorité d'un processus interne au chroot (dont lui-même).
Deny sysctl writes in chroot: (chroot_deny_sysctl)
Empêche le processus (et donc éventuellement un attaquant) d'écrire sur les entrées sysctl tel que le /proc.
Capability restrictions within chroot: (chroot_caps)
Empêche un processus d'insérer des modules dans le noyau, d'avoir des accès e/s "brutes", d'avoir des accès aux taches systèmes et d'administration, de redémarrer le système, changer l'heure du système, etc...
Kernel Auditing
Single group for auditing: (audit_group)
Permet de logguer toute activité (chdir, exec, mount) d'un groupe d'utilisateur.
Exec logging:(exec_logging)
Log toutes les exécutions de commandes. Cependant il ne faut pas perdre de vu que ce genre d'option peut générer beaucoup de logs dans certains cas.
Ressource logging:
Log toute tentative visant à dépasser les ressources du système.
Log execs within chroot: (chroot_execlog)
Log toutes les exécutions de commandes faites dans un chroot.
Chdir logging:(audit_chdir)
Log tout les changements de répertoire.
(Un)Mount logging:(audit_mount)
Log tout les (dé)montages de partitions.
IPC logging: (audit_ipc)
Log toutes les créations/destruction de queues de messages, sémaphores et de mémoire partagée.
Signal logging: (signal_logging)
Log tout les signaux transmis entre les processus.
Fork failure logging: (forkfail_logging)
Log toutes les tentatives de fork() échouées, ceci étant souvent du à des forks bombs.
Time change logging: (timechange_logging)
Log tout les changements d'heure effectué sur la machine, ceci servant parfois à cacher certaines modifications.
/proc/<pid>/ipaddr support
Cette option ajoute une nouvelle entrée dans chaque /proc/<pid>:
ipaddr
Ce fichier contiendra toutes les ips des personnes utilisant ce processus.
Cette information peut se révèler utile pour les Détecteur d'Intrusion pour effectuer une réponse distante à une attaque locale (Par exemple indiquer au firewall d'empêcher l'accès à tout les services de telle ip).
Seul le propriétaire du processus (et root si dans les ACLs il a la capacité " CAP_DAC_OVERRIDE " qui peut être retirée par l'intermédiaire du système RBAC) peut lire cette entrée.
J'ai experimenté cette option sans ACL, et il semblerait que le root puisse, par défaut dans ce cas, lire tout de même cette entrée.
Exécutable protection
Enforce RLIMIT_NPROC on execs: (execve_limiting)
Cette options permet de vérifier lors de l'exécution d'une commande, que le nombre de processus lancés par le processus d'origine ne franchi pas une certaine limites en ressources.
Dmesg restriction: (dmesg)
Empêche tout utilisateur autre que root d'utiliser dmesg.
Randomized pids: (rand_pids)
Chaque fois qu'un processus est créé, pour lui attribuer un numéro, Linux se contente de reprendre l'id du dernier processus créé et d'y ajouter 1, ceci a notamment pour effet que même après un redémarrage, les différents daemons tournants sur une machine garde le même pid, les rendant plus facilement repérables et donc vulnérables. Cette option permet donc au noyau de choisir des ids au hasard (enfin il s'agit d'un "pseudo-hasard")
Trusted path execution: (tpe)
Empêche les utilisateurs faisant partis du groupe spécifié de lancer des commandes qui n'ont pas pour propriétaire root.
Partially restrict non-root users: (tpe_restrict_all)
Tout les utilisateurs autre que root et n'appartenant pas au groupe spécifié précédemment n'ont le droit de lancer que des programmes appartenant à root, ou alors des programmes leur appartenant mais étant dans des répertoires non-accessibles aux autres.
Network Protections
Larger entropy pools:
Permet d'augmenter la taille du "fond commun d'entropie" servant à générer les nombres aléatoires. En activant cette option, les nombres aléatoires générés et utilisés par GrSecurity (ainsi qu' éventuellement d'autres parties du noyau Linux) seront de meilleurs qualités (moins prévisibles)
Truly random TCP ISN selection (rand_isns)
Lors de l'initialisation d'une connexion TCP, le serveur doit définir un nombre (ISN) qui sera transmis et incrémenter dans chaque packet de cette même connexion. Ceci permettant notamment d'éviter qu'un client se fasse passer pour un autre et permet aussi de se rendre compte quand un paquet est perdu (corrigé moi si je me trompe ?).
Cette option permet de choisir l'ISN à la manière de Open BSD (nombre aléatoire), rendant ce nombre moins prévisible.
Randomized IP IDs: (rand_ip_ids)
Si cette option est activé, les champs id de tout les packets ips sortant seront mis au hasard. Linux par défaut se contente d'incrémenter de 1 chaque packets envoyé, laissant la possibilité d'un scan de port intracable.
Randomized TCP source ports: (rand_tcp_src_ports)
Lorsque vous établissez une connexion TCP, un port est ouvert localement. Pour déterminer ce port, Linux se contente d'incrémenter de 1 par rapport au dernier port ouvert. Cette option permet à Linux de choisir ce port aléatoirement.
Randomized RPC XIDs: (rand_rpc)
Permet de rendre aléatoires les XIDs des RPCs (appels de fonction à distance)
Altered Ping IDs: (altered_pings)
L'id que Linux va utiliser pour répondre sera le même que celui contenu dans la requête ping. Ceci rendra plus difficile pour un attaquant de déterminer votre OS.
Socket restrictions:
Vous permet d'accéder aux options suivantes:
Deny any sockets to group: (socket_all)
Empêche les utilisateurs faisant partie du groupe spécifié d'ouvrir une socket, quel qu'elle soit: que ce soit ouvrir un port ou se connecter ailleurs
Deny client sockets to group: (socket_client)
Empêche les utilisateurs faisant partie du groupe spécifié d'ouvrir une connexion sur l'extérieur.
Deny server sockets to group: (socket_server)
Empêche les utilisateurs faisant partie du groupe spécifié d'ouvrir un port sur la machine.
Sysctl support
Sysctl support
Permet de modifier les réglagles de grsec à partir /proc/sys/kernel/grsecurity.
Si vous souhaitez continuer à installer/configurer grsec à l'aide de ce document, je vous recommande fortement de répondre [Y])
Logging options
Ils s'agit d'options concernant la manière dont grsec loggue les événements, je ne pense pas qu'il soit nécessaire que je détaille.
Après tout ça, il ne vous reste plus qu'à compiler votre noyau:
make dep modules bzImage modules_install install
Vous pouvez déjà ajuster votre configuration de lilo ou grub selon vos besoins, mais ne redémarrer pas tout de suite...
* 5ème étape: Et nan, c'est pas fini ...
Si vous avez activé l'option sysctl comme je vous l'ai recommandé, il vous reste maintenant à vous en servir.
Pour cela nous allons créer un script de démarrage qu'on placera dans /etc/init.d (personnellement je l'ai appelé 'grsec' tout bêtement).
NB:<!-- U --> On m'a fait remarquer qu'il était aussi possible d'utiliser le/etc/sysctl.conf pour ce genre de réglages
On commence par un classique:
#!/bin/sh
ensuite le but du jeu est d'activer les différentes options de grsec dans le /proc grâce à une série de commande du genre:
echo 1 > /proc/sys/kernel/grsecurity/[option]
("echo 0 [...]" pour les désactiver bien entendu)
J'ai précisé dans la précédente description des options leurs noms dans le /proc (cf ce qui est entre parenthèse après les noms des options). Si rien n'est préciser, il est probable que cette option ne soit pas changeable à partir du /proc
Donc par exemple pour activer "Randomized TCP source ports", on utilisera:
echo 1 > /proc/sys/kernel/grsecurity/rand_tcp_src_ports
Je vous recommande de le faire pour chaque options, même celle que vous souhaitez désactiver (echo 0). On est jamais trop prudent...
Une fois que vous avez tout spécifié dans votre script, il ne faut pas oublier de verrouiller GrSecurity et donc mettre en fin de script:
echo 1 > /proc/sys/kernel/grsecurity/grsec_lock
En pratique, ça donne:
#!/bin/sh echo Mise en place de Grsecurity echo Ce script a été fait pour l'exemple echo Si vous décidez de l'utiliser, n'oubliez surtout pas echo de l'ajuster à vos besoins # On déverrouille (pas obligatoire mais je recommande quand même de le faire) echo 0 > /proc/sys/kernel/grsecurity/grsec_lock # Chroot restrictions ... echo 1 > /proc/sys/kernel/grsecurity/linking_restrictions echo 1 > /proc/sys/kernel/grsecurity/fifo_restrictions echo 1 > /proc/sys/kernel/grsecurity/chroot_deny_mount echo 1 > /proc/sys/kernel/grsecurity/chroot_deny_chroot echo 1 > /proc/sys/kernel/grsecurity/chroot_deny_pivot echo 1 > /proc/sys/kernel/grsecurity/chroot_enforce_chdir echo 1 > /proc/sys/kernel/grsecurity/chroot_deny_chmod echo 1 > /proc/sys/kernel/grsecurity/chroot_deny_fchdir echo 1 > /proc/sys/kernel/grsecurity/chroot_deny_mknod echo 1 > /proc/sys/kernel/grsecurity/chroot_deny_shmat echo 1 > /proc/sys/kernel/grsecurity/chroot_deny_unix echo 1 > /proc/sys/kernel/grsecurity/chroot_findtask echo 1 > /proc/sys/kernel/grsecurity/chroot_restrict_nice echo 1 > /proc/sys/kernel/grsecurity/chroot_deny_sysctl echo 1 > /proc/sys/kernel/grsecurity/chroot_caps # Audit echo 0 > /proc/sys/kernel/grsecurity/audit_group echo 0 > /proc/sys/kernel/grsecurity/exec_logging echo 0 > /proc/sys/kernel/grsecurity/chroot_execlog echo 0 > /proc/sys/kernel/grsecurity/audit_chdir echo 0 > /proc/sys/kernel/grsecurity/audit_mount echo 0 > /proc/sys/kernel/grsecurity/audit_ipc echo 0 > /proc/sys/kernel/grsecurity/signal_logging echo 1 > /proc/sys/kernel/grsecurity/forkfail_logging echo 1 > /proc/sys/kernel/grsecurity/timechange_logging # Exécutable protections echo 1 > /proc/sys/kernel/grsecurity/execve_limiting echo 1 > /proc/sys/kernel/grsecurity/dmesg echo 1 > /proc/sys/kernel/grsecurity/rand_pids echo 0 > /proc/sys/kernel/grsecurity/tpe echo 0 > /proc/sys/kernel/grsecurity/tpe_restrict_all # Network Protections echo 1 > /proc/sys/kernel/grsecurity/rand_ip_ids echo 1 > /proc/sys/kernel/grsecurity/rand_tcp_src_ports echo 1 > /proc/sys/kernel/grsecurity/rand_rpc echo 1 > /proc/sys/kernel/grsecurity/altered_pings echo 0 > /proc/sys/kernel/grsecurity/socket_all echo 0 > /proc/sys/kernel/grsecurity/socket_client echo 0 > /proc/sys/kernel/grsecurity/socket_server echo Verrouillage... echo 1 > /proc/sys/kernel/grsecurity/grsec_lock echo Done
Il faut ensuite penser à rendre le script exécutable et illisible par d'autres utilisateurs que root:
chmod 700 /etc/init.d/grsec
Puis créer un lien dans /etc/rc2.d vers ce script pour qu'il s'exécute automatiquement au démarrage:
cd /etc/rc2.d ; ln -s /etc/init.d/grsec S90grsec
Maintenant il ne vous reste plus qu'à rebooter et voir si tout fonctionne comme vous le souhaitez.
L'utilisation de gradm et des ACLs n'est pas obligatoire pour avoir la protection de
grsec, et à moins que vous n'ayez besoin d'une sécurité des plus absolue
sur votre système, il me semble peu probable que vous décidiez de
l'utiliser (d'où le fait qu'il se trouve dans une partie à part).
Le but de l'ACL (Access Control List) est de limiter les droits de tout les utilisateurs autant que possible.
L'ACL permet notamment de préciser pour chaque répertoire, des modes d'accès précis (lecture seule, lecture/écriture, etc...) ainsi que de préciser des exceptions pour certains programmes.
Il permet aussi de spécifier pour chaque programmes des ressources plafonds ainsi que tout un tas d'autres trucs, dont certaines protections pour certaines processus particulier, la limitation de la capacité de certains processus, etc...
En fait, tout ça se résume plutôt bien dans la définition de ACL:
Access Control List.
Je vais être honnête, je ne l'ai pas mis en application (trop long à configurer, et le fait de devoir discuter de l'installation de chaque programme avec GrSec ne m'enchantait pas vraiment)
Ce document n'étant qu'une traduction (plus ou moins partielle) du document http://www.grsecurity.org/gracldoc.htm , je ne peux que vous recommandez d'aller le voir.
* 1ère étape : Apt-get
apt-get install gradm
(notez la difficulté de cette étape)
* 2ème étape : Mettre un mot de passe sur le système ACL de GrSec
gradm -P
(Encore une fois, c'est super dure)
* 3ème étape : Configurer le /etc/grsec/acl
Là par contre, ça rigole déjà moins...
Il faut savoir que le paquetage gradm contient déjà un fichier /etc/grsec/acl. Vous pouvez donc le reprendre et l'adaptez à vos besoins, ceci étant sans doute plus simple, vu que gradm vérifie que ce fichier n'autorise pas tout et n'importe quoi.
Je vous recommande d'ailleurs d'aller voir le /etc/grsec/acl fourni avant de lire la suite de cet article, dans le but d'avoir une meilleure idée de ce que ça donne en pratique.
Le fichier est formé de cette manière:
include <"fichier à inclure">
"chemin du sujet" "modes du sujet (optionnel)"
{
# Commentaire
"fichier ou répertoire objet" "modes de l'objet"
[+|-]"capacité"
"nom de la ressource" "limite basse" "limite haute"
connect {
"ip"/"netmask":"port inférieur"-"port supérieur" "type" "protocole"
}
bind {
"ip"/"netmask":"port inférieur"-"port supérieur" "type" "protocole"
}
}
Il faut savoir que l'ACL applique un principe d'héritage:
Par exemple ce qui s'applique au répertoire "/usr" s'appliquera aussi à ses sous-répertoires comme "/usr/bin", et ceci, à moins que ne soit explicitement donner des règles pour le sous-répertoire en question.
L'ACL supporte aussi les 'wildcards' telles que "?" et "*", par exemple "/dev/tty*". Ces 'wildcards' ne prennent effet que sur les fichiers présent au moment où le système ACL est activé.
Explication morceau par morceau:
Les commentaires:
Mettez simplement une # en début de ligne
"fichier à inclure":
GrAdm permet d'inclure des fichiers contenant eux-mêmes d'autres portions de la config. Cela permet de répartir la configuration sur plusieurs fichiers, la rendant parfois plus lisible. Normalement les "include" peuvent être mis n'importe-où dans le /etc/grsec/acl.
"chemin du sujet":
Le sujet peut être soit "/" et donc dans ce cas-là il s'agira de préciser les accès possible pour les programmes par défaut, soit être un programme, tel que "/sbin/init" par exemple, et il s'agira alors de définir les accès auquel lui a droit.
Vous _devez_ avoir un sujet "/" quelque part dans votre fichier.
"mode du sujet":
Il faut savoir que si vous ne précisez pas de mode (aussi bien pour le sujet que pour l'objet), les accès "FIND" (stat, chdir, filldir, etc...) seront permis, mais aucun autre accès ne sera permis.
h - Ce processus est caché et est seulement visible par les processus ayant le mode v.
v - Ce processus peut voir les processus cachés
p - Ce processus est protégé: Il peut seulement être tuer par un processus avec le mode k
k - Ce processus peut killer les processus protégés
l - Active le mode d'apprentissage pour ce processus
d - Protège les entrées /proc/"pid"/fd et le /proc/"pid"/mem des processus dans ce sujet
b - Active la comptabilité pour les processus dans ce sujet
P - Désactive la fonctionnalité "Paging based non-executable pages" dans ce sujet (voir la configuration de votre kernel)
S - Désactive la fonctionnalité "Segmentation based non-executable pages" dans ce sujet
M - Désactive la fonctionnalité "Restrict mprotect()" dans ce sujet
R - Désactive la fonctionnalité "Randomize mmap() base" dans ce sujet
G - Active la fonctionnalité "Emulate trampolines" dans ce sujet
X - Active la fonctionnalité "Randomize ET_EXEC base" dans ce sujet
O - Outrepasse les restrictions additionnelles de mmap() et ptrace() dans ce sujet
A - Protège la mémoire partagée de ce sujet. Aucun processus hors de ce sujet ne pourra accéder à la mémoire partagée.
K - Quand les processus internes à ce sujet génèrent une alerte, tuer les processus.
C - Quand les processus internes à ce sujet génèrent une alerte, tuer les processus et repérer l'IP de l'attaquant s'il y avait une ip connecté au processus.
T - S'assure qu'un processus ne pourra jamais exécuter un code de troyen
o - Outrepasser le système d'héritage de l'ACL
"fichier ou répertoire objet":
Fichier ou répertoire auxquels le programme spécifier en tant que sujet tentera sans doute d'accéder (les modes suivants définissants ses droits d'accès). Si le sujet est "/", alors il s'agira des accès possible par défaut aux programmes.
"modes de l'objet":
r - Cet objet peut être ouvert en lecture
w - Cet objet peut être ouvert en écriture
x - Cet objet peut être exécuté
a - Cet objet peut être ouvert en mode "ajout"
h - Cet objet est caché
t - Cet objet peut être ptraced (cf ptrace()), mais ne peut pas modifié la tâche en cours. "ptrace read-only" fait référence à ceci.
s - Les accès refusés à cet objet ne seront pas loggués.
i - Ce mode s'applique seulement au binaires: Quand l'objet est exécuté, il hérite des modes du sujet dans lequel il est contenu.
R - Log les accès en lecture réussis sur cet objet
W - Log les accès en écriture réussis sur cet objet
X - Log les exécutions réussi de cet objet
A - Log les ajouts réussi à cet objet
F - Log les "finds" réussi à cet objet
I - Log si l'héritage ACL de cet objet a réussi
Rappel:
Les modes s'appliquant sur "/bin" s'appliquent aussi sur "/bin/su" à moins que vous ayez préciser des modes pour "/bin/su". Pour plus de détails sur le fonctionnement de l'héritage, je vous recommande d'aller voir http://www.grsecurity.org/gracldoc.htm (et oui, c'est en anglais :P)
Note:
Le mode "i" pour les objets aura seulement un effet si l'application fait un fork() puis un execve() ou juste un execve(): Le mode "i" n'a donc aucun effet si l'application utilise la fonction system() (qui d'ailleurs est Mal(tm))
"[+|-] capacité":
Pour obtenir la liste complète des capacités, je vous recommande d'aller voir le document officiel: http://www.grsecurity.org/gracldoc.htm (vous ne pouvez pas les rater, c'est à la fin du document)
"nom de la ressource":
Utilisé pour limiter l'usage des ressources. Voici la liste des ressources limitables:
RES_CPU - Temps CPU en millisecondes
RES_FSIZE - Taille du fichier en octets
RES_DATA - Taille d'une donnée en octets
RES_STACK - Taille du tampon en octets
RES_CORE - Taille du core en octets
RES_RSS - Taille de la mémoire résidente utilisée
RES_NPROC - Nombre de processus
RES_NOFILE - Nombre de fichiers ouverts
RES_MEMLOCK - Taille de la mémoire verrouillée en octets
RES_AS - Espace d'adressage limite en octets
RES_LOCKS - Nombre de fichiers verrouillés
Les concepteurs suggèrent de garder surtout un oeil sur le nombres de fichiers, l'espace d'adressage limite, et le nombre de processus.
RES_CPU est la seule ressource acceptant le temps comme limite, par exemple:
100s = 100 secondes
25m = 25 minutes
65h = 65 heures
2d = 2 jours
Les autres ressources utilisent soit un nombre seul ou une taille en octets:
Tous peuvent être données en K (kilo), M (Méga), ou en G (Giga), que ce soit des octets ou de simple nombres.
Une autre valeur possible est "unlimited".
GrSecurity propose aussi une fausse ressource, dont le but est de limiter le nombre de plantage d'un programme:
RES_CRASH "nombre de crashs" "intervalle de temps"
Par exemple:
RES_CRASH 1 30m
empêchera le programme d'être exécuter pendant 30min après un plantage.
Il faut savoir que si le programme est lancé par un utilisateur normal, tout les processus de cet utilisateur seront killé, et il ne pourra se logguer pendant l'intervalle de temps défini. Si ce programme/processus n'est pas s[u|i|g]id (donc par exemple s'il est lancé par root), alors seul ce programme sera tué, et sera inexécutable pendant l'intervalle de temps.
L'ACL pour l'IP:
[connect|bind] {
"ip"/"netmask":"port_inférieur"-"port_supérieur" "type" "proto"
"ip"/"netmask":"port_inférieur"-"port_supérieur" "type" "proto"
[...]
}
"connect" permet de préciser les ips auxquelles à le droit de se connecter le processus.
"bind" permet de préciser sur quelle ip ont le droit de se connecter d'autres hôtes.
"ip":
Si vous avez choisi connect, alors il s'agit des ips sur lesquels peut se connecter le processus.
Si vous avez choisi bind, alors il s'agit de l'ip sur laquelle le processus est autorisé à écouter (donc l'ip de l'interface).
"netmask":
Il s'agit du masque réseau allant de paire avec l'ip. S'il est omis, la valeur par défaut est 32.
"port_inférieur"-"port_supérieur":
Intervalle de ports sur lesquels la connexion est autorisé. Si port_supérieur est omis, alors "port_inférieur" et "port_supérieur" prendront tout deux la valeur de "port_inférieur". Si les deux sont omis, 0 est utilisé pour "port_inférieur" et 65535 pour "port_supérieur".
"type":
Peut prendre comme valeur: "stream" (Tcp), "dgram" (Udp), "raw_sock" (Raw), ou "any_sock" (n'importe lequel).
"proto":
Peut prendre comme valeur n'importe quel nom de protocole donné dans /etc/protocols, notamment "raw_proto" ou "any_proto".
Si vous voulez empêcher le programme de se connecter (connect) ou d'ouvrir un port (bind), vous pouvez utilisez "disabled".
Quelques exemple:
connect {
disabled
}
bind {
192.168.1.2/24:80 stream tcp
}
connect {
192.168.1.2/24 stream dgram tcp udp
134.55.22.12/24:1024-65535 any_type any_proto
}
Voici une ACL que ma donné une de mes connaissances pour permettre à apache de fonctionner, bien entendu, si vous décidez de l'utiliser, il faudra l'adapter à vos besoins:
/usr/sbin/apache {
/dev/log rw
/etc h
/etc/passwd r
/etc/group r
/etc/apache rx
/etc/hosts r
/etc/hostname r
/etc/nsswitch.conf r
/etc/resolv.conf r
/etc/php4/apache/php.ini r
/etc/mime.types r
/usr/lib/cgi-bin rx
/home h
/var/www rx
/var/log/apache rwx
/root h
bind {
192.168.3.200:80-80 stream tcp
}
}
(Merci à asyd :)
Recommandations au sujet de l'ACL:
Il s'agit de recommandations faite par les concepteurs dans la documentation officielle:
- Essayer de retirer autant que possible des droits par rapport à ce que propose l'ACL fourni par défaut avec le paquetage gradm. Le plus vous en retirez, le plus root agira comme un utilisateur courant. Le plus de droits vous retirerez, le plus d'ACLs vous aurez à créer pour les programmes ayant besoin de ces droits.
- Utilisez les ACLs dans le répertoire "debian_secure_acls" de gradm si possible.
- Utilisez le mode apprenant. Il peut créer des ACLs mieux que vous.
- Les programmes administratifs, comme l'arrêt ou le redémarrage, devrait nécessiter une authentification plutôt que de donner à n'importe qui le droit de les lancer. Vous pouvez le faire en créant une ACL pour /sbin/shutdown, et en le rendant caché par tout les processus en mettant /sbin/shutdown h comme un objet dans votre ACL pour "/". Alors la seule manière que vous aurez d'accéder aux privilèges spéciaux de /sbin/shutdown sera d'entrer en mode administratif avec gradm -a (voir plus loin).
- Familiarisez-vous avec les capacités de Linux et et ce qu'elles permettent. Une liste et des descriptions de chacune de ces capacités est présenter à la fin de ce document: http://www.grsecurity.org/gracldoc.htm et aussi dans include/linux/capability.h du code source du noyau Linux.
Si vous souhaitez d'autres exemples d'ACL, sachez que des exemples sont donnés à la fin du document http://www.grsecurity.org/gracldoc.htm.
* 4ème étape: Utilisation de gradm
C'est bien beau d'avoir fait des ACLs à la pelle, maintenant, reste à s'en servir.
Voici une rapide description des options à donner à la ligne de commande à gradm (oui, je sais, vous pouvez facilement l'obtenir en faisant "gradm --help")
-E : Active le système d'ACL
Lorsque que vous utilisez cette option, GrAdm vérifie d'abord vos ACLs pour être sûr qu'il n'y ait pas de faille de sécurité potentielles.
-R : Relance le système ACL (marche seulement en mode d'administration)
-M <nom de fichier|uid> : Enlève une interdiction d'exécution sur un fichier ou sur un utilisateur (cf RES_CRASH)
-L <fichier de log> : Examine les logs d'apprentissage: Accepte un argument optionnel qui spécifie quel fichier log du noyau scanner. Les logs d'apprentissage sont enregistrés via syslog avec un niveau d'INFO. Si aucun argument n'est spécifier, gradm scannera votre /etc/syslog.conf pour trouver des logs à scanner. Cette option doit être utilisé avec -O
-O <nom de fichier|flux> : Spécifie le fichier de sortie pour les ACLs générés grâce au mode d'apprentissage. Les noms possibles sont "stdout", "stderr" ou un nom de fichier. Seulement utilisé avec -L
-D : Désactive le système d'ACL (généralement, quand on a besoin de cette commande, c'est qu'on ne peut déjà plus s'en servir)
-T <sujet> <objet> : Affiche les permissions pour un objet en fonction de son sujet.
-P : Réglage du mot de passe du système ACL (normalement vous l'avez déjà fait).
-a : Permet d'obtenir pour l'utilisateur en cours les pleins droits d'administration (aka admin mode)
-v : Affiche les informations concernant la version de gradm/grsec.
Seul le changement de mot de passe n'est pas possible en mode admin.
* 5ème étape: Le mode "apprenant"
Comme vous avez pu le constater, gradm offre la possibilité de générer des ACLs à partir des logs. Évidemment, c'est comme quand on voit le mot "gratuit", le premier réflexe est de se dire qu'il y a un piège quelque part ... on va voir ça ...
- Pour utiliser le mode apprenant, il suffit d'ajouter le mode "l" au sujet du processus pour lequel vous voulez activer l'apprentissage.
- Activez ensuite le système ACL
- Lancez l'application concernée plusieurs fois (selon la doc officielle le "plusieurs fois" est important).
- Si 4 accès ou plus sont fait dans un seul même répertoire, l'application obtiendra l'accès complet au répertoire.
- Une fois que vous avez lancé l'application et que vous l'avez utilisé de manière habituelle, désactiver le système ACL (gradm -D ou gradm -a, au choix)
- Taper ensuite
gradm -L -O /etc/grsec/acl
Ceci va placer la nouvelle ACLs apprises grâce aux logs à la fin du /etc/grsec/acl.
- Il suffit ensuite de simplement retirer l'ancienne ACL, et c'est fini.
Personnellement, je vous recommanderais tout de même de regarder avant ce qu'à produit le mode d'apprentissage en créant d'abord l'ACL dans un fichier à part.
Bien, maintenant que vous avez tout lu, je pense que je peux vous dire qu'il s'agit en fait de mon tout premier article.
Dans l'éventualité où j'aurais fait une erreur dans cet article, je vous prierais de me contacter par email ( jflesch@nerim.net ), merci d'avance.
http://www.grsecurity.org/
- Le site officiel
http://pageexec.virtualave.net/
- Le site officiel de PaX (et de chpax). GrSecurity utilise PaX pour toutes les options en rapport avec les pages mémoires non-exécutables, l'adressage aléatoire en mémoire, etc...