Blog

Présentation de l'outil integrit + intégration Nagios + intégration Ansible

Écrit le 28 06 2013 par Kévin MET _

UPDATE DU 08/02/2017

Et hop ! Je fais un petit coup de peinture sur cet article qui commençait lentement à s'écailler. J'ai ajouté la section Ansible, j'ai changé les liens qui étaient morts et j'ai corrigé tout ce qui était un peu daté par rapport à l'article de base. Bref, cet article est à jour pour 2017 et j'éspère pour encore quelques autres années :)

Dans ce billet on va parler de l'outil integrit. Ce petit logiciel permet de vérifier l'intégrité de ses fichiers par le biais de plusieurs tests : checksum, inode, permissions, nombres de liens, uid, gid, taille du fichier, date d'accès, date de modification et date de changement UNIX. Un fichier de configuration permet de régler tout cela très finement en désactivant ou en activant des options et en indiquant sur quels fichiers l'on veut que les tests soient effectués. Bref, un outil très complet dans le rôle pour lequel il est fait.

Principes de bases

Integrit, lorsqu'on l'installe sur Debian via le gestionnaire de paquet va ajouter un cron dans le dossier /etc/cron.daily/ qui lancera chaque jour une vérification et nous avertira par mail en cas de changement. Dans la suite de l'installation nous allons changer ce comportement et intégrer cette vérification directement dans nagios. Il est également possible de combiner les deux modes de vérification mais c'est strictement inutile...

Integrit s'appuie sur un système de base de de données. Lors de l'installation du logiciel, il faudra donc créer une base de données reflétant l'état des fichiers à un instant T. Lors des futures vérifications, Integrit fera un comparatif en s'appuyant sur cette base. Le mode de fonctionnement est donc très simple mais très efficace. Il faut donc prendre soins de mettre la base de données sur un système de fichier en lecture seul (un montage NFS en read only par exemple). Bon, j'avais écris ça à l'époque car c'est vrai que c'est plus secure mais dans les faits c'est très chiant car à chaque mise à jour de la base de données il faut remonter en écriture puis remonter en lecture. De plus, lorsqu'un serveur est compromis on a le plus souvent affaire à un script kiddie voire un bot mais en aucun cas à un vrai humain. Du coup, je ne trouve pas franchement nécessaire de changer l'emplacement par défaut de la base de données, à savoir /var/lib/integrit/known.cdb.

Installation

Concernant l'installation, c'est très simple :


# aptitude install integrit

Comme je l'expliquais précédemment, je préfère désactiver le check journalier effectué par défaut et intégrer ce check directement dans nagios. Pour cela, je vide le fichier /etc/cron.daily/integrit et je laisse simplement un retour à 0 au lieu de le supprimer. Cela permet que lors des mise à jours le fichier ne soit pas remis en place par aptitude.


cat /etc/cron.daily/integrit

#!/bin/sh
exit 0

Configuration

Sous Debian, la configuration se fait via 2 fichiers :

  • /etc/integrit/integrit.debian.conf : le fichier de conf spécifique à Debian
  • /etc/integrit/integrit.conf : le fichier principal de de conf d'integrit
  • /etc/integrit/nagios.conf : le fichier que l'on va créer pour nagios

Le fichier /etc/integrit/integrit.debian.conf vous permet d'indiquer ou se trouve le fichier de conf principal, qui traditionnellement se trouve être /etc/integrit/integrit.conf. Il vous permet également de paramétrer le sujet du mail ainsi que le destinataire du mail mais comme on vient de désactiver cette option en supprimant la quasi totalité du fichier /etc/cron.daily/integrit, tout cela ne sert donc à rien. Voici donc à quoi ressemble ce fichier chez moi :


# Configuration of the example daily cron job /etc/cron.daily/integrit

# Set the configuration file(s) for integrit.  /etc/cron.daily/integrit
# will run ``integrit -uc -C '' for each file specified in CONFIGS.
# An empty CONFIGS variable disables /etc/cron.daily/integrit.  Multiple
# file names are separated with spaces, e.g.:
# CONFIGS="/etc/integrit/usr.conf /etc/integrit/lib.conf"
# CONFIGS="/etc/integrit/integrit.conf"
CONFIGS="/etc/integrit/integrit.conf"

Pareil pour le fichier de conf principal, on ve pas pas l'utiliser au profit du fichier /etc/integrit/nagios.conf. On le laisse donc tel quel et on passe à la suite.

On s'attaque donc au fichier de configuration qui sera utilisé par nagios via NRPE. Pour commencer, on désigne la racine sur laquelle la vérification sera effectuée avec l'option root. Par défaut integrit descendra dans tous les sous-dossiers de la racine pour y scanner tous les fichiers. Nous allons voir par la suite comment filtrer cela plus finement. Ensuite on désigne le chemin de stockage des bases de données. Il y en a deux, la base de données de référence (known) et la base de donnée résultante du scan qui vient d'être effectué (current). C'est entre ces deux bases que la différence sera faite par integrit. Comme je le disais précédemment, il est fortement préférable de mettre la base de référence sur un système de fichier en lecture seule. Cela permettra, en cas de compromission de votre serveur de veiller à ce que l'attaquant ne modifie pas la base de référence rendant ainsi la vérification d'integrit inefficace.

Il existe plusieurs options pour filtrer les dossiers et fichiers. Vous pouvez placer un ! devant le un dossier que vous ne souhaitez pas scanner. Pour éviter de scanner le dossier /proc par exemple :


!/proc

Attention à ne pas laisser de / en fin de ligne car cette ligne ne serait alors pas prise en compte.

Pour scanner uniquement un dossier sans descendre dans ses sous-dossiers, on utilise =. Par exemple, si je veux scanner /opt/test mais pas ses sous-dossiers :


=/opt/test

Il existe un troisième filtre, le dollar $, qui permet de spécifier des options sur un dossier sans que celle-ci ne soit retransmise aux sous-dossiers comme c'est le cas par défaut.

On peut ensuite définir des options via une liste de lettres qui permettent d'activer ou de désactiver des types de tests. Par défaut, tous les tests sont activés et on désactive un test en indiquant la lettre correspondante en majuscule et on l'active en indiquant la lettre correspondante en minuscule. Voici la liste des filtres :

  • s : checksum
  • i : inode
  • p : permissions
  • l : nombres de liens
  • u : uid
  • g : gid
  • z : taille du fichier
  • a : date d'accès
  • m : date de modification
  • c : date de changement UNIX (changement des propriétés du fichier)
  • r : une option pour reset la date d'accès

Par exemple si je veux désactiver le check sur la date de changement UNIX et la date de modification sur le dossier /etc, je vais ajouter cette ligne :


/etc MC

Et cette option est très pratique pour ne pas avoir d'alertes quand on fait une modification sur un fichier de conf d'un serveur...

La configuration est donc à adapter à vos besoins. Le plus simple étant de faire quelques réglages grossiers au début, en excluant les dossiers peu sensibles comme /home/web/ ou /proc et d'affiner les réglages au fur et à mesure des alertes qui remontent.

Voici un fichier de configuration que j'utilise par défaut et que j'adapte en fonction de l'utilisation du serveur :


# # Here's a table of letters and the corresponding checks / options:
# # Uppercase turns the check off, lowercase turns it on.
# # 
# #       s     checksum
# #       i     inode
# #       p     permissions
# #       l     number of links
# #       u     uid
# #       g     gid
# #       z     file size (redundant if checksums are on)
# #       a     access time
# #       m     modification time
# #       c     ctime (time UN*X file info last changed)
# #       r     reset access time (use with care)
root=/
known=/var/lib/integrit/known.cdb
current=/var/lib/integrit/current.cdb
/etc MC
!/cdrom
!/root
!/dev
!/floppy
!/home
!/lost+found
!/mnt
!/media
!/proc
!/tmp
!/var
!/sys
!/run
!/usr/local/rtm

Ce fichier à jour et dispo sur github : integrit.conf

Utilisation

Pour initialiser la base on utilise cette commande :


# integrit -C /etc/integrit/integrit.conf -u

Il faut ensuite bouger la base de référence dans le dossier en read-only. Pour l'exemple, on va garder les dossiers par défauts.


# mv /var/lib/integrit/current.cdb  /var/lib/integrit/known.cdb 

On peut ensuite lancer un check avec la commande suivante :


# integrit -C /etc/integrit/integrit.conf -cu

Et voici un exemple de résultat avec des fichiers manquants, des changements, etc.


integrit: ---- integrit, version 4.1 -----------------
integrit:                      output : human-readable
integrit:                   conf file : /etc/integrit/integrit.conf
integrit:                    known db : /var/lib/integrit/known.cdb
integrit:                  current db : /var/lib/integrit/current.cdb
integrit:                        root : /
integrit:                    do check : yes
integrit:                   do update : yes
changed: /opt   l(3:4) m(20130626-201850:20130627-102323) c(20130626-201850:20130627-102323) 
new:     /opt/integrit   p(755) t(40000) u(0) g(0) z(4096) m(20130627-151630) 
changed: /opt/squid-3.3.4-1/etc   m(20130625-102828:20130627-150237) c(20130625-102828:20130627-150237) 
changed: /opt/squid-3.3.4-1/etc/squid.conf   s(383d087ad453fb41e9f019fae2e7243e92f1ada7:d1ab50ecf2d127b2f3b2014ace6a1e146ae8ad1f)
changed: /opt/squid-3.3.4-1/etc/squid.conf   i(13624:8749) m(20130625-102742:20130627-144934) c(20130625-102742:20130627-144934) 
changed: /usr/local   l(11:10) m(20130613-182114:20130627-151929) c(20130613-182114:20130627-151929) 
changed: /etc   m(20130626-103524:20130627-151801) c(20130626-103524:20130627-151801) 
changed: /etc/integrit   m(20130626-122935:20130628-134030) c(20130626-122935:20130628-134030) 
changed: /etc/integrit/integrit.debian.conf   s(fac3e52d94e975cbbda7a05c09946712e1b9b9d8:5ace0cbf0773690ff3c50f6be14b52344ecee30d)
changed: /etc/integrit/integrit.debian.conf   i(394858:399607) m(20130626-103658:20130628-125830) c(20130626-103658:20130628-125830) 
changed: /etc/cron.daily   m(20130626-103525:20130628-124802) c(20130626-103525:20130628-124802) 
changed: /etc/cron.daily/integrit   s(b269d6c9a7af59b08e6f3fbb66c10287e30c3007:a93c9644233997e6d395add1065ddd5727815fbd)
changed: /etc/cron.daily/integrit   i(399607:403734) m(20070810-110710:20130628-124802) c(20130626-103525:20130628-124802) 
changed: /etc/crontab   s(066b4b643625261214b5828bd47f53b59bab3b90:821d3ecebdbb74fb10b8e0b6e945df81f1d64abc)
changed: /etc/crontab   i(390380:400240) m(20130613-182114:20130627-151801) c(20130613-182114:20130627-151801) 
integrit: checking for missing files --------------
missing: /opt/integrit_update.sh   p(750) u(0) g(0) z(119) m(20130626-201850) 
missing: /opt/integrit_update.sh   s(8f6f41c8ac1875bd725ed89039a4ed9968e4a29c) 
missing: /usr/local/rtm   p(2755) u(0) g(50) z(4096) m(20130613-182114) 
missing: /usr/local/rtm/bin   p(2755) u(0) g(50) z(4096) m(20130613-182114) 
missing: /usr/local/rtm/bin/rtm-update-ip.sh   p(750) u(0) g(0) z(862) m(20130613-182114) 
missing: /usr/local/rtm/bin/rtm-update-ip.sh   s(932a7bddf8a4d86574b54596b3492ebe6d6f2ef4) 
missing: /usr/local/rtm/bin/rtm   p(sym) u(0) g(50) z(31) m(20130613-182114) 
missing: /usr/local/rtm/bin/rtm   s(e539fb1ef0fdb02bd3f4f904acaa61550c9edb84) 
missing: /usr/local/rtm/bin/rtm-0.9.4.pl   p(750) u(0) g(0) z(7684) m(20130613-182114) 
missing: /usr/local/rtm/bin/rtm-0.9.4.pl   s(44fab68817374e2acd45154e29f19cfc58f88436) 
missing: /usr/local/rtm/scripts   p(2755) u(0) g(50) z(4096) m(20130613-182114) 
missing: /usr/local/rtm/scripts/hour   p(2755) u(0) g(50) z(4096) m(20130613-182114) 
missing: /usr/local/rtm/scripts/hour/smart.pl   p(750) u(0) g(0) z(4228) m(20130613-182114) 
missing: /usr/local/rtm/scripts/hour/smart.pl   s(6a304ca1381c34c50f5c04b406160176f00aa2b8) 
missing: /usr/local/rtm/scripts/hour/hwinfo.pl   p(750) u(500) g(500) z(1635) m(20130613-182114) 
missing: /usr/local/rtm/scripts/hour/hwinfo.pl   s(84137bb92cc22c2ab828dd88278826385309d49a) 
missing: /usr/local/rtm/scripts/hour/listen_ports.pl   p(750) u(0) g(0) z(1779) m(20130613-182114) 
missing: /usr/local/rtm/scripts/hour/listen_ports.pl   s(0228a459b2ccbd7f95f59b3d8885c1cfd4e6ae1e) 
missing: /usr/local/rtm/scripts/hour/hwinfo-root.pl   p(750) u(0) g(0) z(5912) m(20130613-182114) 
missing: /usr/local/rtm/scripts/hour/hwinfo-root.pl   s(7f22cb0fe3dba092b3be88aba55a41277dd8aaa7) 
missing: /usr/local/rtm/scripts/hour/raid.pl   p(750) u(0) g(0) z(19679) m(20130613-182114) 
missing: /usr/local/rtm/scripts/hour/raid.pl   s(f3997487112b4f6b51bf40432bc99bad1cd5667c) 
missing: /usr/local/rtm/scripts/daily   p(2755) u(0) g(50) z(4096) m(20130613-182114) 
missing: /usr/local/rtm/scripts/daily/kernel.sh   p(750) u(500) g(500) z(192) m(20130613-182114) 
missing: /usr/local/rtm/scripts/daily/kernel.sh   s(d01999816aa2a947178be579674c098451cfa470) 
missing: /usr/local/rtm/scripts/daily/release.sh   p(750) u(500) g(500) z(720) m(20130613-182114) 
missing: /usr/local/rtm/scripts/daily/release.sh   s(e4fdef1089abad21dfb42119359ed49e789d1c8d) 
missing: /usr/local/rtm/scripts/daily/raid-daily.pl   p(750) u(0) g(0) z(2561) m(20130613-182114) 
missing: /usr/local/rtm/scripts/daily/raid-daily.pl   s(a47031ccdf1c8593c25d67020ff0e37826e6de2d) 
missing: /usr/local/rtm/scripts/min   p(2755) u(0) g(50) z(4096) m(20130613-182114) 
missing: /usr/local/rtm/scripts/min/hddinfo.pl   p(750) u(0) g(0) z(2274) m(20130613-182114) 
missing: /usr/local/rtm/scripts/min/hddinfo.pl   s(40141c852a1cc6e1e20e717c2d1a729d989b2fa4) 
missing: /usr/local/rtm/scripts/min/usage-root.pl   p(750) u(0) g(0) z(1472) m(20130613-182114) 
missing: /usr/local/rtm/scripts/min/usage-root.pl   s(3bf6e737a5a4fdbbc164ab49b265577466c93dd3) 
missing: /usr/local/rtm/scripts/min/check.pl   p(750) u(0) g(0) z(314) m(20130613-182114) 
missing: /usr/local/rtm/scripts/min/check.pl   s(15389f628215bc406d6fe2da600f32b2ecf6726c) 
missing: /usr/local/rtm/scripts/min/usage.pl   p(750) u(500) g(500) z(4479) m(20130613-182114) 
missing: /usr/local/rtm/scripts/min/usage.pl   s(da34eef571c604914a7764418d7bb2b7659a8c1b) 
missing: /usr/local/rtm/etc   p(2755) u(0) g(50) z(4096) m(20130613-182114) 
missing: /usr/local/rtm/etc/rtm-ip   p(644) u(0) g(50) z(16) m(20130626-025102) 
missing: /usr/local/rtm/etc/rtm-ip   s(cfc2caac0fb60baab4ad989312646ed2163f935c) 
integrit: current-state db RMD160 -------------- 
integrit: 28207cf30b3aa480ccc371cc12eb83e719aa9c57  /var/lib/integrit/current.cdb

Dans le paquet integrit est integré un outil qui permet de lire la base simplement. Il s'agit de i-viewdb que l'on utilise avec l'option -s pour cacher le checksum et en indiquant le fichier de la base.


 i-viewdb -s /var/lib/integrit/current.cdb | less

Intégration à Nagios

Pour monitorer intergrit avec Nagios il faut commencer par autoriser le groupe nagios à utiliser la commande integrit. Pour cela on va utiliser sudo.


# aptitude install sudo

Une fois que c'est fait, on édite le fichier /etc/sudoers pour y ajouter les droits avec le commande visudo. On ajoute donc cette ligne :


%nagios ALL = NOPASSWD: /usr/sbin/integrit

Il suffit ensuite d'utiliser ce script que je maintiens sur mon dépôt git en le téléchargeant via wget


# wget https://raw.githubusercontent.com/nierdz/admintools/master/nagios/plugins/check_integrit

Ensuite, comme pour n'importe quel autre plugins Nagios, il faut l'ajouter dans les commandes et les services et relancer Nagios. Je vous conseille de le mettre environ 1 fois pas heure car, en fonction du nombre de fichiers que vous vérifiez, cela peut prendre pas mal de temps à s’exécuter.

Voici un exemple de définition d'une commande pour un check local :


# cat /etc/nagios-plugins/config/integrit.cfg 
define command{
	command_name    check_integrit
	command_line    $USER1$/check_integrit -C $ARG1$
}

Mais comme cela n'est pas forcément intéressant de faire que des checks locaux, je l'utilise principalement avec NRPE pour sonder les serveurs à distance. Voici un extrait du fichier nrpe.cfg :


command[check_integrit]=/opt/nrpe/libexec/check_integrit -C /etc/integrit/integrit.conf

Et pour finir, lorsque j'ai fait des modifications sur les fichiers vérifiés par intergrit et que je veux reset la base j'utilise ce micro script bash :


#! /bin/bash
integrit -C /etc/integrit/nagios.conf -u
mv /var/lib/integrit/current.cdb  /var/lib/integrit/known.cdb
find /tmp/ -name 'integrit-*' && rm -rf /tmp/integrit-*

Si jamais je fais des modifs sur ce script, il est dispo sur mon github : https://github.com/nierdz/admintools/blob/master/nagios/plugins/db_update.sh

Ansible

Vous avez le choix de tout faire à la main comme je viens de l'expliquer ou si vous n'avez pas envie de vous faire chier vous pouvez utiliser un role ansible que j'ai écrit spécialement pour automatiser cette tâche. Il est disponible ici : https://github.com/nierdz/ansible. C'est le role nrpe. Il y a déjà pas mal d'informations dans le fichier README.md en anglais. La seule chose importante à savoir est qu'il faut lancer le script /opt/integrit/db_update.sh après installation pour initialiser la base.

Il faut également savoir que ce rôle fait plein d'autres choses qui me sont utiles dans le cadre de mon boulot mais qui ne le seront peut-être pas pour vous. Dans ce cas, je vous invite à utiliser uniquement le fichier integrit.yml qui contient toute la partie concernant l'installation d'integrit et son paramétrage sur NRPE et Nagios. Voici le contenu à la date du 08/02/2017 :


---
- name: Install integrit package
  apt: name=integrit cache_valid_time=86400 state=latest

- name: Copy default configuration file
  copy: src=integrit.conf dest=/etc/integrit/nagios.conf owner=root group=root mode=0600 force=no

- name: Create /opt/integrit folder
  file: path=/opt/integrit state=directory owner=root group=root mode=0700

- name: Copy db_update.sh script
  copy: src=db_update.sh dest=/opt/integrit/db_update.sh owner=root group=root mode=0700

- name: Copy check_integrit script
  copy: src=check_integrit dest=/usr/lib/nagios/plugins/check_integrit owner=root group=root mode=0755

- name: Write integrit command to /etc/nagios/nrpe_local.cfg
  lineinfile:
    dest: /etc/nagios/nrpe_local.cfg
    regexp: '^command\[check_integrit\]=.*/usr/lib/nagios/plugins/check_integrit.*'
    line: 'command[check_integrit]=sudo /usr/lib/nagios/plugins/check_integrit -C /etc/integrit/nagios.conf'
  notify:
    - restart nrpe

- name: Ajout du path /usr/sbin/integrit dans sudo pour nagios
  lineinfile:
    dest: /etc/sudoers
    state: present
    line: 'nagios ALL=(ALL) NOPASSWD: /usr/sbin/integrit'
    validate: 'visudo -cf %s'

- name: Add INTEGRIT service in {{ mnttech_fqdn }}.cfg
  delegate_to: "{{ nagios_fqdn }}"
  blockinfile:
    dest: /etc/nagios3/servers/{{ mnttech_fqdn }}.cfg
    marker: "# {mark} ANSIBLE : INTEGRIT service"
    block: |
      define service {
        use					integrit-services
        host_name			{{ mnttech_fqdn }}
        service_description	INTEGRIT
        check_command		check_nrpe!check_integrit
      }

Je pense que le nom de chaque tâche est assez explicite pour ne pas avoir à commenter ce fichier...

Il faut également penser à ajouter le dossier files qui contient des fichiers qui seront placés sur votre serveur :

  • /opt/integrit/db_update.sh
  • /usr/lib/nagios/plugins/check_integrit
  • /etc/integrit/nagios.conf

Et voilà, vous savez tout au sujet d'integrit et vous pouvez tranquillement surveiller vos fichiers via Nagios, et tout ça de manière automatisé !

♥ Partage sur tes réseaux sociaux ♥
Kévin MET
Kévin MET

Auteur de ce blog et gérant de la société MNT-TECH, je publie sur ce blog lorsque le temps me le permet et lorsqu'un sujet qui me parait intéressant n'a pas encore été abordé en français. Toutes les informations techniques présentes sur cette page peuvent être réutilisées moyennant le fait de citer la source.