Sécuriser un Kernel avec Grsecurity

17 avril 2016 Linux, Sécurité 8 Commentaires

Vous allez rapidement comprendre pourquoi mon dernier billet expliquait comment compiler et installer un Kernel Linux. J’avais déjà dans l’idée de vous expliquer comment il est possible de sécuriser un Kernel avec grsecurity, je voulais simplement faire correctement les choses.

 

 

Sécuriser un Kernel avec grsecurity : grsecurity Késséssé ?

grsecurity est un patch permettant d’augmenter la sécurité d’un noyau Linux en renforcant le controle d’accès local et le confinement des applications. De plus il inclut PAX, un ensemble de correctifs rendant votre système plus résistant à l’exploitation de vulnérabilités.

 

 

Sécuriser un Kernel avec grsecurity : Pré-requis

Je radote, tu radotes, il radote, etc.

Comme dans mon précédent mémo, je vous conseille fortement d’effectuer une sauvegarde de votre système avant d’installer un nouveau Kernel. Puisque j’adore me répéter, je vous rappelle que compiler un noyau prend du temps et beaucoup d’espace disque.

 

Installation des dépendances

La compilation d’un noyau avec le module grsecurity requiert plus de dépendances. Il vous faudra commencer par récupérer la version de gcc installée sur votre système.

gcc -v

 

Qui dans ici nous donne

root@noobunbox:~$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper

 

Maintenant installons les dépendances requises, n’oubliez pas de remplacer 4.9 par votre version de gcc

sudo apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc kernel-package gcc-4.9-plugin-dev

 

 

Sécuriser un Kernel avec grsecurity : C’est parti

Ici aussi nous allons créer un nouveau répertoire, parce que l’on est un peu psycho-rigide et que l’on aime travailler proprement

mkdir ~/kernel-grsecurity && cd ~/kernel-grsecurity

 

grsecurity n’est pas compatible avec les derniers Kernels, à l’heure ou j’écris ce mémo, la dernière version du noyau Linux avec laquelle est compatible grsecurity est la version 4.4.7. Téléchargeons là

 wget https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.4.7.tar.xz
 wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.7.tar.sign

 

Vérifions la signature de l’archive

unxz linux-4.4.7.tar.xz
gpg --verify linux-4.4.7.tar.sign

 

Si tout va bien, voici ce que vous devriez obtenir

root@noobunbox:~/kernel-grsecurity$ gpg --verify linux-4.4.7.tar.sign
gpg: les données signées sont supposées être dans « linux-4.4.7.tar »
gpg: Signature faite le mar. 12 avril 2016 19:09:46 MSK avec la clef RSA d'identifiant 6092693E
gpg: Bonne signature de « Greg Kroah-Hartman (Linux kernel stable release signing key) <greg[at]kroah.com> »
gpg: Attention : cette clef n'est pas certifiée avec une signature de confiance.
gpg: Rien n'indique que la signature appartient à son propriétaire.
Empreinte de clef principale : 647F 2865 4894 E3BD 4571 99BE 38DB BDC8 6092 693E

 

Nous pouvons donc extraire l’archive

tar xvf linux-4.4.7.tar

 

 

Sécuriser un Kernel avec grsecurity : Patch du Kernel

Commençons donc par nous déplacer dans le répertoire contenant les sources du noyau 4.4.7

~/kernel-grsecurity/linux-4.4.7

 

Téléchargeons le dernier patch grsecurity disponible (201604152208) ainsi que sa signature

wget https://grsecurity.net/test/grsecurity-3.1-4.4.7-201604152208.patch
wget https://grsecurity.net/test/grsecurity-3.1-4.4.7-201604152208.patch.sig

 

Vérifions que le patch soit correctement signé

root@noobunbox:~/kernel-grsecurity/linux-4.4.7$ gpg --verify grsecurity-3.1-4.4.7-201604152208.patch.sig
gpg: les données signées sont supposées être dans « grsecurity-3.1-4.4.7-201604152208.patch »
gpg: Signature faite le sam. 16 avril 2016 05:09:53 MSK avec la clef RSA d'identifiant 2525FE49
gpg: Bonne signature de « Bradley Spengler (spender) <spender[at]grsecurity.net> »
gpg: Attention : cette clef n'est pas certifiée avec une signature de confiance.
gpg: Rien n'indique que la signature appartient à son propriétaire.
Empreinte de clef principale : DE94 52CE 46F4 2094 907F 108B 44D1 C0F8 2525 FE49

 

Tout semble normal, nous pouvons donc appliquer le patch aux sources du Kernel, pour cela rien de plus simple, lançons la commande suivante

patch -p1 < grsecurity-3.1-4.4.7-201604152208.patch

 

La liste des fichiers patchés apparaît dans votre terminal

[...]
patching file tools/gcc/gen-random-seed.sh
patching file tools/gcc/initify_plugin.c
patching file tools/gcc/kallocstat_plugin.c
patching file tools/gcc/kernexec_plugin.c
patching file tools/gcc/latent_entropy_plugin.c
patching file tools/gcc/randomize_layout_plugin.c
patching file tools/gcc/size_overflow_plugin/.gitignore
patching file tools/gcc/size_overflow_plugin/Makefile
[...]

 

 

Sécuriser un Kernel avec grsecurity : Configuration du Kernel

Copiez le fichier de configuration de votre Kernel, histoire de ne pas risquer de tout casser en touchant a tout 🙂

 cp /boot/config-$(uname -r) .config

Maintenant ouvrons le menu de configuration du Kernel (étape obligatoire)

make menuconfig

 

Dans ce menu naviguez vers « Security Options »

Sécuriser un Kernel avec grsecurity

 

Puis vers Grsecurity

Sécuriser un Kernel avec grsecurity

 

 

Utilisez la barre espace de votre clavier pour modifier la configuration du module Grsecurity

Sécuriser un Kernel avec grsecurity

 

Naviguez vers Configuration Method

Sécuriser un Kernel avec grsecurity

 

Sélectionnez Automatic

Sécuriser un Kernel avec grsecurity

 

Attention IPtables peut ne pas fonctionner par défaut. Pour s’assurer de son fonctionnement suivez les recommandations ci-dessous
Networking Support -> Networking options -> Network packet filtering framework (Netfilter) -> IP:Netfilter Configuration -> Enable: IPv4 masquerade support + iptables support
Networking Support -> Networking options -> Network packet filtering framework (Netfilter) -> IPV6:Netfilter Configuration -> ip6tables NAT support -> Enable: masquerade support

 

Vous pouvez maintenant sauvegarder votre configuration et quitter.

 

 

Sécuriser un Kernel avec grsecurity : Compilation du Kernel

Ici aussi on met un peu d’ordre dans nos fichiers

make-kpkg clean

 

Maintenant récupérez le nombre de coeur CPU disponibles sur votre machines

nproc

 

Dans mon cas, cette commande me retourne le chiffre 12. Je peux donc affecter jusqu’à 12 cores à la compilation du Kernel

Nous pouvons maintenant lancer la compilation du Kernel (modifiez l’option -j 12 en fonction du nombre de cores que vous souhaitez affecter à cette opération)

fakeroot make-kpkg --initrd --revision=1.0.noobunbox kernel_image kernel_headers -j 12

 

 

Sécuriser un Kernel avec grsecurity : Installation du Kernel

La compilation est terminée, deux fichiers devraient avoir été générés, vérifions

root@noobunbox:~/kernel-grsecurity/linux-4.4.7$ ls ../*.deb
../linux-headers-4.4.7-grsec_1.0.noobunbox_amd64.deb
../linux-image-4.4.7-grsec_1.0.noobunbox_amd64.deb

 

Je vais me répéter mais ce n’est pas grave 🙂 je vous conseille de transférer ces deux paquets sur une machine virtuelle afin de les tester. Connectez vous donc sur votre MACHINE VIRTUELLE via SSH.

 

Avant de pouvoir installer notre Kernel grsecurity, nous allons devoir installer deux paquets

apt-get install paxctl paxtest

 

Maintenant installez les deux paquets précédemment transférés

sudo dpkg -i linux-headers-4.4.7-grsec_1.0.noobunbox_amd64.deb
sudo dpkg -i linux-image-4.4.7-grsec_1.0.noobunbox_amd64.deb

 

L’installation terminée, redémarrez votre machine virtuelle. Une fois le redémarrage terminé, vérifiez la version du Kernel installé via la commande

root@noobunbox:~$ uname -a
Linux debian 4.4.7-grsec #1 SMP Sun Apr 17 23:04:15 MSK 2016 x86_64 GNU/Linux

 

 

Sécuriser un Kernel avec grsecurity : Test du module grsecurity

Afin de vérifier que grsecurity fonctionne correctement nous allons utiliser la commande suivante

root@noobunbox:~$ paxtest blackhat

 

Cette commande permet de simuler l’exploit de vulnérabilités. Si tout va bien voici ce que vous devriez obtenir

root@noobunbox:~# paxtest blackhat
PaXtest - Copyright(c) 2003,2004 by Peter Busser <peter[at]adamantix.org>
Released under the GNU Public Licence version 2 or later

Writing output to /root/paxtest.log
It may take a while for the tests to complete
Test results:
PaXtest - Copyright(c) 2003,2004 by Peter Busser <peter[at]adamantix.org>
Released under the GNU Public Licence version 2 or later

Mode: Blackhat
Linux noobunbox 4.4.7-grsec #1 SMP Sun Apr 17 23:04:15 MSK 2016 x86_64 GNU/Linux

Executable anonymous mapping : Killed
Executable bss : Killed
Executable data : Killed
Executable heap : Killed
Executable stack : Killed
Executable shared library bss : Killed
Executable shared library data : Killed
Executable anonymous mapping (mprotect) : Killed
Executable bss (mprotect) : Killed
Executable data (mprotect) : Killed
Executable heap (mprotect) : Killed
Executable stack (mprotect) : Killed
Executable shared library bss (mprotect) : Killed
Executable shared library data (mprotect): Killed
Writable text segments : Killed
Anonymous mapping randomisation test : 28 bits (guessed)
Heap randomisation test (ET_EXEC) : 23 bits (guessed)
Heap randomisation test (PIE) : 35 bits (guessed)
Main executable randomisation (ET_EXEC) : 28 bits (guessed)
Main executable randomisation (PIE) : 28 bits (guessed)
Shared library randomisation test : 28 bits (guessed)
Stack randomisation test (SEGMEXEC) : 35 bits (guessed)
Stack randomisation test (PAGEEXEC) : 35 bits (guessed)
Arg/env randomisation test (SEGMEXEC) : 39 bits (guessed)
Arg/env randomisation test (PAGEEXEC) : 39 bits (guessed)
Randomization under memory exhaustion @~0: 28 bits (guessed)
Randomization under memory exhaustion @0 : 28 bits (guessed)
Return to function (strcpy) : paxtest: return address contains a NU LL byte.
Return to function (memcpy) : Killed
Return to function (strcpy, PIE) : paxtest: return address contains a NU LL byte.
Return to function (memcpy, PIE) : Killed

 

Pour comparaison voici ce que l’on obtient avec un Kernel ne comprenant pas le module grsecurity

root@noobunbox:~$ paxtest blackhat
PaXtest - Copyright(c) 2003,2004 by Peter Busser <peter@adamantix.org>
Released under the GNU Public Licence version 2 or later

Writing output to /root/paxtest.log
It may take a while for the tests to complete
Test results:
PaXtest - Copyright(c) 2003,2004 by Peter Busser <peter@adamantix.org>
Released under the GNU Public Licence version 2 or later

Mode: Blackhat
Linux noobunbox 4.5.1 #1 SMP Sun Apr 17 16:04:50 MSK 2016 x86_64 GNU/Linux

Executable anonymous mapping : Killed
Executable bss : Killed
Executable data : Killed
Executable heap : Killed
Executable stack : Killed
Executable shared library bss : Killed
Executable shared library data : Killed
Executable anonymous mapping (mprotect) : Vulnerable
Executable bss (mprotect) : Vulnerable
Executable data (mprotect) : Vulnerable
Executable heap (mprotect) : Vulnerable
Executable stack (mprotect) : Vulnerable
Executable shared library bss (mprotect) : Vulnerable
Executable shared library data (mprotect): Vulnerable
Writable text segments : Vulnerable
Anonymous mapping randomisation test : 29 bits (guessed)
Heap randomisation test (ET_EXEC) : 14 bits (guessed)
Heap randomisation test (PIE) : 30 bits (guessed)
Main executable randomisation (ET_EXEC) : 29 bits (guessed)
Main executable randomisation (PIE) : 28 bits (guessed)
Shared library randomisation test : 29 bits (guessed)
Stack randomisation test (SEGMEXEC) : 30 bits (guessed)
Stack randomisation test (PAGEEXEC) : 30 bits (guessed)
Arg/env randomisation test (SEGMEXEC) : 22 bits (guessed)
Arg/env randomisation test (PAGEEXEC) : 22 bits (guessed)
Randomization under memory exhaustion @~0: 28 bits (guessed)
Randomization under memory exhaustion @0 : 28 bits (guessed)
Return to function (strcpy) : paxtest: return address contains a NULL byte.
Return to function (memcpy) : Killed
Return to function (strcpy, PIE) : paxtest: return address contains a NULL byte.
Return to function (memcpy, PIE) : Killed

 

Source