**Ceci est une ancienne révision du document !**

auditd

Nous avons étudié plusieurs solutions permettant de journaliser les commandes exécutées sur le système, le but étant de pouvoir remonter à la cause d'un éventuel problème sur l'infrastructure.

auditd est actuellement la solution la plus adaptée aux besoins de Picasoft : il est largement supporté, s'intègre bien avec SELinux si besoin, permet de centraliser les logs et d'effectuer leur rotation, permet de journaliser en détail de nombreux événements sur le système et est hautement configurable.

Aperçu des fonctionnalités

  • journalisation de nombreux événements sur le système (appels systèmes, modification du système de fichiers, etc.)
  • contrôle granulaire sur les événements journalisés et les conditions de leur journalisation
  • bonne intégration à d'autres systèmes tels que selinux, kerberos ou rsyslog
  • rotation automatique des journaux

Configuration

La configuration d'auditd se fait en deux parties : celle des règles d'audit et celle du démon en lui-même.

Rédaction de règles

Les règles se trouvent dans /etc/audit/rules.d/audit.rules, qui ne doit pas être édité manuellement. Il est automatiquement consitué par aggrégation de celles contenues dans les fichiers de /etc/audit/rules.d/. Il contient une succession d'options qui peuvent être directement passées au démon en appelant la commande auditctl. Les options inscrites dans ce fichier sont passés à auditd lorsqu'il est lancé. Ces options sont documentées dans auditctl(8) et audit.rules(7).

Parmi elles, celles commençant par -w permettent de journaliser les accès aux fichiers en lecture, écriture, exécution ou modification d'attributs. auditd se charge de déterminer ces accès en fonction de certains appels système pertinents. Par exemple, un appel à write(2) ne suffit pas à déterminer accès en écriture car ceux-ci sont trop courants. auditd a (notamment) besoin de l'associer à un appel à open(2) pour considérer une écriture de fichier.

Les règles contenant -S permettent de journaliser les appels système. L'option -F, pouvant apparaître plusieurs fois, spécifie un filtre et l'option -a spécifie au moteur de correspondance du noyau dans quel cas un événement est pris en compte. Un événement générant généralement plusieurs enregistrement, une règle peut soit concerner soit tout un événement, soit juste un enregistrement. Par exemple :

-a never,exit -F exe=/usr/sbin/runc

supprime tous les événements liés à runc alors que :

-a always,exclude -F msgtype=CWD

élimine les enregistrements CWD de tous les événements mais journalise encore les autres enregistrements leur étant associé (sous condition évidente que les autres règles le permettent).

L'option -k permet d'associer un label à une règle. Chaque événement journalisé par celle-ci sera alors portera alors ce label, ce qui est utile pour l'analyse postérieure des journaux.

Il est à noter que l'ordre des règles dans le fichier importe : elles sont évaluées les unes à la suite des autres. Ainsi, si une règle exclut un événement, il ne sera journalisé, peu importe ce que stipulent d'autres règles situées plus loin dans le fichier de configuration.

Une configuration disponible sur Github présente de bonnes pratiques concernant les règles auditd et permet de rapidement se familiariser avec des nombreuses options proposées par son système de règles.

Règles suggérées

Voici la configuration des règles dans /etc/audit/rules.d/audit.rules que nous avons déployée sur tous les hôtes dans le cadre de la TX :

# First rule - delete all
-D

# Increase the buffers to survive stress events.
# Make this bigger for busy systems
-b 8192

# This determine how long to wait in burst of events
--backlog_wait_time 0

# Set failure mode to syslog
-f 1




# don't log verbose container commands events
-a never,exit -F exe=/usr/sbin/runc
-a never,exit -F exe=/usr/bin/docker-runc
-a never,exit -F exe=/usr/bin/containerd



# don't log CWD records
-a always,exclude -F msgtype=CWD

# don't log SELinux AVC records
-a always,exclude -F msgtype=AVC



# log all 32/54bit execve calls from root, docker and others
-a exit,always -F arch=b64 -F euid=root -S execve -k execve_root
-a exit,always -F arch=b32 -F euid=root -S execve -k execve_root

-a exit,always -F arch=b64 -F egid=docker -S execve -k execve_docker
-a exit,always -F arch=b32 -F egid=docker -S execve -k execve_docker

-a exit,always -F arch=b64 -S execve -k execve_others
-a exit,always -F arch=b32 -S execve -k execve_others

# monitor writes and file attribute changes on /etc and /lib
-w /etc -p wa -k etc_modification
-w /lib -p wa -k lib_modification

Configuration du démon

Le démon auditd en lui-même est configuré dans le fichier /etc/audit/auditd.conf. Il s'organise en paires clef = valeur séparées par des retours à la ligne. On peut y configurer les journaux, de leur localisation (/var/log/audit/audit.log par défaut) à leur format et à l'espace qu'ils peuvent prendre au maximum, la centralisation des journaux avec Kerberos et les paramètres réseau d'auditd.

La configuration de base proposée par Debian est pertinente. Nous insisterons toutefois sur les options suivantes :

  • dispatcher = /sbin/audispd : on souhaite que la centralisation des logs soit faite par le plugin rsyslog d'audispd
  • action_mail_acct = root : les mails envoyés par auditd sont par défaut à destination de root. On pourra plus tard mettre en place une centralisation des mails en configurant le service de mail en réseau
  • max_log_file = 8 et max_log_file_action = ROTATE : dès qu'un fichier de log atteint une taille de 8M, on effectue une rotation
  • space_left = 75 et space_left_action = SYSLOG : lorsque la partition contenant les journaux descend en-dessous des 75M de libres, on émet un avertissement avec syslog
  • admin_space_left et admin_space_left_action : lorsque la partition contenant les journaux descend en-dessous des 75M de libres, on suspend l'activité d'auditd
  • disk_full_action = SUSPEND et disk_error_action = SUSPEND : lorsque la partition contenant les journaux est pleine, on suspend l'activité d'auditd

Au-delà de la configuration d'auditd en lui-même, il est conseillé de passer audit=1 comme paramètre au noyau afin de pouvoir auditer les processus éventuellent lancés avant auditd lui-même.

Centralisation

Il est très important que les journaux soient centralisés car ils seront principalement utilisés pour des analyses post-mortem. Or, on n'a pas de garantie d'intégrité sur les journaux d'un hôte compromis, donc on souhaite les conserver sur un hôte plus sûr (monitoring).

auditd permet d'utiliser Kerberos pour cela, mais cette solution est très lourde, compliquée à mettre en place et à maintenir. Nous avons plutôt décidé d'utiliser rsyslog car il est déjà présent sur tous les hôtes et permettra de centraliser d'autres journaux que ceux produits par auditd. Il s'agit d'une solution mature et très capable, permettant notamment de discriminer les journaux en fonction de leur hôte d'origine.

La mise en place de ce système se fait en plusieurs étapes : il faut rediriger les journaux d'auditd vers rsyslog, configurer rsyslog pour qu'il envoie ses journaux sur monitoring et configurer monitoring pour qu'il gère correctement ces journaux et les tourne de façon appropriée.

On commence par appliquer la configuration suivante à /etc/audisp/plugins.d/syslog.conf sur chacun des clients:

active = yes
direction = out
path = builtin_syslog
type = builtin
args = LOG_INFO
format = string

Cela active le plugin audisp passant les journaux d'auditd à rsyslog sur chaque client. On configure ensuite rsyslog dans /etc/rsyslog.d/client.conf pour qu'il envoie ses journaux à monitoring :

###########################################
# Log centralization client configuration #
###########################################
module(load="omrelp")   # provides RELP output for log centralization

# Forward auditd and audispd logs to a distant host
if ($programname == "auditd" or $programname == "audispd") then {
    action(type="omrelp"
        target="monitoring.picasoft.net"
        port="20514"
        tls="on"
        # For tls authentication
    #     tls.caCert="/path/to/cert"
    #     tls.myCert="/path/to/cert"
    #     tls.myPrivKey="/path/to/key"
    #     tls.authmode="name"
    #     tls.permittedpeer=["monitoring.picasoft.net"]
)
}

On remarquera que l'authentification TLS n'a pas encore été mise en place car nous attendions encore les certificats nécessaires.

On configure enfin monitoring pour qu'il gère correctement les journaux lui étant envoyés. On commence par rajouter la configuration suivante à /etc/rsyslog.d/server.conf pour que les journaux entrant soient ségrégés en fonction de l'hôte dont ils proviennent :

module(load="imrelp" ruleset="relp")   # provides RELP input for log centralization
                                       # and bind it to ruleset relp (see below)
input(type="imrelp" port="20514"
    tls="on" 
# For tls authentication:
#     tls.caCert="/path/to/cert" 
#     tls.myCert="/path/to/cert" 
#     tls.myPrivKey="/path/to/key"
#     tls.authMode="name" 
#     tls.permittedpeer=["pica02.picasoft.net", "pica01.picasoft.net", "pica01-test.picasoft.net"]
) 

# Places the right log in the right file
ruleset (name="relp") {
    if $source == "pica01-test" then {
        action(type="omfile"
            file="/var/log/pica01-test.log") 
        stop
    }
    if $source == "pica01" then {
        action(type="omfile"
            file="/var/log/pica01.log") 
        stop
    }
    if $source == "pica02" then {
        action(type="omfile"
            file="/var/log/pica02.log") 
        stop
    }
    stop
}

Puis on rajoute la configuration suivant à /etc/logrotate.conf pour déterminer le comportement des rotations :

/var/log/pica01-test.log
/var/log/pica01.log
/var/log/pica02.log
{
    # keep log files for 30 days
    maxage 30
    # Rotate them when they are larger than 10M
    size 10M
    missingok
    notifempty
    compress
    delaycompress
    sharedscripts
    postrotate
            invoke-rc.d rsyslog rotate > /dev/null
    endscript
}

Cette configuration supprime les journaux plus vieux qu'un mois, car on suppose qu'un problème nécessitant une enquête sera découvert avant cela. Par ailleurs, ne pas supprimer les journaux lorsqu'ils occupent une taille trop importante permet d'éviter qu'un attaquant les supprime en effectuant de nombreux appels à execve depuis un shell.

Utilisation

Outils

Une fois configuré, auditd ne fait que journaliser les événements pertinents dans /var/log/audit/audit.log (ou ailleurs selon la configuration). On peut alors utiliser différentes méthodes pour retrouver ceux nous intéressant. On peut notamment utiliser ausearch et aureport, des outils propres à auditd, journalctl venant avec systemd, ou simplement chercher manuellement à travers les journaux.

aureport(8) produit des résumés des journaux produits par auditd. Ces résumés peuvent être basés sur différents critères décrits dans le manuel, comme par exemple les labels (définis dans les règles de configuration), le groupe de l'utilisateur ayant généré l'événement ou le pid du processus. Il est aussi possible d'obtenir certains événements courants comme ceux concernant par exemple les modifications de configuration ou les actions sur fichiers et/ou sockets. Dans ces cas, auditd gère lui-même les cas correspondant au besoin exprimé.

ausearch(8) est un autre outil fourni par auditd offrant des fonctionnalités plus bas niveau. Ses arguments sont très similaires à ceux de aureport mais plutôt que d'afficher des résumés des événements, il les affiche directement tels qu'ils sont contenus dans les journaux. Il s'agit donc en un sens d'un “grep contextuel intelligent” pour auditd.

Il est également possible de directement manipuler les journaux avec les outils présents sur le système, ce qui peut être plus rapide (selon la familiarité de l'utilisateur) pour explorer les événements sans savoir exactement ce que l'on cherche ou pour au contraire trouver quelque chose de particulier qu'on sait pouvoir facilement trouver avec grep ou less.

Finalement, journalctl permet aussi d'accéder aux journaux d'auditd, bien que ce ne soit pas une façon recommandée de les traiter.

Heurisitiques

auditd permet de tracer les utilisateurs responsables des commandes journalisés. En particulier, on peut savoir qui a exécuté une commande avec sudo. Cependant, on perd l'information d'utilisateur lorsque celui-ci devient root avec su.

On peut continuer à le traçant en utilisant les identifiants de session que conserve auditd. Ainsi, les enregistrements SYSCALL contiennent un champ ses. À partir de celui-ci, il suffit de remonter dans les journaux et de trouver l'appel (par exemple) à su ayant le même identifiant de session et qui comportera l'UID original de l'utilisateur.

  • auditd.1560454887.txt.gz
  • Dernière modification: 2019/06/13 19:41
  • par cbarrete