En savoir un peu plus

Nous avons rapidement vu les outils permettant de soutirer des informations aux agents SNMP, à cette occasion nous avons parlé de communautés, mais nous n'avons pas vu ce que c'est. Voyons ceci en configurant (un minimum) un agent SNMP sur une distribution GNU/Linux.

Les versions de SNMP

Il semble bien qu'au final, seules les versions 1, 2c (classique) et 3 soient utilisées.

La version 3 apporte des fonctions de sécurité (chiffrement et authentification) qui permettent d'utiliser SNMP dans un environnement « hostile », mais n'est pas implémenté sur tous les matériels. Cette version n'apportant rien de plus pour la compréhension du fonctionnement de SNMP, nous n'en parlerons pas d'avantage.

La version 1 est généralement implémentée sur tous les équipements proposant SNMP, de même que la version 2c, qui ne fait qu'ajouter des compteurs sur 64 bits et une commande supplémentaire : GetBulk-Request. Cette nouvelle commande donne le même résultat que la commande Get-next-request, mais de façon plus efficace. Nous verrons cela plus loin dans les analyses de trames.

Ces deux versions offrent une sécurité tout à fait indigente. Il n'y a ni chiffrement des données, ni authentification (aussi bien de l'agent que du manager). Dans un environnement « hostile » il restera possible de pallier cet inconvénient par l'usage de tunnels chiffrés, de vlans etc. Voyons tout de même ce que proposent les versions 1 et 2 en termes de restrictions d'accès.

Les communautés et leurs privilèges

Nous illustrerons le propos en configurant l'agent snmpd proposé dans les distributions GNU/Linux.

Une communauté représente un groupe d'utilisateurs. Nous nous sommes jusqu'ici déclarés de la communauté public (option -c public dans les diverses commandes).

Par défaut, la plupart des équipements proposent les communautés public et private. Il est toutefois possible de les renommer ou d'en créer d'autres.

La communauté public n'a généralement accès qu'en lecture, et pas forcément à toute l'étendue des informations exposées.

La communauté private est généralement exploitée pour écrire (donc reconfigurer) un équipement et disposer de la totalité des informations que l'agent sait exposer. Il est donc nécessaire d'en réserver l'accès aux seuls administrateurs autorisés, mais ceci ne peut se faire que sur la base des adresses IP des managers, ce qui reste très rudimentaire.

Il est clair que dans un environnement hostile, il reste assez simple d'utiliser SNMP (v 1 et 2) à des fins tout à fait malveillantes.

Nous allons faire quelques manipulations sur notre Lynx Lucide pour illustrer les restrictions que l'on peut appliquer avec les communautés.

Nous avons fait, lors de l'installation de snmpd une modification de la configuration par défaut. Revoici une configuration minimale, équivalente, ne prenant en compte que les versions 1 et 2c de SNMP :

com2sec readonly  default         public
com2sec readwrite default         private

group MyROGroup v1         readonly
group MyROGroup v2c        readonly
group MyRWGroup v1         readwrite
group MyRWGroup v2c        readwrite

view all    included  .1

access MyROGroup ""      any       noauth    exact  all    none   none
access MyRWGroup ""      any       noauth    exact  all    all    none

La logique séquentielle de ce fichier n'est pas forcément la meilleure pour en comprendre le principe. Commençons donc par les view.

Les « view »

Ici nous n'avons qu'une view qui inclut la totalité de l'arbre (.1) et qui s'appèle all. Nous aurions pu tout aussi bien écrire

view bidule    included  .1

ou

view machin    included  .1

le mot-clé est view le nom de la vue sera all (ou bidule ou machin) et ce qui est inclus dans cette vue c'est .1 c'est-à-dire la totalité de ce que l'agent peut proposer.

Les « group »

Nous créons des noms de groupes auxquels nous associons un « nom de sécurité », en fonction de la version du protocole utilisé. Ceci n'a de réel sens qu'avec la version 3, mais en v1 et en v2c, il faut en passer par là quand même.

Nous avons écrit :

group MyROGroup v1         readonly
group MyROGroup v2c        readonly
group MyRWGroup v1         readwrite
group MyRWGroup v2c        readwrite

Nous aurions aussi bien pu faire :

group voyeurs v1     regarderMaisPasToucher
group voyeurs v2c    regarderMaisPasToucher
group violeurs v1    regardeEtPlus
group violeurs v2c   regardeEtPlus

pas forcément du meilleur gout, mais tout aussi correct syntaxiquement parlant.

Ces groupes et noms de sécurité nous serviront plus loin.

Les « access »

Ils sont de la forme :

access GROUP CONTEXT {any|v1|v2c|usm} LEVEL PREFX READ WRITE NOTIFY

On va faire simple :

  • le CONTEXT n'a de sens que pour la version 3 ;
  • le LEVEL est forcément noauth pour les versions 1 et 2c ;
  • le PREFIX n'a pas de sens pour v1 et v2c, nous mettrons exact ;
  • le NOTIFY « is not currently used ».

reste donc :

  • le GROUP est un nom que l'on a créé de toutes pièces, juste au dessus ;
  • le READ sera le nom de la vue dans laquelle le groupe aura le droit de lire ou none s'il ne peut rien lire (ce qui n'aurait aucun sens, pourquoi créer un groupe qui aurait le droit de ne rien lire) ;
  • le WRITE sera le nom de la vue dans laquelle le groupe pourra écrire (ou none s'il ne peut écrire).

Ainsi, dans notre fichier :

access MyROGroup ""      any       noauth    exact  all    none   none
access MyRWGroup ""      any       noauth    exact  all    all    none

Veut dire qu'il existe deux groupes, MyROGroup et MyRWGroup :

  • MyROGroup peut lire dans la vue all mais ne peut y écrire et ce, en utilisant aussi bien les protocoles v1 que v2c ;
  • MyRWGroup peut aussi bien lire qu'écrire dans la vue all aussi bien en v1 qu'en v2c.
Le « com2sec »

C'est ici que l'on recolle tous les morceaux, en ajoutant en prime les communautés. De la forme :

com2sec  [-Cn CONTEXT] SECNAME SOURCE COMMUNITY
  • CONTEXT n'a toujours pas de sens en v1 ni en v2c) ;
  • SECNAME, ça vient d'un peu plus haut dans l'explication ;
  • SOURCE, c'est l'adresse IP source (ou le sous-réseau IP, ou default si c'est « wide open ») ;
  • COMMUNITY, c'est le nom de la communauté dans laquelle l'agent s'est déclaré.

Nous avons :

com2sec readonly  default         public
com2sec readwrite default         private

Autrement dit, le groupe de sécurité readonly (qui aurait pu s'appeler regarderMaisPasToucher) est attaché à la communauté public. Comme ce groupe de sécurité est attaché au groupe MyROGroup (qui aurait pu s'appeler voyeurs) pour les protocoles v1 et v2c et que ce groupe MyROGroup peut aussi bien en v1 qu'en v2c lire et seulement lire partout, il s'ensuit que tout manager qui se connectera sur notre hôte en se déclarant de la communauté public pourra lire ce qu'il veut.

L'ennui, c'est que si le manager se déclare de la communauté private, qui est attachée au groupe de sécurité readwrite (qui aurait pu s'appeler ?…) depuis n'importe où (default) et que ce groupe de sécurité est attribué au groupe MyRWGroup (qui aurait pu s'appeler ?…), lequel peut lire dans all mais aussi y écrire, alors ce manager pourra modifier tout ce qui est modifiable sur notre hôte, preuve que notre configuration est complètement nulle. En fait, elle est là pour l'exemple, nous en ferons une moins sale par la suite.

Particularité Debian

(Et dérivées)

Le fichier /etc/default/snmpd contient des options ajoutées lors du lancement du service snmpd. Ces options, par défaut, limitent le service à écouter sur 127.0.0.1 :

# This file controls the activity of snmpd and snmptrapd

# MIB directories.  /usr/share/snmp/mibs is the default, but
# including it here avoids some strange problems.
export MIBDIRS=/usr/share/snmp/mibs

# snmpd control (yes means start daemon).
SNMPDRUN=yes

# snmpd options (use syslog, close stdin/out/err).
SNMPDOPTS='-Lsd -Lf /dev/null -u snmp -g snmp -I -smux -p /var/run/snmpd.pid 127.0.0.1'

# snmptrapd control (yes means start daemon).  As of net-snmp version
# 5.0, master agentx support must be enabled in snmpd before snmptrapd
# can be run.  See snmpd.conf(5) for how to do this.
TRAPDRUN=no

# snmptrapd options (use syslog).
TRAPDOPTS='-Lsd -p /var/run/snmptrapd.pid'

# create symlink on Debian legacy location to official RFC path
SNMPDCOMPAT=yes
Un simple man snmpd nous indiquera clairement (une fois n'est pas coutume) qu'il suffit d'enlever l'adresse locale dans la ligne d'options pour que snmpd écoute sur toutes les interfaces. Notez que si nous avons deux interfaces, dont par exemple une attachée à un vlan (un vlan pourquoi pas réservé à l'administration des équipements), nous pouvons forcer snmpd à n'écouter que sur cette interface, ce qui permettrait de sécuriser quelque peu le dispositif.

Après modification de cette ligne et redémarrage du service, nous pouvons constater que :

# netstat -lupn
Connexions Internet actives (seulement serveurs)
Proto Recv-Q Send-Q Adresse locale          Adresse distante        Etat       PID/Program name
udp        0      0 0.0.0.0:68              0.0.0.0:*                           639/dhclient    
udp        0      0 0.0.0.0:47712           0.0.0.0:*                           618/avahi-daemon: r
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           618/avahi-daemon: r
udp        0      0 0.0.0.0:161             0.0.0.0:*                           1507/snmpd

C'est compris ?

Bien sûr ! Et ceci va nous permettre de créer une configuration un peu plus complète de la façon suivante :

  • une communauté public, qui aura droit à l'accès en lecture seule, mais seulement à la branche system pour tous ceux qui peuvent joindre notre agent, quelle que soit leur adresse IP ;
  • une communauté private aura droit à la lecture seule de toutes les informations possibles, mais seulement à partir d'un réseau IP particulier ;
  • une communauté admin pourra lire et écrire partout où c'est possible, mais depuis une adresse IP bien particulière.

Voici la configuration proposée :

com2sec voirUnPeu     default                public
com2sec voirTout      192.168.0.0/24         private
com2sec voirEtToucher 192.168.0.16           admin

group touristes v1         voirUnPeu
group touristes v2c        voirUnPeu
group riverains v1         voirTout
group riverains v2c        voirTout
group proprio   v1         voirEtToucher
group proprio   v2c        voirEtToucher

view system included       .1.3.6.1.2.1.1.1
view all    included       .1

access touristes ""      any       noauth    exact  system none   none
access riverains ""      any       noauth    exact  all    none   none
access proprio   ""      any       noauth    exact  all    all    none

Interro surprise 2

  1. Quelqu'un se déclarant de la communauté public pourra-t-il
    1. se connecter depuis n'importe quelle adresse IP ?
    2. obtenir les informations de la branche .iso.org.dod.internet.mgmt.mib-2.interfaces ? (on pourra s'aider de snmptranslate pour obtenir la version numérique de cette branche)
  2. Quelqu'un se déclarant de la communauté private pourra-t-il
    1. obtenir les informations de la branche .iso.org.dod.internet.mgmt.mib-2.interfaces s'il dispose de l'adresse 192.168.1.25 ?
    2. obtenir les informations de la branche .iso.org.dod.internet.mgmt.mib-2.interfaces s'il dispose de l'adresse 192.168.0.25 ?
  3. Quelqu'un se déclarant de la communauté admin depuis l'adresse IP 192.168.0.17
    1. pourra-t-il obtenir les informations de la branche .1.3.6.1.2.1.2 ?
    2. pourra-t-il modifier une valeur accessible en écriture (SNMPv2-MIB::sysLocation par exemple) ?

Réponses toujours en dernière page.