INTRODUCTION A
SNMP
Bon, c'est bien joli d'exploiter à fond TCP/IP et autres ICMP, mais il est grand temps pour les grands c0wb0yZ que vous êtes de passer aux protocoles un peu moins connus...
Bin, par exemple le protocole Simple Network Management (SNMP).
Nous voici donc parti pour un (long) article qui vous sera certainement utile pour sécuriser votre propre réseau, ou pour approfondir vos connaisances...
Dans tous les cas, vous serez les seuls responsables de ce que vous ferez de votre connaissance... tachez d'être intelligents !
- Le B-A-BA de SNMP
Bah, pourquoi SNMP me direz vous, ça sert à quoi et ça permet quoi ?
Bin, c'est surtout une sacré source d'infos et ca peut aussi être une sacré source d'emmerdes pour un admin qui a mal configuré son matériel réseau... comme on verra plus bas (non, on triche pas ! on lit d'abord la théorie bande de chenapans et chenapines ;) SNMP permet entre autre d'arréter des interfaces (cartes) réseau x ainsi que de tuer des connexions effectuées sur les Èquipements qui sont mal configurés :)
Grosso modo, l'architecture ça ressemble à ça :
- les agents : tout un tas d'équipements réseaux (switchs, routeurs,
certains serveurs, ...) qui enregistrent des informations dans une base de données
locale appelée Management Information Base (MIB).
Si les agents voient qu'un événement particulier se produit (interface rèseau
qui s'arrête ou qui démarre, erreur d'authentification, ...), ils émettent un
datagramme appelé "trap" vers la station de Management pour la prévenir
de l'évènement.
- la station de Management : elle reçoit les traps envoyés, va chercher à intervalles réguliers l'information (polling) sur chacun des équipements gérés et permet à l'admin de les contrôler à distance (redémmarrage, arrêt d'une interface, tuer des connexions TCP).
Et pour communiquer, ces deux ensembles utilisent le protocole SNMP !
L'admin organise les MIB par *communautés* ce qui lui permet de classer et protéger les informations. Tout ce qu'il pense pouvoir laisser accessible au plus grand nombre, il le met dans la communauté "public". Tout ce qu'il veut cacher, il le met dans la communauté "private" (et limite l'accés à cette base uniquement à la machine de Management) ou alors utilise un nom de communauté vachement dur à trouver (comme "mickey" par exemple ;). Sur chacune des communautés qu'il définit, il attribue des droits (la communauté public ne devrait par exemple pas permettre la modification de données) et les adresses autorisées à y accéder (en général uniquement l'IP de la machine de supervision).
- Les nominés sont....
Bon, fini la théorie, passons à l'action :)))
Si vous avez suivi, il nous faut :
- identifier d'une part le nom de la communauté qui est accessible en écriture,
- repérer l'@IP de la machine de Management.
Pour ça facile !!! Ya des programmes tout faits :) Et au pire, on est suffisamment malins pour se débrouiller seuls, n'est ce pas ?
Moi je pense que l'idéal c'est peut être déjà de repérer les équipements (@IP) qui font tourner SNMP.
Donc, pour ce faire, je dois vous révéler un truc de hacker guedin :
le protocole SNMP utilise le protocole UDP pour toutes ses transmissions
(enfin, il existe des variantes...mais c'est généralement le cas) :
les agents écoutent les requêtes sur le port 161 et le manager écoute les
trap sur le port 162.
Le scan se fait tout simplement grace à THE nmap (inse-cure. org/nmap) :
(considérons que nous voulons scanner toutes les machines du réseau 172.23.4.0/24)
[uzy@bocal ~]$ nmap -sU -p 161,162 172.23.4.*
Starting nmap V. 2.54BETA25 ( www.insecure.org/nmap/ )
Interesting ports on (172.23.4.19):
|
Port |
State |
Service |
|
161/udp |
open |
Snmp |
Interesting ports on (172.23.4.249):
|
Port |
State |
Service |
|
161/udp |
open |
snmp |
Interesting ports on (172.23.4.252):
|
Port |
State |
Service |
|
161/udp |
open |
snmp |
|
162/udp |
open |
snmptrap |
Ouaich, on a trouvé trois adresses IP (Ca suffit pour l'exemple !) qui font tourner les services SNMP et on a, à priori, repéré le Manager (172.23.4.252) puisqu'il a le port 162 ouvert :). Les deux autres sont donc des agents.
-Quelle communauté choisir ???
Sans transition, voyons donc voir si, parmi ces adresses, on arrive à trouver les noms de communautés et si l'admin a bien fait son travail (fait vraiment tout pour nous pourrir la vie cui la ;)...
Pour ça, le fameux team ADM à fait un outil sympa qui s'appelle... devinez... ADMsnmp
Récupérez le sur
http://www.openbsd.org/2.7_pac-kages/i386/ADMsnmp-0.1.tgz-long.html ou ailleurs, et en avant !- begin of 31337 section
[uzy@bocal ~]$ tar xvzf ADMsnmp.0.1.tgz
ADMsnmp/
ADMsnmp/snmp.c
ADMsnmp/snmp.passwd
ADMsnmp/ADMsnmp.README
[uzy@bocal ~]$ cd ADMsnmp
[uzy@bocal ADMsnmp]$ gcc -o ADMsnmp snmp.c
[uzy@bocal ADMsnmp]$
- end of 31337 section ;)
ADMsnmp permet de scanner une @IP pour les noms de MIB courant (un genre de brute force de noms de communauté si vous voulez) et teste en bonus si la communauté est accessible en écriture :))
Rajoutez les noms que vous pensez plausibles dans le fichier snmp.passwd (comme "mickey" par exemple ;).
Bon, on lance ADMsnmp sur chacun des trois machines trouvées plus haut :
[uzy@bocal ~]$ ./ADMsnmp 172.23.4.19
ADMsnmp vbeta 0.1 (c) The ADM crew
ftp://ADM.isp.at/ADM/
greets: !ADM, el8.org, ansia
|
.. >>>>>> get req name=private id = 11 >>>>>> <<<<<<<<<<< recv snmpd paket id = 12 name =private ret =0 <<<<<<<<<< >>>>>>>>>>>> send setrequest id = 12 name = private>>>>>>>> <<<<<<<<<<< recv snmpd paket id = 13 name =private ret =0 <<<<<<<<<< .. |
<!ADM!> snmp check on 172.23.4.19 <!ADM!>
sys.sysName.0:SWITCH1
name = private write access
w00w00 !!! En voilà déjà un qui permet l'écriture dans la zone private :)))
Apparemment, c'est un switch => on risque de pouvoir déconnecter une partie du réseau très simplement ! C'est un bon début ! Continuons :)
[uzy@bocal ~]$ ./ADMsnmp 172.23.4.249
ADMsnmp vbeta 0.1 (c) The ADM crew
ftp://ADM.isp.at/ADM/
greets: !ADM, el8.org, ansia
|
.. >>>>>>>>>>> get req name=public id = 8 >>>>>>>>>>> <<<<<<<<<<< recv snmpd paket id = 9 name = public ret =0 <<<<<<<<<< >>>>>>>>>>>> send setrequest id = 9 name = public >>>>>>>> <<<<<<<<<<< recv snmpd paket id = 10 name = public ret =0 <<<<<<<<<< >>>>>>>>>>> get req name=private id = 11 >>>>>>>>>>> <<<<<<<<<<< recv snmpd paket id = 12 name = private ret =0 <<<<<<<<<< >>>>>>>>>>>> send setrequest id = 12 name = private >>>>>>>> <<<<<<<<<<< recv snmpd paket id = 13 name = private ret =0 <<<<<<<<<< .. |
<!ADM!> snmp check on 172.23.4.249 <!ADM!>
sys.sysName.0:SRVWEB
name = public readonly access
name = private readonly access
Bon, cui la est un peu mieux protégé ! Mais on peut quand même récupérer les infos présentes dans ses bases "public" et "private" :)
Et puis, il faut jamais cracher sur les informations que le serveur web peut nous fournir !
Passons maintenant à la station de Management.
[uzy@bocal ~]$ ./ADMsnmp 172.23.4.252
ADMsnmp vbeta 0.1 (c) The ADM crew
ftp://ADM.isp.at/ADM/
greets: !ADM, el8.org, ansia
|
.. >>> >>>>>>>> get req name=public id = 8 >>>>>>>>>>> >>>>>>>>>>> get req name=private id = 11 >>>>>>>>>>> .. |
<!ADM!> snmp check on 172.23.4.252 <!ADM!>
Bon, cui là est pas très causant :( Mais, de toute façon, on a déjà deux cibles qui vont nous permettre de nous renseigner et de nous amuser un peu :)
Donc, on a trouvé deux noms de communauté: public et private. L'admin a pas l'air de tellement se fouler ou de trop maîtriser la config SNMP, c'est bon signe ! C'est là que ça commence à être sympa... tiendez bon !!!
- Mettez vos masques, nous entrons dans les entrailles de SNMP ...
Jusque là je suis pas trop rentré dans les détails du protocole SNMP.. Le
temps de l'insouciance est révolu, place à la connaissance !
Les données sont classées dans la base par un système d'arbre de classement :

Donc, pour arriver à accéder aux données de la MIB, il faut en théorie spécifier toute la chaîne partant de la racine de l'arbre jusqu'a la position de la donnée MIB que l'on souhaite accéder, soit 1.3.6.1.2.1 pour accéder à iso.org.dod.internet.mgmnt.MIB.
Il existe deux types de données : les objets de type variable simple et ceux de type table (des tableaux koa). En règle géné-rale, les objets de type tableau s'appellent kelkechoseTable et ils sont composés d'éléments de type kelkechoseEntry.
Sous la feuille MIB, nous avons encore plusieurs catégories, et c'est ci que nous allons fouiner : (je ne donne que les champs les plus intéressants)
* System(1) qui contient l'identifiant de la machine (sysObjectID(2)), sa description (sysDescr(1)) qui permet de savoir à quel type d'équipement nous avons affaire, le nom du responsable(sysContact(4)), le nom de l'équipement(sysName(5)), sa localisation (sysLocation(6)), ... données toujours utiles pour faire de l'"Ingénieurie Sociale" ou pour trouver des exploits liés à l'équipement.
* Interfaces(2): humm... nous allons en savoir un peu plus sur la config matériel de l'équipement
ifNumber(1) fournit le nombre d'interfaces réseau.
ifTable(2): un tableau d'interfaces (ifEntry(1)). Une ifEntry est constituée de
:
ifIndex(1): numero identifiant de cette interface dans la table des interfaces.
ifDescr(2): description de cet interface (ça peut permettre de comprendre le rôle de cet équipement, notamment pour les routeurs :)
ifType(3): le type de support physique. si c'est de l'ethernet, ca sera ethernet-csmacd(6).
ifMtu(4): la Maximum Transmit Unit (la taille max au delà de laquelle un paquet doit être fragmenté pour pouvoir passer sur le réseau).
ifSpeed(5): bande passante en bits/s.
ifPhysAddress(6): @Phys (MAC pour les réseaux ether-net).
ifAdminStatus(7): statut désiré de l'interface : on souhaite qu'elle fonctionne (up(1)) ou qu'elle soit arrêtée (down(2)) ?
ifOperStatus(8): idem ifAdminStatus sauf que là c'est le statut réel de l'interface.
d'autres variables statistiques
Lorsque vous souhaiterez arréter une interface (pour "débrancher" toute une partie du réseau par exemple), vous devrez effectuer la requête sur la donnée ifAdminStatus et non pas sur ifOperStatus qui est en lecture seule.
* Address Translation(at(3)) contient les données liées à la résolution ARP (gromo dosso).
atTable(1): table d'entrées de type atEntry(1) :

Bon, bin avec ça on récupère la table ARP de l'équipement. Quand ça marche, ca peut être très utile !
AtPhysAddress est l'@Physique, atNetAddress l'@IP associée.
* IP(4) qui est parmi les plus intéressantes :
ipForwarding(1): l'équipement sert de passerelle si la valeur est à 1. Elle
peut être à 2 dans le cas contraire.
ipDefaultTTL(2): bin ça permet de connaître le TTL par défaut. Si on peut le modifier, ca peut tout changer...
des attaques de Deni de Service... quoi que les réglages, c'est plutôt tout à fond (comme le rock ;), nan ? Bon, au cas où ça intéresse kelkun, c'est le temps qu'un paquet fragmenté est conservé (en attente de réception de tous les fragments) avant destruction. Cette variable est read-only (on ne peut pas la modifier).
ipAddrTable(20): table des @IP de l'équipement.

Elle est constituée comme suit :
Bah, c'est cool, grace à ipAddrTable, on peut récupérer l'@IP de toutes les
interfaces de l'équipement, le masque de (sous-)réseau associé, l'@ broadcast
(pour écrire à toutes les machine sur (sous-)réseau. On n'en demande pas tant
! Et pourtant, on va nous en donner encore plus :)
ipRouteTable(21): tout simplement la table de routage de cette machine, livrée sur un plateau d'argent, constituée de ipRouteEntry(1) :)
ipRouteDest renseigne sur la destination associée à cette route (0.0.0.0 pour la route par défaut).
ipRouteIfIndex donne l'indentifiant de interface qui sera utilisée pour retransmettre le paquet sur le bon réseau.
ipRouteNextHop donne l'@IP du prochain routeur pour cette route.
ipRouteType nous indique si le réseau de destination est connecté sur l'interface destination (direct(3)) ou sur un réseau non accessible localement(indirect(4) : va falloir passer par d'autres routeurs !!! ).
ipRouteMask(11) spécifie le masque de (sous-)réseau associé à cette route.
Il existe aussi ipRouteProto(9) qui est au même niveau que ipRouteNextHop et cie et qui peut être utile pour savoir quels protocoles réseaux de configuration de route sont pris en compte sur ce réseau (valeurs notoires : local(2) (route mise en dur par l'admin), icmp(4) (icmp redirect !), egp(5),
rip(8), ospf(13)).
ipNetToMediaTable(22): table des correspondances @IP/@Physique (souvent @MAC).
Je vous laisse admirer :
Bon, bin là vous êtes en mesure de récupérer l'@Physique des interfaces locales et des autres @IP connues, plus le type d'attribution de l'@IP (dynamique si ipNetToMedia-Type==3 ; si égal à 4, l'attribution est statique (configuré en dur par l'administrateur)).

* IMCP(5) bon, ça existe. Mais je détaille pas, c'est des statistiques (pas forcément inutiles d'ailleurs).
* TCP(6) qui fournit une sorte de netstat (liste toutes les connexions ouvertes et les serveurs en écoute) plus pleins d'infos fort intéressantes.
Pleins de trucs :
tcpMaxConn(4) est le nombre maximum de connexions TCP que l'équipement peut
accepter.
tcpConnTable(13) est une table contenant des tcpConnEntry(1) qui sont composées
de :
tcpConnState(1): état de la connexion (1: fermée, 2: en écoute (serveur), 5: établie, 10: fermée, 12: fermeture de la connexion ordonnée par le manager (dele-teTCB))
tcpConnLocalAddress(2): adresse locale pour cette connexion (0.0.0.0 pour un serveur acceptant des connexions depuis n'importe quelle interface)
tcpConnLocalPort(3): port local
tcpConnRemAddress(4): @IP destinataire de cette connexion
tcpConnRemPort(5): port de destination.
Ca nous permet de savoir si des serveurs écoutent sur cette machine, et avec quelles machines cet équipement est actuellement en relation.
* UDP(7) permet de récup le même style d'info pour le proto UDP.
udpTable(5): contient la liste des ports (udpEntry(1)) sur lesquelles une
application écoute et attends la réception de données en UDP.
Une udpEntry contient les champs suivants :
udpLocalAddress(1): l'adresse de l'interface sur laquelle le serveur "écoute".
udpLocalPort(2): le port local sur lequel l'application "écoute".
De la même manière qu'avec TCP, on peut ainsi connaître les ports ouverts
sur chaque interface sans avoir à scanner le réseau de manière bruyante et
fortement repérable !
* EGP(8) idem ICMP
* ... il en existe d'autres en fonction de la version de la MIB (ici MIB-I).
Et si on s'amusait un peu :))
peu plus fun :)
Linux est formidable !Il fournit,avec le paquetage ucd-snmp (à récupérer sur freshmeat.net),des outils permettant d'accéder en lecture/écriture aux données des agents :)
C'est les commandes snmpwalk (pour récuperer toutes les valeurs des données situées à partir d'un certain point de l'arborescence), snmptable (plus sympa pour récupérer des variables de type table (vous comprendrez en utilisant snmpwalk ;)) et snmpset (pour modifier la valeur de variable) qui fonctionnent comme ca : on interroge la valeur de la variable 1.5 (system.sysName) => on doit rajouter .0 à la fin car c'est une variable de type simple):
[uzy@bocal ~]$ snmpget 172.23.4.19 private 1.5.0
system.sysName.0 = SWITCH1
Bon, on va quand même pas faire tout l'arbre un par un... utilisons snmpwalk sur toute l'arborescence débutant à sys !!!
[uzy@bocal ~]$ snmpwalk 172.23.4.19 private 1
system.sysDescr.0 = BayStack 450-24T HW:RevL FW:V1.46 SW:v3.0.0.41 ISVN:0
system.sysObjectID.0 = OID: enterprises.45.3.35.1
system.sysUpTime.0 = Timeticks: (235697570) 27 days, 6:42:55.70
system.sysContact.0 = Pierpoljack
system.sysName.0 = SWITCH1
system.sysLocation.0 = Au_pied_de_la_tour_Eiffel
system.sysServices.0 = 3
system.sysORLastChange.0 = Timeticks: (0) 0:00:00.00
Pour la modification, voici les principaux types : ("man snmpset" pour
tous les types)
i ENTIER
s CHAINE DE CARACTERES
a @IP
On modifie cette valeur (le s est pour STRING car le champ en question est de
type CHAINE DE CARACTERES) :
[uzy@bocal ~]$ snmpset 172.23.4.19 private 1.5.0 s
"UZY_CONTENT"
system.sysName.0 = UZY_CONTENT
Récupération de table :
[uzy@bocal ~]# snmptable 172.23.4.19 private 4.20
SNMP table: ip.ipAddrTable
ipAdEntAddr ipAdEntIfIndex ipAdEntNetMask ipAdEntBcastAddr ipAdEntReasmMaxSize
172.23.4.19 1 255.255.254.0 1 1512
Donc, là on n'a qu'une seule interface, mais on peut voir que son @IP est 172.23.4.19 et que son masque de sous-réseau est 255.255.254.0.
Après, à vous de faire preuve d'imagination pour explorer la MIB et recueillir les informations que vous recherchez !
Pensez bien que lorsque vous tapez les identifiants 1.5.0, le système considère que vous vous placez déjà dans le chemin suivant : iso.org.dod.internet.mgmt.mib.
Vous n'avez plus qu'à taper l'identifiant de sys, ip, tcp, udp, interface, at, ... plus les champs nécessaires pour atteindre la variable recherchée.
Vous pouvez également taper l'ensemble des identifiants à partir de la racine en démarrant par un '.' (à ce moment là, il faut donner tous les champs .iso.org.dod....).
Quelques petites commandes sympas (mais pas forcément très intelligentes utilisées tel quel ;) :
Fermeture d'une connexion TCP (172.23.4.237:2524 => 172.23.4.19:23) :
(tapez "snmpwalk 172.23.4.19 private tcp.tcpConnTable.tcpConnEntry"
pour avoir une liste des connexions)
[uzy@bocal ~]# snmpset 172.23.4.19 private
tcp.tcpConnTable.tcpConnEntry.tcpConnState.172.23.4.19.23.172.23.4.237.2524 i 12
(la valeur 12 correspond à deleteTCB (fermeture dela connexion demandée par le
manager)
Arrêt d'une interface réseau :
[uzy@bocal ~]# snmpset 172.23.4.19 private interfaces.ifTable.ifEntry.ifAdminStatus.4 i 2 interfaces.ifTable.ifEntry.ifAdminStatus.4 = down(2)
Conclusion
Bon, voilà... Vous avez maintenant une bonne base pour explorer le monde de SNMP et des MIBS... Ces informations sont à utiliser pour comprendre l'architecture d'un réseau et son fonctionnement et pour expérimenter certains failles sur votre réseau local.
Ces commandes ne marcheront que si votre machine est autorisée à accéder à la communauté private de l'équipement destination.
Si l'admin à eu la bonne idée de changer le nom de la communauté principale ou de poser des filtres par @IP aux accès aux agents SNMP, il ne vous reste plus qu'à sniffer le réseau (en UDP) pour récupérer le nom de ladite communauté et à faire du spoofing d'IP pour toute interrogation ou modification de base (avec l'@IP de la station de management en source par exemple :)...
Je ne connais pas d'outils qui fasse cela, il ne me/vous reste plus qu'à le développer !
Sachez enfin que depuis sa création, le protocole SNMP a évolué et il existe notamment de nos jours SNMPv3 qui permet le cryptage et une authentification plus forte ! Dans ce cas, les opérations seront plus délicates (et plus excitantes aussi ;) !
uZy