Quelques bonnes pratiques de sécurisation d’un serveur Linux, partie 4

closeCet article a été publié il y a 8 ans 9 mois 28 jours, il est donc possible qu’il ne soit plus à jour. Les informations proposées sont donc peut-être expirées.

Si vous avez suivi les précédents numéros (le premier, le deuxième, et le troisième), vous avez déjà une machine particulièrement bien armée pour résister à pas mal de menaces. Mais quand celles-ci deviennent plus ciblées, il faut aussi utiliser des solutions spécifiques. C’est tout particulièrement vrai dans le cadre d’une plateforme d’hébergement d’applications Web.

Rappel : il est évident qu’on ne saurait être exhaustif quand il s’agit de sécurité. Que ce soit le contexte d’installation du serveur ou son utilisation, je ne saurais couvrir tous les besoins. Aussi, il ne faut pas hésiter à me corriger quand je dis une énorme connerie 🙂

Le serveur Web

Ce que j’appelle serveur Web correspond au serveur dit HTTP, du nom du protocole que tout le monde utilise. C’est lui qui se charge de vous délivrer les pages Web, ainsi que les contenus dits statiques : images, fichiers CSS/JS, vidéos… Le plus répandu à l’heure actuelle reste Apache, même si des outsiders comme Nginx, dont j’aurais l’occasion de reparler bientôt, commencent à sérieusement grignoter des parts.

Et il faut dire, au moins sous Debian, que la configuration par défaut qu’on peut en faire est permissive. Il n’est pas non plus question de s’amuser, à l’instar du SSH, de modifier le port, parce que pour un site web standard, c’est tout bonnement con, personne ne saurait comment arriver sur votre site. Seulement, il y a des moyens simples de réduire la voilure, sans porter atteinte à vos applications.

« Masquer » l’identité du serveur

Ce n’est pas non plus une solution parfaite, mais en effet, par défaut, notamment en cas de page non trouvée (erreur 404), ou d’erreurs fatales (erreurs 50X), le message s’accompagne des informations techniques du serveur. Sous Apache, c’est encore plus important puisque ça s’accompagne souvent de la version de PHP installée, ainsi que de la version de la distribution.

Sous Apache, directement dans le fichier principal de configuration /etc/apache2/apache.conf :

Sous Nginx, dans /etc/nginx/nginx.conf, on utilisera la directive suivante :

Pourquoi procéder ainsi ? Si l’on peut aisément deviner qui de l’un ou l’autre est utilisé, le numéro de version est un indice qui permet à un attaquant de cibler certaines failles potentiellement utilisables dans lesdites version.

Pour PHP, c’est dans votre fichier php.ini (le chemin diffère suivant votre installation) :

Limiter les modules

En effet, Apache dispose de quantité de modules utilisables et activés par défaut (c’est aussi le cas pour Nginx). Chaque module peut évidemment faire l’objet de failles ou de bugs quelconques qui pourraient éventuellement être exploités. Restreindre leur nombre à la partie congrue est donc préférable, à l’image du conseil que je donnais au niveau de la machine complète dans l’épisode 2 : conserver un nombre de paquets restreints à l’usage de la machine.

Dans cette optique, externaliser l’exécution de PHP, au moyen notamment de PHP-FPM (ou d’HHVM pour les plus aventureux), est aussi une bonne chose. Et justement, l’un des prochains points concerne donc le langage de script côté serveur le plus populaire.

Bien séparer les vhosts

Pour bien isoler les applications et éviter toute attaque de grande envergure, on utilisera si possible les hôtes virtuels permettant de définir des règles bien précises pour chaque application/domaine. C’est une configuration qu’on retrouve notamment dans les hébergements mutualisés, où chaque client dispose de son propre espace de stockage sur lequel pointe son hôte virtuel, paramétré pour répondre au nom de domaine choisi à la commande.

C’est ce que j’ai notamment utilisé pour l’hébergement du blog. La machine héberge plusieurs applications, certaines regroupées dans le même « domaine », et j’avais notamment parlé que j’avais isolé Piwik dans son propre vhost quand je l’ai présenté.

Voici un exemple de Vhost Apache :

PHP

Je viens d’évoquer le fait d’utiliser FPM comme cadre d’exécution de PHP au lieu du module intégré à Apache. Ce mode de fonctionnement n’a pratiquement que des avantages, en performance et sécurité, l’inconvénient reposant alors que sur la bonne communication entre les deux. Un bon moyen de protéger cette communication est d’utiliser les sockets, qui ne sont que des communications locales sur une même machine. Si pour une raison ou une autre vous utilisez comme moi une configuration réseau (oui, sur la même machine), il faut s’assurer que FPM ne puisse recevoir des ordres que du serveur Web. Pour ça, là aussi dans l’épisode 2 j’ai évoqué l’utilisation de l’interface loopback. Le recours au pare-feu est aussi une alternative au verrouillage de cette communication.

PHP dispose de pas mal de modules lui aussi, à l’instar du serveur Web on essaiera de contenir le nombre de modules disponibles pour les applications. Un phpinfo(); dans fichier PHP permettra de connaître la liste des modules actifs ainsi que de leurs paramètres. On pourra éventuellement vérifier et ajuster les paramètres de certains d’entre eux (par exemple la taille maximale des fichiers envoyés, voire carrément désactiver la possibilité si l’application s’y prête).

MySQL

Le serveur de base de données le plus populaire est un des composants les plus critiques de la plateforme. En effet, comme sa définition l’indique, c’est lui qui stocke toutes les données de vos applications, y compris les plus sensibles (utilisateurs, mots de passe, adresse mail, infos bancaires, que sais-je encore). Avant même les deux précédents, il est celui qu’il faut bichonner pour en éviter les fuites.

Communication

De la même façon que pour FPM et comme je l’ai pris en exemple dans l’épisode 2, on limitera au maximum les possibilités de communication entre le serveur MySQL et les applications nécessitant un accès à leur base. L’interface loopback, configurée par défaut lors d’une installation sous Debian, conviendra parfaitement.

Droits utilisateurs

Évitez de donner des droits passe-partout à un utilisateur qui n’a normalement besoin de n’accéder qu’à une seule base. De la même façon, si la base n’est utilisée qu’en local, ne pas donner les droits sur tous les domaines.

Aussi, il est plus que fortement déconseillé d’utiliser le compte administrateur de MySQL (root) dans une application pour la gestion de sa base de données. Aussi, dans la mesure du possible, une application = une base = un utilisateur restreint. Non seulement la sécurité est meilleure, mais si vous optez pour une politique de sauvegarde ciblée par application (par exemple, pour sauvegarder à des fréquences différentes), ce sera beaucoup plus simple.

Renommer root

Si l’on conseille fréquemment de renommer ou de supprimer le compte administrateur d’une application, il est aussi préférable de changer le nom d’administrateur de MySQL, qui s’appelle lui aussi root. Le fait de connaître le nom de l’administrateur permet à un attaquant de plus rapidement atteindre sa cible (il n’a pas à essayer les couples utilisateurs/motsdepasse, mais seulement le mot de passe, un gain de temps considérable).

Pour modifier le nom de l’utilisateur, on modifiera directement la base mysql qui contient entre autre les privilèges utilisateurs. On utilisera la commande suivante pour modifier le nom de root :

Le FLUSH PRIVILEGES final est là pour mettre à jour directement les droits des utilisateurs sans redémarrer tout le serveur. Je conseille alors de se déconnecter, et de se reconnecter avec le nouveau nom de l’administrateur (bob dans l’exemple).

Bien s’occuper de vos applications

Chaque application pouvant faire l’objet d’un article à part, je n’évoquerais ici que des concepts globaux, même si je prend des exemples que je connais plus particulièrement.

En effet, une fois la base bien consolidée, rien n’empêche un attaquant de cibler votre application, ce qui pourrait s’avérer suffisant. La cible pourrait alors non pas nécessairement être la machine complète, mais juste la base de données de l’application. C’est notamment le cas dans le cadre d’un site d’e-commerce, qu’on sait forcément sensible, puisqu’il conserve les données personnelles de ses clients. On ne compte plus les attaques sur des plateformes qui stockent le nécessaire notamment financier (numéro de carte bleue, RIB pour virement).

Par exemple, j’ai longuement réfléchi sur la base à utiliser pour le blog. J’avais le choix entre tout écrire de zéro (un bon moyen de grossir les connaissances en PHP/MySQL), au risque de devoir gérer moi-même la sécurité au niveau du code –ce qui peut être coton quand on est relativement débutant (observez la qualité du code de collect pour vous faire une idée)–, et choisir un logiciel existant, qui est géré par une équipe active et attentive à la sécurité; avec à la clé des mises à jour simples et fréquentes pour boucher tout ça.

Et en choisissant WordPress, s’est de nouveau posé la question des extensions, comme pour Apache et PHP. Plus vous avez d’extensions, plus vous augmentez les sources possibles d’attaques, puisque du coup les mises à jour de chaque module incombent à leur auteur et non plus à l’équipe WordPress. La réactivité de chacun d’entre eux est à prendre en compte. Avant d’en installer une, il faudra vérifier l’historique, les notes, les commentaires, l’actualité… De manière générale, il faut essayer de garder le minimum possible d’extensions. Certaines possibilités, notamment de WordPress, pourront être plus efficacement appliquées « à la main » avec un thème enfant plutôt qu’une extension (une remarque que j’ai pu lire en me renseignant sur la suppression des query strings). Les articles de Korben sont très accessibles à comprendre sur le sujet.

J’ai pris l’exemple de WordPress, mais cela vaut pour toutes les applications lourdes de nos jours : blogs, galeries photos, réseaux sociaux, e-commerce, CRM, clouds privés… De manière générale, il ne faudra pas s’en tenir uniquement à l’application de base, il faudra aussi « valider » certaines extensions pour éviter par exemple des déboires comme l’actualité nous l’a montré récemment. Lorsque vous développez vous-même une application, essayez de ne pas penser à la sécurité après coup, mais dès le départ, pour éviter de trop grosses réécritures qui pourraient faire pire que mieux (le travail pour avoir une vraie gestion intégrée et sécurisée de l’accès administrateur sera plutôt lourd pour collect, dont le mot de passe est pour l’instant stocké en clair).

Fail2ban, le retour de la vengeance

J’ai déjà évoqué Fail2ban dans l’épisode 2. Il contient déjà des règles pour Apache, mais pas assez. Une fois n’est pas coutume, je vais faire le feignant et vous diriger vers cet article qui couvre le tristement célèbre w00t-w00t et les erreurs 403 (quand des gens tentent notamment de scanner des dossiers quand vous l’interdisez). Non par contre, une que je rajouterais ici, c’est celle qui permet de « protéger » l’accès à PHPMyAdmin :

En effet, il n’est pas rare que PHPMyAdmin soit utilisé pour gérer la base MySQL/MariaDB au quotidien (il est vrai qu’en ligne de commande, c’est lourdingue). Et quand il est installé à la main, sa mise à jour est particulièrement lourde à faire, ce qui conduit les gens à souvent le négliger.

Aucune sécurité n’est parfaite

On est passé du point le plus basique au point le plus visible de tous sur le serveur. Malgré tout, et comme les différentes attaques qui défraient la chronique le prouvent (Orange Business encore dernièrement), un attaquant motivé intervenant manuellement trouvera toujours un moyen de s’introduire.

À cette fin, il convient de rester actif sur la sécurité de la machine. Et donc, de tester et surveiller cette sécurité régulièrement, ce qu’on appelle dans le jargon l’audit et la supervision. Ce sera probablement la dernière étape du processus. La fin au prochain numéro donc 😉

3 Commentaires
Le plus ancien
Le plus récent
Commentaires en ligne
Afficher tous les commentaires
Cascador
Cascador
28/06/2015 14:33

Bon article remonté sur le Journal du Pirate 😉

Je modifie également ServerTokens sur Apache :
sed -i « s/ServerTokens OS/ServerTokens Prod/;s/ServerSignature On/ServerSignature Off/ » /etc/apache2/conf.d/security

Je te conseille également de t’intéresser à mysql_secure_installation

Tcho !

Angristan
28/06/2015 15:40

Bientôt a conf F2B pour piwik ? 🙂