Papier en francais traitant de la securisation d'un environnement FreeBSD. Tres complet, travail vraiment reussi . [ Original et mise a jour à cette adresse :
http://www.minithins.net/warehouse/FreeBSD.txt ]
Securing FreeBSD step by step (for Dummies and even Geeks)
cns at minithins.net
Securing FreeBSD step by step (for Dummies and even Geeks)
cns at minithins.net
Last Update > 23/12/2003
> fix login.conf, huge grammatical clean up
"A physician, a civil engineer, and a computer scientist were arguing about
what was the oldest profession in the world. The physician remarked, "Well, in
the Bible, it says that God created Eve from a rib taken out of Adam. This
clearly required surgery, and so I can rightly claim that mine is the oldest
profession in the world." The civil engineer interrupted, and said, "But even
earlier in the book of Genesis, it states that God created the order of the
heavens and the earth from out of the chaos. This was the first and certainly
the most spectacular application of civil engineering. Therefore, fair doctor,
you are wrong : mine is the oldest profession in the world." The computer
scientist leaned back in her chair, smiled, and then said confidently, "Ah,
but who do you think created the chaos ?"
Résumé
Ce paper est issu comme beaucoup d'initiatives libres d'un besoin de la part
des auteurs. Dans cet article nous souhaitons faire partager ce que nous avons
traversé afin d'obtenir une machine FreeBSD configurée au mieux pour résister
a toutes sortes de menaces. C'est une sorte de compilation des connaissances
disparates dont nous avons nous même eu besoin. Comme le faisait remarquer
Bruce Scheiner, la sécurité est une processus, pas un produit ; c'est pourquoi
nous tentons dans ce document d'aborder un large panel de sujets et
d'utilisations en nous basant sur la branche FreeBSD 4.x-STABLE.
1. Burn out !
1.1. services
1.2. CVSup
1.3. (re)compilation et update
2. Tuning système
2.1. sysctl
2.1.1. securelevel et chflags
2.1.2. performances
2.2. gestion utilisateurs
2.2.1. adduser / rmuser / chpass / watch
2.2.2. quotas et login.conf
2.2.3. jail
2.3. intégrité
2.4. secure shell
2.5. syslog
2.6. cron
2.7. ipfw et natd
3. Outils
3.1. TCPdump
3.2. Nessus
3.3. lsof
3.4. stack smashing
3.5. tunneling
4. Conclusion
1. burn out !
Nous allons partir du fait que vous avez réussi à installer correctement
FreeBSD, et que vous êtes parvenu à une connexion Internet stable. Nous ne
donnerons donc aucune indication quant à ces phases. Dans ce chapitre, nous
nous concentrerons sur la configuration de base de FreeBSD, c'est-à-dire les
premières mesures que vous appliquerez dans une optique de sécurité, peu après
votre installation réussie.
1.1. services
Inetd est un super daemon qui permet de lancer plusieurs services reseau ainsi
qu'une partie de leur configuration comme ftpd, smptd ou telnetd. Le fichier
de configuration pour inetd est conservé dans /etc/inetd.conf. En voici un
extrait :
ftp stream tcp nowait root /usr/libexec/ftpd ftpd -l
#shell stream tcp nowait root /usr/libexec/rshd rshd
En règle générale, on place le caractere '#' devant une ligne que nous ne
voulons pas afin de la mettre en commentaire. Si nous ne desirons offrir aucun
de ces services - il est preferable de supprimer cette configuration de base
laxiste afin de repartir de zero - nous pouvons retirer inetd de notre fichier
de demarrage pour augmenter encore un peu la sécurité et la convivialité. Si
par ailleurs vous desirez tout de meme offrir un shell distant à quelques
utilisateurs, un chapitre entier couvre la configuration du sshd d'OpenSSH.
Enfin, en éclipsant inetd, nous décidons d'abandonner également TCP Wrappers
utilisé par défaut sous FreeBSD.
Tout d'abord il est utile de vérifier quel service tourne en écoute sur un
port actuellement. Pour cela nous allons utiliser l'utilitaire netstat qui
affiche une liste des ports et connexions actives. Nous l'allions à grep pour
préciser notre recherche.
# netstat -a | grep 'listen'
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp4 0 0 *:ssh *:* LISTEN
tcp4 0 0 *:ftp *:* LISTEN
tcp4 0 0 *:smtp *:* LISTEN
udp4 0 0 *:portmap *:* LISTEN
Comme vous le voyez nous ne croulons pas sous les services. Mais si votre
machine est destinée à devenir un serveur avec de multiples services, je vous
recommande de suivre notre solution. Bref, sur le même schéma que précédemment,
tous les services réseau que vous voudrez proposer à l'avenir tourneront sous
la forme de stand alone daemon, c'est-à-dire des daemons autonomes augmentant
la sécurité mais aussi simplifiant la configuration et améliorant la rapidité
de réponse des services en éliminant l'intermédiaire inetd. Pour éviter
qu'inetd ne se lance au démarrage, nous éditons le fichier /etc/rc.conf après
avoir effectué un rapide grep permettant de savoir si nous avons
effectivement besoin d'éditer :
# grep inetd /etc/rc.conf
inetd_enable="YES"
inetd_flags="-wW"
inetd est donc lancé au démarrage avec par ailleurs les options -wW signifiant
la capacité de filtrage des services internes et externes TCP via TCP Wrappers
que nous n'utiliseront pas non plus. Donc, toujours dans rc.conf,
inetd_enable="YES" devient inetd_enable="NO" et on met inetd_flags="-wW" en
commentaire. Nous désactivons également portmapper, un outil extrêmement
pratique dans le cadre de services RPC tels que NFS mais qui présentent un
nombre incalculable de vulnérabilités. Nous transformons donc la ligne
portmap_enable="YES" en NO. Ainsi inetd et portmapper ne seront pas exécutés
la prochaine fois que vous redémarrerez. Si vous voulez killer inetd de suite,
vous pouvez faire :
# killall inetd
Notez que c'est également dans rc.conf que vous pourrez configurer les
programmes ou scripts à lancer dès le démarrage. Selon le destin de votre
machine, ça peut être une bonne idée de manipuler les champs portmap_enable,
named_enable ou sendmail_enable.
1.2 CVSup
Le meilleur moyen d'obtenir un système sécurisé - en plus du fait d'avoir une
configuration bétonnée et de connaître FreeBSD sur le bout des doigts bien sûr
- reste de conserver les sources système et l'arborescence des ports à jour.
Ainsi dès qu'une vulnérabilité ou un quelconque problème apparaît au sein du
système ou encore qu'une nouvelle release ou plutôt qu'une nouvelle version
stable est sortie, vous maintenez votre système à jour et donc protégé au
mieux. Une bonne idée consécutive à l'update de votre système consiste à
s'abonner a la liste freebsd-security afin d'être tenu au courant des
derniers patchs. Notez également la liste freebsd-questions en français utile
à tous les utilisateurs francophones. Consultez les pages suivantes :
http://lists.freebsd.org/mailman/listinfo/freebsd-security-notifications
http://www.freebsd-fr.org/local-fr/www/spec/support/liste_diffusion.html
Maintenant nous allons voir un aspect extrêmement séduisant de la famille
*BSD : la mise à jour complète du système par le net. Pour cela nous
utiliserons tout d'abord un utilitaire nomme CVSup. Il permet l'update simple
de collections de fichiers à travers un réseau. Il peut efficacement et
précisément mirrorer tous types de fichiers incluant sources, binaires, hard
links, symlinks, et même des noeuds de périphériques. Le protocole de
communication en streaming et l'architecture multithreads font très
probablement de lui l'outil de mirroring le plus performant existant à ce
jour. En plus de toutes ces qualités, CVSup inclut des usages et des
optimisations spécifiquement conçues en fonction des repositories CVS. En
d'autres termes, CVSup se relie à la base de données principale de code
source FreeBSD et met à jour les fichiers source qui ont été modifié. Nous
effectuons donc un simple :
# cd /usr/ports/net/cvsup-bin && make install clean
en tant que root afin d'installer cet utilitaire.
Nous devons maintenant editer le cvs-upfile duquel cvsup recevra ses
directives pour l'update.
# mkdir /usr/share/cvsup/
# cp /usr/share/examples/cvsup/ports-supfile /usr/share/cvsup/
# cp /usr/share/examples/cvsup/doc-supfile /usr/share/cvsup/
# cp /usr/share/examples/cvsup/cvs-supfile /usr/share/cvsup/
# ee /usr/share/cvsup/cvs-supfile
------------------------------------ SNiP -------------------------------------
# nous allons rentrer une série de paramètres par défaut que nous utiliserons
# a chaque invocation de cvsup.
# nous rentrons ici le serveurs cvsup que nous voulons utiliser. Vous pouvez
# en choisir sur la liste presente sur
# http://www.freebsd.org/handbook/mirrors.html
*default host=cvsup.fr.FreeBSD.org
# ici nous informons cvsup du repertoire ou stocker les fichiers transferes
# plus quelques autres informations notamment celle de faire le menage apres
# download ou encore quel version nous desirons obtenir grace au champ Tag qui
# peut correspondre aussi bien a la version stable que current ou une version
# precedente. Enfin nous activons la compression de part notre faible bande
# passante.
*default base=/usr
*default prefix=/dist
*default release=cvs tag=RELENG_4
*default delete use-rel-suffix
*default compress
# ici nous decidons de mettre a jour l'ensemble de l'arborescence.
# Notez que les sources des programmes soumis a des limitations d'exportation
# (crypto) ne seront pas mis a jour.
src-all
------------------------------------ SNiP -------------------------------------
Pareil pour les ports ...
------------------------------------ SNiP -------------------------------------
# nous devons maintenant selectionner les ports que nous desirons mettre a jour.
# La collection de ports FreeBSD vous offre une multitude de programmes simples
# a installer et optimiser pour FreeBSD, cependant certains vous paraitront
# d'une utilite douteuse d'ou notre choix au cas par cas et la mise en
# commentaire de : ports-all
#ports-archivers
#ports-astro
ports-audio
ports-base
#ports-benchmarks
#ports-biology
#ports-cad
#ports-chinese
#ports-comms
#ports-converters
ports-databases
ports-deskutils
ports-devel
ports-editors
ports-emulators
ports-ftp
ports-french
#ports-games
#ports-german
ports-graphics
ports-irc
#ports-japanese
ports-java
#ports-korean
ports-lang
ports-mail
#ports-math
#ports-mbone
ports-misc
ports-net
ports-news
ports-palm
ports-picobsd
ports-print
#ports-russian
ports-security
ports-shells
ports-sysutils
ports-textproc
#ports-vietnamese
ports-www
# et on ne sait jamais, des fois que l'appel du graphisme soit trop fort...
ports-x11
ports-x11-clocks
ports-x11-fm
ports-x11-fonts
ports-x11-servers
ports-x11-toolkits
ports-x11-wm
------------------------------------ SNiP -------------------------------------
... puis la doc.
------------------------------------ SNiP -------------------------------------
# pour finir nous decidons de profiter de l'excellent travail de documentation
# issu du FreeBSD Documentation Project qui comporte notamment le FreeBSD
# handbook, veritable bible de cet OS et même traduit en francais :)
doc-all
------------------------------------ SNiP -------------------------------------
Nous en profitons également pour éditer le fichier /etc/make.conf afin de nous
assurer de la presence de certaines variables.
# cp /etc/default/make.conf /etc/
# ee /etc/make.conf
------------------------------------ SNiP -------------------------------------
INSTALL=install -C -S -s
PPP_NOSUID= true
ENABLE_SUID_SSH= true
ENABLE_SUID_NEWGRP= true
NO_FORTRAN= true # do not build g77 and related libraries
NO_I4B= true # do not build isdn4bsd package
NO_IPFILTER= true # do not build IP Filter package
NO_KERBEROS= true # do not build and install Kerberos 5 (KTH Heimdal)
NO_OBJC= true # do not build Objective C support
NO_SENDMAIL= true # do not build sendmail and related programs
NOGAMES= true # do not build games (games/ subdir)
COMPAT1X= no
COMPAT20= yes
COMPAT21= yes
COMPAT22= yes
COMPAT3X= yes
MAKE_RSAINTL= yes # RSA (public key exchange)
USA_RESIDENT= no
SUP_UPDATE= yes
SUP= /usr/local/bin/cvsup
SUPFLAGS= -g -L 2
SUPFILE= /usr/share/cvsup/cvs-supfile
PORTSSUPFILE= /usr/share/cvsup/ports-supfile
DOCSUPFILE= /usr/share/cvsup/doc-supfile
------------------------------------ SNiP -------------------------------------
Vous pouvez vous amuser avec les nombreux exemples de supfile et de refuse
disponibles dans le répertoire examples, puis, une fois votre paramétrage
effectué, il ne vous reste plus qu'à lancer une update :
# cd /usr/src && make update
Notez bien que la totalité du système est mis à jour (ou tout du moins les
sources si NO_DOCUPDATE et NO_PORTSUPDATE sont mis à "yes"). SUPFILE,
DOCSUPFILE et PORTSSUPFILE permet simplement de filtrer les modules qui
seront mis à jour pour les sources, la documentation et le ports tree,
respectivement.
1.3. (re)compilation et update
Maintenant que nous avons une arborescence des sources et de la port collection
correctement mis à jour, il ne nous reste plus (sic) qu'à 'construire' cette
arborescence.
Tout d'abord nous allons réellement construire l'ensemble des sources de notre
systeme de base :
# cd /usr/src && make buildworld
Cette opération assez importante peut durer plusieurs heures. Sur un Celeron
400, il aura fallu un peu plus d'une heure et demie. Bref le nombre de verres
que vous prendrez dépendra de la puissance de votre machine.
Nous nous attelons maintenant à la configuration et la compilation du kernel.
Pour les configurations ultérieures et des performances optimales, nous vous
recommandons de sélectionner les options suivantes dans votre fichier de
configuration kernel situé dans le répertoire /sys/votre_architecture/conf.
Afin de pouvoir toujours revenir en arrière avec une configuration
fonctionnelle, nous éditerons une copie de GENERIC, à partir de laquelle nous
compilerons.
# cd /sys/i386/conf && cp GENERIC LSD
# ee LSD
------------------------------------ SNiP -------------------------------------
options INET
options INET6
options IPSEC
options IPSEC_ESP
options IPSEC_FILTERGIF
options IPFIREWALL
options IPFIREWALL_VERBOSE
options IPFIREWALL_VERBOSE_LIMIT=30
options IPFIREWALL_FORWARD
options IPSTEALTH
options BRIDGE
options IPDIVERT
options DUMMYNET
#options IPFIREWALL_DEFAULT_TO_ACCEPT
options ACCEPT_FILTER_DATA
options ACCEPT_FILTER_HTTP
options NETGRAPH
options NETGRAPH_ONE2MANY
options NETGRAPH_PPPOE
options NETGRAPH_HOLE
options NETGRAPH_ECHO
options NETGRAPH_TEE
options NETGRAPH_TTY
options NETGRAPH_ASYNC
options NETGRAPH_INTERFACE
options TCP_DROP_SYNFIN
options ICMP_BANDLIM
options RANDOM_IP_ID
options SC_DISABLE_DDBKEY
options SC_DISABLE_REBOOT
options SC_NO_HISTORY
options NO_LKM
options NO_KLD
options QUOTA
options SOFTUPDATES
options UFS_DIRHASH
options COMPAT_LINUX
options DDB
options DEVICE_POLLING
maxusers 0
options HZ=1000
options NMBCLUSTERS=32768
pseudo-device snp 4
# high because of all the security tools
pseudo-device bpf 10
# high because of IPSec
pseudo-device gif 10
pseudo-device faith 1
pseudo-device stf 1
------------------------------------ SNiP -------------------------------------
Dans l'ordre, nous sélectionnons le support IPv4, IPv6, IPSEC et ESP. Puis nous
activons le support IPFW (que vous pouvez décider de remplacer par IPFilter non
traité dans cet article) avec l'envoi des messages à syslog limité à 30 fois la
même occurrence. Nous aurons eu soin avant cela de permettre à IPFW de filtrer
les paquets encapsulés avec IPSEC et transitant via des interfaces gif, tout
ceci depuis FreeBSD 4.9. Le forwarding est aussi activé ainsi que le forwarding
caché (passant un paquet sans décroître son TTL), tout comme les divert sockets
permettant de modifier le transit d'un paquet dans le kernel ; et enfin le
support de dummynet, le traffic shaper basique du système. Nous activons ensuite
les accept filters qui accélère le processus d'admission de certains types de
connexions (comme HTTP) en les plaçant directement dans le kernel. Notez que
mi-2002, Luigi Rizzo a totalement réécrit les mécanismes internes d'ipfw afin
d'en doubler la vitesse et de le rendre facilement extensible via un jeu de
microinstructions similaires à BPF. Ce code a été backporté sur stable et se
trouve totalement compatible avec vos rulesets. Bien qu'encore non documenté,
vous pouvez l'activer en plaçant l'option IPFW2 dans votre configuration.
Après cela, nous activons la cohorte de noeuds du sous-système NetGraph qui
permet des manipulations complexes au niveau réseau à l'aide de nodes héritant
des particularités de leur type (hooks possibles, traitement du trafic à chaque
hook, interprétation des messages de contrôle...) qui peuvent être chaînés à
travers des hooks pour constituer une suite d'edges : un graphe. Plus
d'informations et la descriptions des nodes dans la manpage netgraph(4).
Nous enchaînons avec quelques sécurités réseau, d'abord, comme le rejet de
certains paquets forgés (SYN/FIN) permettant la reconnaissance d'OS, la
limitation, via sysctl, d'émission de paquets ICMP afin de ne pas servir de
réflecteur lors d'un DoS, et la génération aléatoire des IP ID pour réduire les
opportunités de scanning. Puis sécurité physique avec la désactivation des
séquences clavier de debugging et de redémarrage, ainsi que la désactivation du
backscrolling pour les terminaux virtuels. Enfin, sécurité système avec la
désactivation des LKM ; et même des KLD si vous appliquez le patch suivant
http://people.freebsd.org/~cjc/kld_stable.patch.
Suivent l'activation des quotas disque, du code de compatibilité Linux via
l'émulation de certains appels système et du debugger kernel DDB. Nous
vérifions aussi l'activation des SoftUpdates, méthode d'écriture et de lecture
asynchrone résolvant les problèmes liés aux metadata et à leur perte.
L'approche de Linux est la journalisation (concept hérité des base de données)
qui consiste à écrire les mises à jour de metadata avec leurs dépendances dans
une partie distincte du système de fichier : le journal. Quand les metadata
sont prêtes, elles sont effectivement écrites. Le système de fichiers de
FreeBSD nommé UFS utilise une approche différente (inspirée de CVS) dans
laquelle les opérations d'écriture ou de lecture sont placées dans une file
d'attente divisée en un buffer d'attente et un buffer de vérification des
dépendances. Si un bloc appartient à une boucle de dépendances, il est rejeté
dans le buffer d'attente. Cette approche permettra de plus à l'avenir des
redémarrage suite à un crash avec un fsck fonctionnant en tâche de fond.
Pour de plus amples explications, voir http://www.di.ens.fr/~pornin/jfs.html.
Toujours au niveau système, vous apprécierez le device polling permettant
d'améliorer les performances kernel en limitant les interruptions et donc le
changement de contexte et l'appel à un gestionnaire d'interruption. A la place,
les périphériques sont sondés aux moments opportuns comme les interruptions
d'horloge, les appels système ou pendant les périodes de non-activité.
Notez enfin que le nombres maximal d'utilisateurs est placé à 0 pour qu'il soit
calculé au moment du boot en fonction de la mémoire physique disponible. Cette
variable ainsi que le nombre de clusters du système de fichiers sont utilisées
pour calculer l'allocation de certaines ressources mémoire. La fréquence
d'horloge est ensuite placée à 1000 Hz pour augmenter l'acuité du device
polling (et aussi limiter les burst si vous utilisez ALTQ). Viennent enfin les
pseudo-devices snoop et bpf pour la surveillance respective des tty et des
trames ethernet, et gif, faith et stf pour le tunneling v6/v4.
Certaines options seront déjà présentes, nous ne faisons que les vérifier. Vous
pouvez également réfléchir à mettre en commentaire le support procfs et NFS qui
peuvent créer d'éventuelles vulnérabilités dans le système, à moins bien sûr
que vous n'en ayez besoin. Pour examiner l'ensemble des options kernel
disponibles, référez vous au fichier LINT dans le même répertoire que GENERIC.
Par la séquence de commandes suivantes, nous construisons successivement le
kernel LSD puis nous l'installons et enfin nous le protégeons à l'aide des
flags immutables tout en nettoyant le système des fichiers générés par
l'install.
# cd /usr/src && make buildkernel KERNCONF=LSD && make installkernel
KERNCONF=LSD && make clean
Nous en avons fini avec la première partie de la recompilation complète du
système. Le système mis à jour est désormais fin prêt à être installé.
Cependant pour plus de sûreté il est recommandé d'effectuer la suite des
opérations en single-user mode. Pour ce faire au moment du prompt annonçant le
boot, pressez la barre d'espace pour entrer dans le menu de boot puis tapez
'boot -s'. Cette manoeuvre est recommandée pour chaque mise à jour ou
manipulation entraînant une reconstruction générale du système.
# reboot
La commande suivante installe donc l'ensemble du système de base mis à jour.
Le buildworld précédent correspondait à la compilation des sources (d'où sa
durée) tandis qu'ici nous nous contentons d'installer les binaires générés
(d'où une moindre attente).
# cd /usr/src && make installworld
Nous appliquons ensuite le script mergemaster, très pratique puisqu'il
effectue une comparaison entre les anciens fichiers de configuration et ceux
par défaut de l'installation. Tout cela afin de mettre à jour la configuration
du nouveau système et nous éviter de recommencer un travail fastidieux.
# cd /usr/src/usr.sbin/mergemaster
# ./mergemaster -sv -D /etc/
Voilà, le système est fin prêt pour attaquer sa réelle configuration. Nous
redémarrons une nouvelle fois afin de repasser en multiuser mode.
# reboot
Reportez-vous au handbook en cas de problèmes :
http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/makeworld.html.
2. Tuning Système
Maintenant que notre système est comme neuf et on ne peut plus à jour, il ne
nous reste plus qu'à entamer sa réelle sécurisation. Pour cela nous allons
d'abord voir ce que nous pouvons faire par défaut avec le système de base afin
d'augmenter la sécurité de notre système et de limiter se fenêtre d'exposition
aux attaques.
2.1. sysctl
Sysctl est un outil extrêmement pratique au sein de FreeBSD puisqu'il va nous
permettre de vérifier ou de manipuler l'état du kernel à chaud. Les
informations sont stockées et affichées à travers une Management Information
Base ou MIB selon le même modèle que SNMP. Par exemple pour afficher une liste
des différentes variables d'état kernel, il vous suffit d'effectuer un simple
# sysctl -a
de la même manière que vous utiliseriez un ls. Notez que vous pouvez préciser
l'entrée de la MIB si vous la connaissez juste après l'option afin de
n'afficher qu'elle. Suivant le principe des MIB, vous pouvez réduire
l'affichage en précisant un champ de la MIB. Par exemple pour afficher toutes
les entrées en rapport avec IP
# sysctl net.inet.ip.*
Notez aussi que certaines variables ne sont pas modifiables et que certaines
entrées de la MIB sont sous forme de tableaux utilisés à l'occasion par ps,
netsat ou systat. Enfin, pour obtenir une liste des variables sysctl que vous
pouvez modifier, consultez la page de manuel de sysctl.
2.1.1. securelevel et chflags
L'une des fonctionnalités intéressantes de FreeBSD consiste en l'établissement
de secure level au sein du système. Il existe ainsi 5 niveaux de sécurité au
sein de FreeBSD qui ne peuvent pas être diminués sans relancer init. Ils
peuvent cependant être augmentés par un processus root via la MIB sysctl, et
ce même en cours d'exécution.
Pour définir le securelevel mis en place par init, modifiez les lignes
suivantes dans rc.conf :
kern_securelevel_enable="YES"
kern_securelevel="N"
N représente ici l'entier correspondant à l'un des 5 entiers possibles.
Remplacez-le par le niveau qui vous convient. Puis si vous souhaitez l'élever
une fois votre système initialisé, modifiez l'entrée sysctl suivante :
# sysctl -w kern.securelevel=N
Outre des limitations inscrites dans le code kernel, donc inchangeable, propres
à chacun d'eux, chaque level définit également les opérations possibles sur des
file flags, attributs de fichiers permettant d'améliorer la sécurité fournie
par les classiques permissions Unix. Ci-dessous, les 5 niveaux et leurs
limitations :
- -1 qui instaure le mode insecure (0) de manière permanente. C'est la valeur
par défaut.
- 0 indique le mode insecure dans lequel les files flags 'immutable' et
'system append only' peuvent être retirés et où l'on peut effectuer des
opérations de lecture/écriture sur tous les périphériques avec pour seule
restriction les droits déjà instaurés, par exemple, dans la fstab.
- 1 indique nous sommes en secure mode dans lequel les flags 'system immutable'
et 'system append only' ne peuvent être désactivés. L'accès à /dev/mem et
/dev/kmem est interdit en écriture et les KLD ne peuvent plus être chargés ou
déchargés.
- 2 instaure le highly secure mode qui est strictement le même que le secure
mode à la différence près que les seules opérations désormais effectuées sur
les disques sont le montage et démontage.
- 3 signifie l'instauration du network secure mode qui est similaire au level
précédent avec en plus l'impossibilité de modifier les règles ipfw ou la
configuration du traffic shaper basé sur ipfw dummynet.
Pour une station de travail, l'utilisation devient problématique dès le
securelevel 1. Par exemple, XFree86 peut nécessiter l'accès à /dev/mem alors
que cela lui est interdit. Les niveaux suivants sont adaptés à des serveurs, et
le dernier est plus particulièrement destiné à une passerelle. Notez le niveau
2, très restrictif, qui force l'accès des disques en read-only. A ce niveau,
même un serveur risque de se voir perturbé par les securelevel, encore plus
s’il nécessite des compilations ou modifications de configuration régulières.
Notez que le niveau protège très bien de la plupart des backdoors basées sur
des modules kernel. Il pourrait cependant être judicieusement de remplacer ou
d'ajouter l'option kernel NO_LKM.
Pour paramétrer les file flags sur vos fichiers en fonction de ces levels, il
vous faudra utiliser la commande chflags. Les flags disponibles sont listés
ci-après.
- arch, uniquement utilisable par root, transforme le fichier en archive.
- opaque, rend le fichier "opaque" à certaine lecture (utile contre la lecture
par d'autres applications) et modifiable uniquement par l'owner ou le root.
- nodump, permet d'interdire un backup du fichier via l'utilitaire dump.
Modifiable uniquement par le owner ou le root.
- sappnd, instaure le flag system append-only uniquement modifiable par le root
en securelevel supérieur à 0. Append signifie qu'on ne peut que rajouter des
données et non en retirer.
- schg place le flag system immutable qui, comme son nom l'indique, est censé
empêcher toute évènement. Modifiable par le root uniquement en niveau 0.
- sunlnk permet d'interdire la suppression d'un fichier, sachant que cette
option n'est modifiable que par le root
- uappnd, uchg et uunlnk sont les pendant respectifs de sappnd, schg et sunlnk.
La différence réside dans le fait que, outre le root, le owner du fichier a
également le droit de modifier les file flags.
La syntaxe pourra par exemple être la suivante :
# chflags -RH schg /bin
# chflags -RH schg /sbin
# chflags -RH schg /usr/libexec
# chflags -RH schg /usr/lib
# chflags -RH schg /usr/share/lib
# chflags -RH schg /boot
# chflags -RH sappnd /var/log/*
# chflags -RH sappnd /home/*/.*history
# chflags schg /kernel
Notez qu'en effectuant un man chflags, vous découvrez les quelques options -
notamment la récursivité - que propose cette commande. Pour retirer un file
flag ce sont les mêmes options avec le prefix no tel que nosappnd. Les file
flags sont intéressants à placer sur certains fichiers sensibles précis ou
alors carrément sur un répertoire dont vous souhaitez vous assurer de
l'intégrité et qui sera rarement modifié. Dans l'exemple, R et H permettent de
suivre les liens symboliques et ce récursivement, la commande étant appliquée à
des répertoires entiers de binaires.
Dernier détail qui n'a pas grand chose à voir avec sysctl mais qui importe
beaucoup dans la gestion des droits et des fichiers. Vous avez le loisir de
modifier la fstab afin de monter vos diverses partitions avec certaines
options. Sous FreeBSD, au lieu de ne créer qu'une unique partition root /, le
système crée simultanément une partition /usr et /var. Vous pouvez définir dans
votre fstab pour l'ensemble de vos systèmes de fichiers :
- les droits d'écriture avec l'option rw pour read-write, ou ro pour read-only.
- les droits d'exécution avec l'option noexec.
- les privilèges accordés avec l'option nosuid.
# ee /etc/fstab
#device mountpoint fs options dump pass
/dev/ad0s2b none swap sw 0 0
/dev/ad0s2a / ufs rw 2 2
/dev/ad0s2f /usr ufs rw,nodev 2 2
/dev/ad0s2c /home ufs rw,nosuid,nodev,userquota 2 1
/dev/ad0s2e /var ufs rw,noexec,nosuid,nodev 2 2
/dev/acd0c /cdrom cd9660 ro,noauto 0
Nous limitons ici l'exécution dans /var afin d'éviter qu'un intrus tente d'y
placer des binaires et nous limitons la présence de binaires suid ou de devices
dans les autres répertoires majeurs.
Notez au passage que les soft updates que nous avons mis en place dans notre
configuration kernel ne s'activent pas via la fstab mais grâce à l'utilitaire
tunefs qui modifie directement, et de manière persistante, l'entête du système
de fichier. Pour effectivement activer ces soft updates, suivez la ligne
suivante :
# tunefs -n enable /usr
# tunefs -n enable /home
Remplacez alors enable par disable pour désactiver cette option.
2.1.3. Performances
Sysctl peut également nous apporter une aide précieuse dans la configuration
système et réseau à des fins de performances élevées. Il va ainsi nous
permettre d'activer certaines capacités réseau que supporte parfaitement la
pile TCP/IP BSD - qui est cela dit en passant certainement la plus stable, la
plus performante et la plus standard des piles TCP/IP - mais qui ne sont pas
activées par défaut.
La première entrée intéressante est l'option log_in_vain qui va loguer à
travers une simple entrée dans le fichier de log correspondant de syslogd,
toute tentative d'accès à un service même si aucun service n'est à l'écoute sur
le port de la tentative d'accès. Ceci peut nous permettre dans un environnement
sécurisé, allié de préférence avec un outil d'analyse de log tel que logcheck
ou ASAX, de repérer des tentatives de network mapping même si nous avons un
minimum de services disponibles et qui plus est un firewall. Cependant je ferai
remarquer 2 difficultés : tout d'abord log_in_vain ne logue en réalité que les
paquets avec un flag SYN, ce qui n'est pas assez pour réellement détecter un
scan. Et d'autre part, dans un environnement "chaud" comme une machine servant
de passerelle ou un serveur au sein d'une DMZ, l'utilisation de log_in_vain
peut entraîner une quantité de log assez impressionnante et capable d'occuper un
analyste ou un administrateur sans outils d'analyse pendant des semaines. Mais
au sein d'un réseau d'hors et déjà sécurisé ou sur une machine critique, cette
capacité de log peut être intéressante. Pour l'activer, il vous suffit de saisir :
# sysctl -w net.inet.tcp.log_in_vain=1
# sysctl -w net.inet.udp.log_in_vain=1
Les astuces suivantes sont intéressantes si votre machine doit servir de
passerelle, de filtre ou de load balancer pour d'autres machines. La commande
suivante vous offre la possibilité d'activer le forwarding IP et donc de
transformer notre machine en gateway ce qui s'avérera utile pour le partage de
connexion ou le déploiement d'une jail. Vous pouvez lui adjoindre l'entrée
fastforwarding qui active un système de cache des routes menant à des adresses
externes au réseau local. L'intérêt est de contourner de cette manière
l'inspection par la couche IP pour obtenir un passage direct des trames entre
les niveaux 2 des interfaces de la passerelle.
# sysctl -w net.inet.ip.forwarding=1
# sysctl -w net.inet.fastforwarding=1
Les entrées suivantes sont particulièrement utiles dans le cadre d'un serveur
qui nécessité une haute disponibilité ou une grande fiabilité. En effet, nous
allons apporter à notre machine le support des extensions TCP pour hautes
performances. Ces extensions sont décrites dans la RFC 1323 que je vous
recommande d'étudier. Elles sont constituées de 3 extensions. La première est
le champ Window Scale qui est un facteur appliqué au champ Window Size et utile
sur les Large Fat Network (LFN) afin d'optimiser le flux de donnees sur ces
grands reseaux et d'apporter un meilleur contrôle en multipliant la Window
Size. Nous trouvons ensuite 2 options extrêmement utiles dans le cas
d'utilisation de load balancing en fournissant des informations aux algorithmes
de répartition de charge. Le Round-Trip Time Mesurement (RTTM) et le Protection
Against Wrapper Sequence Numbers (PAWS) se basent tous les 2 sur l'adjonction
d'une option de timestamp aux segments TCP. Avec de simples vérifications de
timestamp on peut ainsi calculer le temps d'aller retour entre 2 ACK et ainsi
optimiser le flux ou modifier la route. On peut également se prévenir du
hijacking, de l'overlapping et surtout du rejeu en effectuant une double
vérification sur le numéro de séquence et le timestamp. Ces options viennent
s'ajouter à la suite d'algorithmes NewReno, évolution de la pile Reno,
permettant de détecter et corriger une congestion dans le réseau en jouant sur
la perte de paquets, les délais et les tailles de fenêtre TCP. L'unique bémol
est que ces options ne fonctionnent bien sûr qu'entre des machines les
supportant toutes les 2 de manière similaire, or elles ne semblent pas être
très utilisées - notez que la branche 4.x supporte la RFC 1323 par défaut
depuis la release 4.4 - et enfin vous pourriez risquer des désagréments face à
certains firewalls ou plugins de normalisation de trafic s'ils ne reconnaissent
pas ces options. Cependant nous décidons de l'aborder dans cet article afin de
faciliter sa diffusion et nous l'appliquons à notre système par acquis de
conscience ! Vous trouverez ensuite une entrée récente qui force FreeBSD à
calculer, pour chaque connexion TCP, la quantité de données en cours de
transmission dans le réseau (à partir du produit delay*bw), afin de limiter
l'envoi de paquets à même d'entraîner une surcharge non pertinente des routeurs
et/ou switchs présent sur la route. Cette configuration rapproche alors le
comportement de FreeBSD de la suite d'algorithmes TCP Vegas. Nous n'avons plus
ensuite qu'à augmenter les tailles par défaut de nos buffers d'envoi et de
réception (aussi bien pour TCP que pour UDP), qui ont une influence directe sur
le champ TCP window size. Du fait de l'influence possible de ces valeurs sur le
délai, il est recommandé d'expérimenter plusieurs valeurs, en suivant par
exemple la règle wnd = bw / 8 * RTT. Par exemple, nous avons volontairement
limité la taille des buffers pour UDP qui ne possède pas de mécanisme de
détection et évitement de congestion et s'y trouve donc plus sensible. Nous
avons également attribué des valeurs différentes aux buffers d'envoi et de
réception pour TCP, la vitesse de download se trouvant souvent plus élevée que
celle d'upload (pensez aux lignes xDSL). Pour finir, les deux dernières entrées
sysctl indiquent de ne pas générer de paquets avec l'option source route, ni de
les accepter, cette option IP facilitant le spoofing déjà évoqué en faisant
remonter les paquets IP strictement par le chemin utilisé à l'aller.
Pour tout cela, il vous suffit d'effectuer les commandes suivantes :
# sysctl -w net.inet.tcp.rfc1323=1
# sysctl -w net.inet.tcp.newreno=1
# sysctl -w net.inet.tcp.inflight_enable=1
# sysctl -w net.inet.tcp.inflight_min=6144
# sysctl -w net.inet.tcp.sendspace=32768
# sysctl -w net.inet.tcp.recvspace=65535
# sysctl -w net.inet.udp.sendspace=32768
# sysctl -w net.inet.udp.recvspace=32768
# sysctl -w net.inet.udp.maxdgram=28672
# sysctl -w net.inet.ip.sourceroute=0
# sysctl -w net.inet.ip.accept_sourceroute=0
Ensuite, nous activons l'implémentation de la RFC 1948 appliquant la
recommandation de Steve Bellovin sur la génération aléatoire d'ISN selon
l'équation ISN = M + F(localhost,localport,remotehost,remoteport) où M est un
timestamp. Cependant, la sécurité de cette recommandation repose
essentiellement sur le caractère aléatoire de la clé secrète et la puissance de
l'algorithme de hashage. En effet, l'étude de Michal Zalewski
(http://razor.bindview.com/publish/papers/tcpseq.html), concernant
l'utilisation des attracteurs étranges à des fins de construction de spoofing
sets répondant au problème de prédiction d'ISN TCP de manière aveugle, a
démontré qu'avec la liberté laissée par la recommandation de ne générer une clé
secrète qu'au démarrage seulement et avec la réutilisation des adresses IPv4,
il est possible pour un serveur au long uptime qu'un attaquant puisse créer un
attracteur étrange assez large pour s'assurer d'un bon taux de réussite en
utilisant la même adresse IP source. Malgré l'absence de démonstrations
mathématiques pour cette étude, nous activons la régénération de secret à un
intervalle de 3600 secondes. Sachez que la phase de régénération brise le
mécanismes de recyclage TIME_WAIT, permettant de purger avant les 240 secondes
réglementaires les connexions TCP en cours de fermeture (état TIME_WAIT),
allouant donc des ressources un peu plus longtemps. A titre personnel je me
demande aussi de quelle manière le projet CBOSS a concilié l'intégration des
syncookies dans FreeBSD à partir de la release 4.5 avec le respect de la RFC
1948. Nous rappelons enfin les différentes entrées relatives aux mécanismes de
syncookies et de syncache limitant fortement les risques liés au SYN flood tout
en améliorant le fonctionnement normal.
# sysctl -w net.inet.tcp.strict_rfc1948=1
# sysctl -w net.inet.tcp.isn_reseed_interval=1800
# sysctl -w net.inet.tcp.syncookies=1
# sysctl -w net.inet.tcp.syncache.hashsize=512
# sysctl -w net.inet.tcp.syncache.cachelimit=15359
# sysctl -w net.inet.tcp.syncache.bucketlimit=30
# sysctl -w net.inet.tcp.syncache.rexmtlimit=3
Nous décidons maintenant de nous protéger face à certaines tentatives de DoS
ainsi que de diverses techniques de network mapping. A l'aide des lignes
suivantes, vous pourrez donc notamment modifier la valeur de TTL par défaut,
qui peut être utilisé pour identifier l'OS, ou interdire les réponses aux ICMP
mask reply menant à une éventuelle cartographie réseau, mais aussi aux ICMP
broadcast, très souvent source de smurf ou DoS par amplification, et de mettre
la limite maximale de paquets ICMP en réponse à 200 par seconde. Pour TCP, nous
activons les delayed acknowledgments, restreignant l'inclination du système à
envoyer des ACK pour chaque segment reçu. Ceci permet d'éviter le Silly Window
Syndrome (SWS) qui tend à réduire la window size et donc d'assurer une
meilleure efficacité (voir RFC 813, 896 et 2581). Nous activons également les
keepalive, segments TCP permettant de vérifier si une transmission TCP est
toujours réellement active et non pas conservée dans un état artificiel (suite
à un SYN flood ou Naptha, par exemple). Vient ensuite l'activation des
blackholes consistant à empêcher votre système d'être scanné en ne répondant ni
par un RST pour TCP ni par un ICMP port unreachable pour UDP aux paquets
envoyés sur un port fermé et donc transformer votre système en "trou noir". La
dernière ligne n'est applicable que sur les hôtes finaux puisqu'elle induit la
vérification à chaque arrivée de paquets que son adresse de destination
corresponde à une adresse de l'interface de réception.
# sysctl -w net.inet.ip.ttl=128
# sysctl -w net.inet.icmp.maskrepl=0
# sysctl -w net.inet.icmp.bmcastecho=0
# sysctl -w net.inet.icmp.icmplim=200
# sysctl -w net.inet.tcp.delayed_ack=1
# sysctl -w net.inet.tcp.always_keepalive=1
# sysctl -w net.inet.tcp.blackhole=2
# sysctl -w net.inet.udp.blackhole=1
# sysctl -w net.inet.ip.check_interface=1
Par ailleurs nous possédons également quelques astuces afin d'éviter les
tentatives de cache poisoning en accélérant le temps de rafraîchissement de la
table de routage et de la table ARP.
# sysctl -w net.inet.ip.rtexpire=60
# sysctl -w net.inet.ip.rtminexpire=10
# sysctl -w net.link.ether.inet.max_age=1200
Finissons avec quelques modifications liées au système à modifier :
# sysctl -w vfs.vmiodirenable=1
# sysctl -w kern.coredump=1
# sysctl -w kern.corefile=%N.sexfault
# sysctl -w kern.ps_showallprocs=0
La première entrée permet d'améliorer le traitement notamment sur des larges
volumes de fichiers. Il concerne les fichiers Unix qui seront cachés dans le
buffer cache plutôt que directement sur le disque exploitant ainsi pleinement
la mémoire virtuelle FreeBSD par ailleurs déjà très performante. Ensuite nous
décidons d'activer l'application savecore qui permet de conserver une trace du
core dump associé à un kernel dans un but d'étude après un crash par exemple
afin d'en déterminer les causes. En dernier lieu, nous faisons en sorte que
les utilisateurs ne voient que leurs propres processus et que seul le root
puisse voir l'ensemble.
Notez que nous disposons également de quelques fonctionnalités configurables
par l'intermédiaire du loader. Par exemple, si vous disposez d'un disque IDE,
la commande suivante permet d'activer le cache en écriture :
# loader set hw.ata.wc=1
Toujours dans les protections contre les DoS mais cette fois-ci côté ressources
plutôt que réseau. Les entrées suivantes de la MIB vont nous permettrent
d'abord de limiter le nombre de processus par utilisateur et le nombre fichiers
(incluant file descriptor et IPC) qu'il peut ouvrir. Nous augmentons aussi la
taille de la queue de connexions de pair avec le nombre maximal de sockets
(2 fois le maximum de connexion approximativement). de même que la taille
maximal des buffers pour sockets (empiriquement 8 fois la taille de
{recv,send}space). Enfin, nous augmentons également le nombre maximum de
fichiers. Toutes ces valeurs paraissent élevées, mais elles ne servent en
réalité qu'à l'allocation de ressources.
# sysctl -w kern.maxprocperuid=512
# sysctl -w kern.maxfilesperproc=1024
# sysctl -w kern.ipc.somaxconn=4096
# sysctl -w kern.ipc.maxsockbuf=262144
# sysctl -w kern.maxfiles=16384
Si vous disposez de disques IBM DPTA ou DTLA, vous pouvez utiliser à la place
l'entrée hw.ata.tags mais à vos risques et périls puisqu'elle est encore
expérimentale.
Ces modifications doivent être répercutées sur /boot/loader.conf. De la même
manière, les options sysctl que voudrez retrouver à chaque demarrage doivent se
trouver dans le fichier /etc/sysctl.conf sous la forme 'entrée=paramètre'.
Ci-dessous notre sysctl.conf final.
------------------------------------- SNiP ------------------------------------
net.inet.tcp.rfc1323=1
net.inet.tcp.newreno=1
net.inet.tcp.inflight_enable=1
net.inet.tcp.inflight_min=6144
net.inet.tcp.sendspace=32768
net.inet.tcp.recvspace=65535
net.inet.tcp.log_in_vain=1
net.inet.tcp.always_keepalive=1
net.inet.tcp.blackhole=2
net.inet.tcp.delayed_ack=1
net.inet.tcp.strict_rfc1948=1
net.inet.tcp.isn_reseed_interval=1800
net.inet.tcp.syncookies=1
net.inet.tcp.syncache.hashsize=512
net.inet.tcp.syncache.cachelimit=15359
net.inet.tcp.syncache.bucketlimit=30
net.inet.tcp.syncache.rexmtlimit=3
net.inet.icmp.maskrepl=0
net.inet.icmp.bmcastecho=0
net.inet.icmp.icmplim=300
net.inet.udp.sendspace=32768
net.inet.udp.recvspace=32768
net.inet.udp.maxdgram=28672
net.inet.udp.blackhole=1
net.inet.udp.log_in_vain=1
net.inet.ip.ttl=128
net.inet.ip.forwarding=1 # ou check_interface=1
net.inet.ip.sourceroute=0
net.inet.ip.accept_sourceroute=0
net.inet.ip.rtexpire=60
net.inet.ip.rtminexpire=10
net.link.ether.inet.max_age=1200
vfs.vmiodirenable=1
kern.coredump=1
kern.corefile=%N.sexfault
kern.ps_showallprocs=0
------------------------------------- SNiP ------------------------------------
Et la même chose pour /boot/loader.conf
------------------------------------- SNiP ------------------------------------
kern.maxprocperuid=512
kern.maxfilesperproc=1024
kern.maxfiles=16384
kern.ipc.somaxconn=4096
kern.ipc.maxsockbuf=262144
------------------------------------- SNiP ------------------------------------
2.2. Gestion utilisateurs
Dans un système multi-utilisateurs, chaque utilisateur local ou distant se
doit d'avoir un compte propre permettant de converser l'environnement de
chacun dans l'état désiré ainsi qu'une gestion plus claire de l'activité du
système. En marge des comptes utilisateur classiques nous vous recommandons
fortement de créer plusieurs comptes dit 'système' destinés à exécuter avec un
minimum de risques de compromission ou d'exploitation de compte compromis, les
services réseau sensibles que vous désirez mettre en place. Parmi les plus
intéressant sur lesquels appliquer cette pratique, on trouve les serveurs DNS,
les serveurs web ou encore les serveurs smtp et pop3/imap4. Notez aussi la
présence du compte nobody correspondant a l'utilisateur système non privilégié
générique, mais plus il y a de services qui utilisent nobody, plus ce compte
acquiert de privilèges. Cette méthode est par ailleurs utilisée par beaucoup
de procédures d'installation dans les ports, réduisant votre charge de
travail.
Notez que les multiples chapitres sur sysctl, la configuration kernel, la
gestion des utilisateurs ou la mise en place d'une jail, nous pensons pouvoir
nous dispenser d'un chapitre supplémentaire sur les commandes basiques que sont
chroot, chmod et chown accompagné d'une explication rapide sur les privilèges.
Donc ne cherchez pas d'information sur ces commandes dans nos colonnes.
Notez par ailleurs que l'utilisation du compte root or des opérations limitées
de maintenance est fortement déconseillée pour des raisons de sécurité. Chaque
manipulation du root peut entraîner des conséquences importantes pour
l'intégrité du système ou bien si le compte est compromis, alors toute la
machine passe sous contrôle de l'intrus. Bref, il est préférable de se
constituer un compte utilisateur appartenant lui aussi au group wheel et ayant
la capacité d'exécuter des commandes en root par sudo qui nous permet de rester
sous un compte utilisateur et effectuer des opérations ponctuelles nécessitent
des droits root ou encore d'intervenir dans sur d'autres comptes si besoin est.
Par exemple nous pouvons éditer l'index de notre serveur web sur le compte
système www en utilisant l'option -u qui permet de préciser l'utilisateur dont
on souhaite endosser les droits
# sudo -u eberkut vi ~eberkut/CNS/FreeBSD.txt
Bien sûr cette liberté de manipulation peut être dangereuse c'est pourquoi nous
avons besoin d'éditer et de configurer /etc/sudoers afin de limiter les accès.
Le schéma de /etc/sudoers est le suivant : vous pouvez définir des alias pour
un ou plusieurs utilisateurs, ou encore une ou plusieurs commandes puis vous
définissez les autorisations selon le schema WHO WHERE=WHAT.
------------------------------------ SNiP -------------------------------------
# options
Defaults syslog=auth, mail_no_user, lecture, insults,
syslog_badpri=alert, rootpw, passwd_timeout=3, authenticate
Defaults:FULLTIMERS !lecture
# alias utilisateurs > root
User_Alias FULLTIMERS = eberkut
User_Alias PARTTIMERS = bindmaster,webmaster
Run_alias OP = root,named,www
# alias commandes
Cmnd_Alias DEBUG = /usr/bin/mt,/usr/sbin/dump,/usr/sbin/restore,
/usr/sbin/dd,/usr/bin/gdb,/usr/bin/ktrace,
/usr/bin/kdump,/usr/bin/file,/usr/bin/truss,
/usr/bin/ldd,/usr/bin/objdump,/usr/bin/strings,
/usr/bin/nm,/usr/bin/size,/usr/bin/kill
Cmnd_Alias KILL = /usr/sbin/shutdown,/usr/sbin/halt,/usr/sbin/reboot
Cmnd_Alias SHELLS = /usr/bin/sh,/usr/bin/csh,/usr/local/bin/zsh,
/usr/bin/ssh,/usr/X11R6/bin/startx
Cmnd_Alias USER = /usr/bin/su,/usr/sbin/adduser, /usr/sbin/rmuser,
/usr/bin/chsh
Cmnd_Alias NET = /usr/sbin/ppp,/usr/sbin/ifconfig,/usr/sbin/ipfw
Cmnd_Alias DAEMON = /usr/sbin/named,/usr/local/apache,/usr/bin/sshd
Cmnd_Alias RIGHTS = /usr/sbin/chroot,/usr/sbin/jail,/usr/sbin/chown,
/usr/bin/chmod
Cmnd_Alias CDROM = /sbin/umount /cdrom, /sbin/mount_cd9660 /dev/acd0c /cdrom
#directives
root ALL = (ALL) ALL
FULLTIMERS ALL = NOPASSWD: DEBUG, KILL, SHELLS, RIGHTS, USER, NET, DAEMON
PARTTIMERS ALL = DEBUG, NET, (OP) NOPASSWD: DAEMON
ALL ALL = NOPASSWD: CDROM
------------------------------------ SNiP -------------------------------------
Sudo se base sur des timestamp entre les différences commandes entrées pour
assurer un minimum de sécurité en plaçant un timeout. Pour updater votre
timestamp sans exécuter de commandes, vous pouvez taper sudo -v et pour le tuer
définitivement, sudo -K.
2.2.1. adduser / rmuser / chpass / watch
adduser est un outil extrêmement utile qui nous permet d'ajouter de nouveaux
utilisateurs de manière très simple. Il permet en une opération de gérer
l'ensemble des actions nécessaire à la création d'un nouveau compte. Une simple
commande effectue une configuration pas à pas du compte ceci incluant la
création des entrées nécessaires dans /etc/passwd et /etc/group, la création du
répertoire de l'utilisateur et la copie des fichiers requis par défaut jusqu'à
une notification de bienvenue.
Nous devons tout d'abord créer le fichier de configuration adduser par :
# adduser -s -config_create
Puis nous lançons la création de l'utilisateur.
# adduser -v
Use option ``-silent'' if you don't want to see all warnings and questions.
Check /etc/shells
Check /etc/master.passwd
Check /etc/group
Enter your default shell: csh date no sh tcsh zsh [sh]: sh
Your default shell is: sh -> /usr/local/bin/sh
Enter your default HOME partition: [/home]:
Copy dotfiles from: /usr/share/skel no [/usr/share/skel]:
Send message from file: /etc/adduser.message no
[/etc/adduser.message]: no
Do not send message
Use passwords (y/n) [y]: y
Write your changes to /etc/adduser.conf? (y/n) [n]: y
Ok, let's go.
Don't worry about mistakes. I will give you the chance later to correct any
input.
Enter username [a-z0-9_-]: eberkut
Enter full name []: eberkut
Enter shell csh date no sh tcsh zsh [zsh]:
Enter home directory (full path) [/home/eberkut]:
Uid [1000]:
Enter login class []: root
Login group wheel [wheel]:
Login group is ``eberkut''. Invite eberkut into other groups: guest no
[no]:
Enter password []:
Enter password again []:
Name: eberkut
Password: ********
Fullname: eberkut
Uid: 1000
Gid: 1000
Class: root
Groups: wheel
HOME: /home/eberkut
Shell: /usr/local/bin/zsh
OK? (y/n) [y]: y
Added user ``eberkut''
Copy files from /usr/share/skel to /home/eberkut
Add another user? (y/n) [y]: n
Goodbye!
Notez que vous pouvez facilement remarquer que nous utilisons ici adduser pour
la première fois puisqu'il nous a fallu créer le fichier de configuration puis
adduser nous a demande ses valeurs par défaut. De plus pour plus de simplicité
nous étions en mode verbose (-v). A l'avenir vous n'aurez que les informations
de l'utilisateur à entrer et vous pourrez effectuer cette opération en mode
silent (-s).
Adduser possède un programme frère, rmuser, qui va nous permettre de manière
symétrique à adduser, de supprimer en une seule opération un utilisateur et
toutes les dépendances que cela suppose. Rmuser effectue ainsi la suppression
de l'entrée utilisateur dans le fichier de mots de passe, de son repertoire
(dans /home), de son courrier en attente (dans /var/mail), de ses fichiers
temporaires (dans /tmp), et son entrée dans /etc/group voire la suppression du
groupe s’il devient vide. Mais rmuser efface également les entrées de
l'utilisateur dans la crontab ou encore tue tous les processus en cours
appartenant à l'utilisateur en question.
# rmuser eberkut
Matching password entry:
eberkut:*:1000:1000::0:0:eberkut:/home/eberkut:/usr/local/bin/zsh
Is this the entry you wish to remove? y
Remove user's home directory (/home/eberkut)? y
Updating password file, updating databases, done.
Updating group file: trusted done.
Removing user's incoming mail file /var/mail/jru: done.
Removing files belonging to eberkut from /tmp: done.
Removing files belonging to eberkut from /var/tmp: done.
Removing files belonging to eberkut from /var/tmp/vi.recover: done.
Enfin, chpass est un autre outil merveilleux de plus nous permettant de
faciliter grandement la gestion utilisateur. Il permet de modifier les
informations de base d'un utilisateur telles que son password, son shell ou
des informations plus personnelles. Seul le root et l'utilisateur lui-même
peuvent modifier les informations avec chpass. Chpass fonctionne de la même
manière que edquota, c'est-à-dire qu'il va ouvrir un éditeur permettant de
modifier notre configuration.
# chpass eberkut
#Changing user database information for eberkut.
Login: eberkut
Password: ********
Uid [#]: 1000
Gid [# or name]: 1000
Change [month day year]:
Expire [month day year]:
Class:
Home directory: /home/eberkut
Shell: /usr/local/bin/zsh
Full Name: eberkut
Office Location:
Office Phone:
Home Phone:
Other information:
Lorsque vous désirez mettre en place un service, en plus de le faire
fonctionner en stand alone comme expliquer précédemment, et s’il nécessite
certains droits, alors lui assigner un utilisateur spécifique peut permettre
de limiter partiellement avec des mécanismes supplémentaires comme jail ou
chroot les dégâts provoqués par une intrusion par l'intermédiaire de ce
service. Cette remarque est vraie aussi pour BIND qui avec les bonnes options
ne reste root que quelques instants ou pour Apache qui tourne en nobody -
et ses scripts aussi ce qui peut donner des vulnérabilités en cas de
mauvaise configuration.
Enfin, lorsqu’un utilisateur vient à se loguer et que vous avez remarqué de sa
part un comportement illégitime ou intrusif, les options pour les snoop device
que nous avons placé au moment de la configuration kernel vont nous permettre
de prendre possession afin d'observer et même d'écrire sur le tty d'un
utilisateur. Pour cela nous allons utiliser l'outil watch. Nous créons d'abord
les périphériques suivants :
# cd /dev
# ./MAKEDEV snp0
# ./MAKEDEV snp1
# ./MAKEDEV snp2
# ./MAKEDEV snp3
Puis nous pouvons lancer watch. Avant cela nous vérifions les utilisateurs
actifs sur le système afin de spécifier le tty device à surveiller. Nous
plaçons l'option t pour obtenir un timestamp au début de l'observation, n
pour empêcher l'utilisateur de changer de tty attaché et l'option W pour
permettre d'écrire au sein du tty surveillé.
# who
# watch -tnW ttyp1
2.2.2. quotas et limites
Les quotas sont une option de FreeBSD qui vous permettant de limiter la
quantité d'espace disque ou encore le nombre de fichiers auxquels a le droit
un utilisateur ou tous les utilisateurs du même groupe, sur un système de
fichiers donné. Dans un système multi-utilisateurs avec des accès distant,
cette méthode évite qu'un seul utilisateur ne consomme tout l'espace disque.
Les quotas devant être activés manuellement au sein du fichier de configuration
du kernel et nécessitant donc une recompilation, nous vous avons recommande de
vérifier la présence de l'option quotas ainsi que plusieurs autres au début de
ce texte. Une fois cette étape passée, vous devez activer une fois de plus les
quotas manuellement cette fois-ci au sein du fichier /etc/rc.conf. Pour cela
nous l'éditons et y ajoutons la ligne suivante :
enable_quotas="YES"
Pour un contrôle accru, vous disposez également d'une seconde option mais qui
va lancer un programme - quotacheck - qui peut considérablement ralentir le
démarrage de votre machine. Cependant la sécurité primant, nous vous
recommandons d'éditer la ligne ci-dessous :
check_quotas="YES"
Vous devez enfin éditer le fichier /etc/fstab pour mettre en service les quotas
système de fichiers par système de fichiers. C'est là que vous dites si vous
voulez des quotas d'utilisation des disques par utilisateur, par groupe ou les
deux, pour chaque système de fichiers.
Pour mettre en service des quotas par utilisateur, ajoutez l'option userquota à
la zone d'options de l'entrée de /etc/fstab pour le système de fichiers sur
lequel vous voulez des quotas. Par exemple :
/dev/ad0s1c /home ufs rw,nosuid,userquota 2 2
Pour des quotas par utilisateur on utilise userquota et pour des quotas par
groups, on utilisera groupquota. Pour appliquer des quotas à la fois à
l'utilisateur et à son groupe, on combinera les 2 commandes précédentes comme
nous l'avons fait pour notre fichier. Il ne vous reste plus qu'à redémarrer
afin d'activer la prise en compte de quota et la génération des fichiers
/etc/quota.user et /etc/quota/group.
Les quotas peuvent etre instaurés sur un système selon plusieurs critères. Tout
d'abord en plus de pouvoir appliquer des quotas par utilisateur et/ou par
groupes, vous avez la possibilité d'appliquer ces limitations selon differents
formats soit en termes d'espace disque, les blocs, soit en terme de fichiers,
les inodes. Par ailleurs, il faut ajouter des degrés dans les limitations :
strictes ou souples. Les premières suivent les règles de quotas à la lettre,
mais lorsqu'un utilisateur atteint son quota, il ne peut plus rien ajouter. Le
second degré de limitation offre à l'utilisateur un délai - valable durant une
semaine par défaut - lui permettant de ne pas être subitement limité
dans son travail par un quota trop strict et d'ajouter ou (surtout) retirer des
fichiers pendant ce délai. Cependant s’il n'est pas revenu à un niveau normal
une fois le délai écoulé, la limitation devient stricte et il ne peut plus rien
ajouter jusqu'à ce qu'il redescende en dessous de sa limitation.
Pour éditer nos quotas, nous utiliserons la commande edquota qui va ouvrir un
éditeur (vi par défaut) :
# edquota
Quotas for user eberkut:
/usr/home/eberkut: blocks in use: 0, limits (soft = 80, hard = 100)
inodes in use: 0, limits (soft = 40, hard = 60)
/usr/var: blocks in use: 0, limits (soft = 80, hard = 90)
inodes in use: 0, limits (soft = 60, hard = 80)
Pour se simplifier l'attribution de quotas, on peut appliquer un quota
prototype à une plage d'uid par l'intermédiaire de l'option -p de edquota une
fois les quotas définis une première fois :
# edquota -p eberkut 1000-10000
La commande quota peut être utilisée afin de connaître les quotas et
l'utilisation de l'espace disque d'un utilisateur et/ou d'un groupe. Comme pour
la majorité des autres commandes relatives aux informations utilisateurs, seul
le root peut aller consulter les quotas de tous comptes et tous groupes.
# quota -u eberkut
Un autre avantage majeur de FreeBSD, est de disposer, avec /etc/login.conf,
d'un fichier centralisé permettant de définir des classes renvoyant à un
utilisateur ou un groupe (au sens Unix) afin de spécifier le plus simplement
possible plusieurs restrictions touchant à l'authentification, aux permissions,
ou aux limitations de ressources des utilisateurs. C'est également un moyen
très pratique de limiter les ressources des comptes utilisés par vos services.
Les différents attributs sont groupés par classes. Celles-ci représentent donc
une politique cohérente à appliquer à un utilisateur ou un groupe, comme déjà
suggéré. Mais ces différentes classes ont la particularité de pouvoir être
héritées. Ainsi, les valeurs spécifiées dans une classe données peuvent être
reprises dans une autre classe grâce à l'attribut 'tc'. Il existe ainsi une
classe 'default' qui contient une configuration basique dont tous les
utilisateurs pourront hériter (et dont ils héritent effectivement si aucune
politique spécifique n'est indiquée). Il peut être alors intéressant d'y
ajouter une classe 'root' qui augmentera la rigueur de l'authentification et
limitera au plus juste les ressources allouées. La classe 'daemon' quant à elle
s'applique à tous les services lancés par /etc/rc au démarrage. De plus, nous
pouvons même remplacer certains attributs, ou en ajouter de nouveaux, en les
écrivant dans la nouvelle classe, après avoir spécifié un héritage (toujours
avec 'tc').
Le format suivi dans login.conf est celui de termcap(5), avec ses bien-connues
colonnes séparées par des : ou ses valeurs séparées par des virgules. Un aperçu
en est donné dans la manpage getcap(3) :
example|an example of binding multiple values to names:
:foo%bar:foo^blah:foo@:
:abc%xyz:abc^frap:abc$@:
:tc=more:
Comme vous le voyez, l'attribution se fait un peu de la même manière que pour
/etc/sysctl.conf, c'est-à-dire 'nom=valeur'. En plus de pouvoir être modifiés
dans login.conf entre deux classes parentes, les utilisateurs peuvent changer
certains attributs en plaçant un fichier .login_conf dans leur home directory
avec, pour seule classe, 'me'. Les variables que l'utilisateur peut lui-même
spécifier ne sont pas nombreuses, puisque authentification, limitation des
ressources et comptabilité en sont soustrait. Cela permet tout de même de
spécifier dans un fichier unique lu par login(1) des variables d'environnement,
par exemple. Cette fonctionnalité est spécifique à FreeBSD.
Il existe de nombreux attributs paramétrables, tombant dans plusieurs
catégories allant de simples booléens, jusqu'aux chemins d'accès, en passant
par des tailles (en b, kb, mb, gb ou tb) et des horaires (en s, m, h, d, w ou
y, indiquant ainsi les secondes, minutes, heures, jours, semaines ou mois).
Nous continuerons maintenant de suivre la manpage en reprenant la description
des attributs selon les catégories de limites de ressources, variables
d'environnement, authentification, et comptabilité. Vous trouverez ci-dessous
des explications des attributs qui nous ont semblé les plus pertinents.
o les limites de ressources
- cputime, permet de limiter le temps CPU que peut exploiter
temps absolu, pas en pourcentage. Correspond à l'option -f de limits(1).
- datasize, indique la taille maximale du segment 'data' d'un processus lancé
sous cette classe. Un peu désuet puisque cette limite s'applique aux appels
à brk(2) et sbrk(2). Identique à l'option -d de limits(1).
- maxproc, subordonné à l'entrée sysctl kern.maxproc, indique le nombre
maximal qu'un utilisateur de cette classe peut posséder. Comme le fait
judicieusement remarquer la section 8.7 du FreeBSD Handbook, prenez garde
à ne pas trop restreindre les utilisateurs compilant beaucoup, utilisant
plusieurs sessions, ou simplement prévu pour des serveurs fortement basés
sur fork() comme Apache 1.x. Option -u de limits(1).
- memoryuse, spécifie la quantité maximale de mémoire utilisée par un
processus, auss bien RAM que swap. Voir également 'memorylock' qui a le
même sens vis-à-vis des appels à mlock(2). Options -m et -l de limits(1).
- openfiles, subordonné à kern.maxfiles, définit le nombre maximal de file
descriptors (fichiers, IPC, sockets) qu'un processus peut avoir. Voir
l'option -n de limits(1).
- sbsize, pour socket buffer size, permet de contrôler la quantité de mémoire
allouée pour tous les sockets buffers d'un utilisateur, c'est-à-dire la
mémoire utilisée pour les transmissions sur le réseau. Il est certainement
soumis aux entrées sysctl net.inet.{tcp,udp}.{send,recv}space, et son
intérêt a diminué avec l'augmentation des protections disponibles contre
les SYN floods, à cause desquels cet attribut fut créé. Option -b de
limits(1).
- vmemoryuse, fixe la quantité maximale de tous types de mémoire virtuelle
(y compris via mmap()), qu'un processus peut exploiter.
- stacksize, que vous retrouverez avec l'option -s de limits(1), indique la
taille maximale jusqu'à laquelle le système peut étendre la stack d'un
processus.
- filesize, précise la taille maximale d'un fichier qu'un utilisateur de
cette classe peut détenir. Correspond à l'option -f de limits(1). Notez que
les quotas sont prioritaires sur cet attribut.
- coredumpsize, subordonné à filesize, permet de définir la taille maximale
acceptable pour un coredump. D
|