Sécurité

Sécurité jpp

La sécurité sera ici abordée essentiellement coté réseau avec IPS/IDS et instruments de contrôle des flux réseaux. 
En effet la plupart des "ennuis" et autres "malwares" arrivent par le réseau, sans parler de virus permettant d'installer des portes dérobées et autres joyeusetés, phishing ....
Il import donc de limiter au maximum les possibilités "d'entrée" dans votre réseau. Si vous disposez de plusieurs machines connectées sur un réseau interne vous utilisez probablement une machine W... il faut donc impérativement interdire l'accès à tous les ports relatifs aux partages depuis "l'extérieur", un bon Firewall, si possible placé sur une machine agissant en tant que pont vers Internet permet d"éviter d'ouvrir ce genre de portes aux méchants qui se cachent lâchement ... derrière des FAI laxistes. 
Un bon contrôle supplémentaire n'est pas inutile et certains outils permettent de "jeter un oeil" sur ce qui passe dans les tuyaux et/ou de bloquer de vilaines choses.

​Pour plus de détails vous pouvez consulter la page "Mesures; monitoring" qui présente plus en détails cette problématique.

 

AbuseIPDB Contributor Badge

 

Sécurité Apache : modsec

Sécurité Apache : modsec durp11_admin

Un serveur Apache est, en lui même, assez sécurisé, mais les applications qu'il héberge peuvent présenter des défauts de sécurité. 
Certains IDS/IPS, par exemple Suricata, peuvent utiliser des règles améliorant la sécurité des applications. Mais, car il y a un "mais", le passage en HTTPS empêche pratiquement l'utilisation de ces règles car le contenu des flux HTTPS ne peut être analysé dans le flux des données réseau. Il faut donc se tourner vers une méthode qui agisse après le traitement HTTPS, il faut donc opérer entre le traitement HTTPS et l'application. 
C'est ainsi que "Modsecurity" (de son petit nom "modsec"), module spécialisé pour Apache, permet d'utiliser des règles sur les données "décodées" et donc d'avoir une analyse fine, comme le fait par exemple Suricata pour le HTTP simple ou les autres protocoles non TLSisés.

Remarques au passage
Si vous utilisez "Phpmyadmin" veillez à bien le configurer, à nettoyer les scripts de démarrage et filtrer au maximum l'accès à ses fonctions. Le filtrage par IP en limitant à une IP utilisée pour l'administration est une bonne méthode. En effet une grande partie des "pirates" cherchent un accès par des URL comportant "/phpmyadmin" (éventuellement avec quelques majuscules ou raccourcis), ou d'autres chemins connus "/pma", "/myadmin" .... en ciblant souvent les modules "setup...." ou d'autres réputés présenter une faille. 
De toutes façons il ne me semble pas "sain" d'installer de tels outils sur des machines de production en contact avec Internet afin de limiter au maximum la surface d'attaque. 
Il y a d'autre part intérêt, on ne le répète jamais assez, à mettre rapidement en place les mises à jour de sécurité de tous les logiciels.

Surveillance : Suricata

Surveillance : Suricata durp11_admin

Articles commencés avec la version 2.0 de suricata. Petites mises à jour pour la version 3.0,  notamment le fichier de paramètres "suricata.yaml".
En 2020 on est passé en version 4.1, en 2023 en 6.0 et en 2024 en 7.0. 

 
La surveillance d'un réseau est une condition indispensable de la sécurité. Après le Firewall qui assure une sécurité "passive" il peut être intéressant d'installer un système d'analyse des flux réseau. Le plus connu de ces logiciels dans le domaine OpenSource est Snort et son cochon mascotte
J'ai déjà installé Snort (paquet Debian standard) avec l'option stockage dans une base Mysql et affichage des résultats à l'aide du logiciel "Base" fourni par le paquet Debian Acidbase. 
J'ai découvert dans un magazine (MISC pour ne pas le citer) un nouveau (enfin presque) logiciel effectuant ce type de travail et j'ai décidé de le tester. Petit problème il n'existe pas de paquet Debian et il faut donc charger, compiler et installer tout ce petit monde. 
Je n'entrerais pas dans les discussions (vous avez dit troll ?) au sujet d'une lutte (d'influence) entre Snort et Suricata au sujet des performances et de la compatibilité des règles.

Pour mémoire il s'agit de :

Note : Snorby est obsolète et impossible à mettre à jour (utilisation d'une version très ancienne de Ruby) et je prépare une application équivalente baptisée Snorbis (note 2024 : qui fonctionne correctement depuis des années).

Les opérations seront donc séparées en trois parties principales, on installe Snorby avant Barnyard car Snorby initialise la base de données. Cette base est très semblable à celle de Snort ... avec quelques bricoles en plus.

Après un premier test "à blanc" sur un portable (Debian 6.0), le test suivant a été réalisé sur une machine virtuelle "vierge" afin de bien faire ressortir toutes les dépendances.

La MV (avec KVM bien sûr!) a été installée sur une Debian (6.0) a été utilisée pour initialiser cette machine avec le minimum et "gcc4.7" sans oublier "ln -s /usr/bin/gcc4.7 /usr/bin/gcc" et "g++4.7" avec son petit lien en "g++". 
En ce qui concerne la gestion des règles je présenterai, peut-être, plus tard quelque chose couvrant ce sujet.

Suricata : installation

Suricata : installation jpp

Mise à jour juillet 2016 pour la version 3 (3.0.1 pour être précis). 
Il faut maintenant installer des choses sérieuses : "make", "wget" et "git" si ce n'est déjà fait ainsi que la triplette "mysql-client","mysql-server" ainsi que "libmysqld-dev" , je fonctionne actuellement avec MariaDB. 
J'ai créé un utilisateur "suricata" avec un mot de passe du même métal pour faire tourner le tout sans droits "root". 
Ensuite télécharger le tar.gz (1.4.1 lors des premiers tests 3.0.1 à ce jour) dans un répertoire tranquille : 
wget http://www.openinfosecfoundation.org/download/suricata-3.0.1.tar.gz ou plus récent visible sur https://oisf.net/ 
suivi d'un : tar -xvf suricata-3.0.1.tar.gz 
Il faut charger quelques dépendances spécifiques :

  • pkg-config
  • libpcap-dev
  • libpcre3-dev
  • libyaml-dev
  • libnet1-dev
  • libcap-ng-dev
  • libmagic-dev
  • libhtp-dev
  • zlib1g-dev
  • libjansson4  libjansson-dev
  • libnfnetlink0 libnfnetlink-dev
  • libnetfilter-queue-1 libnetfilter-queue-dev

Un apt-get install de toute la liste suffit. 
Ensuite le "./configure" magique permet de commencer le travail et le récap en fin d'exécution permet de vérifier si toutes les options nous conviennent :

Suricata Configuration: 
  AF_PACKET support:                       yes 
  PF_RING support:                         no 
  NFQueue support:                         no 
  IPFW support:                            no 
  DAG enabled:                             no 
  Napatech enabled:                        no 
  Unix socket enabled:                     no 
  libnss support:                          no 
  libnspr support:                         no 
  libjansson support:                      no 
  Prelude support:                         no 
  PCRE jit:                                no 
  libluajit:                               no 
  libgeoip:                                no 
  Non-bundled htp:                         no 
  Old barnyard2 support:                   no 
  CUDA enabled:                            no 
  Suricatasc install:                      yes 
  Unit tests enabled:                      no 
  Debug output enabled:                    no 
  Debug validation enabled:                no 
  Profiling enabled:                       no 
  Profiling locks enabled:                 no 
Generic build parameters: 
  Installation prefix (--prefix):          /usr/local 
  Configuration directory (--sysconfdir):  /usr/local/etc/suricata/ 
  Log directory (--localstatedir) :        /usr/local/var/log/suricata/ 
  Host:                                    i686-pc-linux-gnu 
  GCC binary:                              gcc 
  GCC Protect enabled:                     no 
  GCC march native enabled:                yes 
  GCC Profile enabled:                     no 
To build and install run 'make' and 'make install'. 
You can run 'make install-conf' if you want to install initial configuration 
files to /usr/local/etc/suricata/. Running 'make install-full' will install configuration 
and rules and provide you a ready-to-run suricata. 
To install Suricata into /usr/bin/suricata, have the config in 
/etc/suricata and use /var/log/suricata as log dir, use: 
./configure --prefix=/usr/ --sysconfdir=/etc/ --localstatedir=/var/

Pour plus de sécurité (isolation dans un répertoire spécifique) je vais lancer la configuration avec les options suivantes : 
./configure --prefix=/opt/suricata \ 
            --sysconfdir=/opt/suricata/ \ 
            --localstatedir=/opt/suricata/ 
Le log final contient :

Generic build parameters: 
  Installation prefix (--prefix):          /opt/suricata 
  Configuration directory (--sysconfdir):  /opt/suricata/suricata/ 
  Log directory (--localstatedir) :        /opt/suricata/log/suricata/

Ce n'est pas tout à fait ce que je voulais et je corrige "un peu" le Makefile (aux environs de la ligne 245) pour obtenir un "arbre" de répertoires sous /opt/suricata :

e_localstatedir = /opt/suricata/run 
e_logdir = /opt/suricata/log 
e_logfilesdir = /opt/suricata/log/files 
e_magic_file = /usr/share/file/magic 
e_rundir = /opt/suricata/run/ 
e_sysconfdir = /opt/suricata/etc 
e_sysconfrulesdir = /opt/suricata/etc/rules

Je lance enfin le "make" qui se déroule sans ennuis ... de même pour le "make install" ... qui m'installe un arbre de répertoires "convenable", enfin qui me convient, "make install-conf" installe la config de base puis "make install-full"  télécharge et installe un jeu de règles standard. 
Image de mon arbre de répertoires :

drwxrwsr-x  9 root suricata 4096 2013-05-06 14:39 . 
drwxrwsr-x 18 root staff    4096 2013-05-06 13:40 .. 
drwxr-xr-x  2 root suricata 4096 2013-05-07 16:29 bin 
drwxr-xr-x  3 root suricata 4096 2013-05-07 17:09 etc 
drwxr-xr-x  3 root suricata 4096 2013-05-06 14:37 include 
drwxr-xr-x  4 root suricata 4096 2013-05-06 15:10 lib 
drwxrwxr-x  3 root suricata 4096 2013-05-07 17:14 log 
drwxrwxr-x  2 root suricata 4096 2013-05-07 16:07 run 
drwxr-sr-x  3 root suricata 4096 2013-05-06 14:37 share

J'ai donné au user "suricata" les droits "group" sur l'ensemble des répertoires de /opt/suricata et les droits d'écriture sur les répertoires "log" et "run". 
Il faut ensuite réaliser un script de démarrage car je n'en ai pas trouvé de disponible (mon exemplaire est disponible par le lien en bas de page). 
Il faut ensuite légèrement modifier le fichier "etc/suricata.yaml" pour l'adapter à la structure de mes répertoires. J'ai désactivé l'option "fast log" qui consomme trop d'espace pour mes besoins de test sur un portable. J'ai aussi réduit la fréquence de stockage des statistiques à 30 minutes. 
Après le lancement du produit on peut constater l'arrivée de quelques alertes ... mais elles sont au format "Unified2" et donc illisibles il faut utiliser un interface pour les rendre compréhensibles. Le projet conseille "Barnyard2" qui les enregistre dans une base de données (ici Mysql) et que je vais essayer au prochain épisode. 
Le paramétrage du fichier de configuration est très bien expliqué (au moins pour les options "courantes") dans le fichier suricata.yaml. 
Vous trouverez ces fichiers en attachement, mes quelques modifications du fichier YAML sont précédées d'un commentaire #JPP.

Suricata : statistiques

Suricata : statistiques jpp

Une petite statistique (sur 30 jours 26/11/2018 au 26/12/2018) sur les événements "bloqués" par Suricata : 
Tableau statistique 
La grande majorité des rejets (j'utilise "drop" pour la plupart des événements) sont dus à des attaques sur le site WEB, Ces attaques sont, en général, le fait de "script-kiddies" utilisant des outils en kit, en effet on retrouve très souvent les mêmes motifs dans les URL testées. Il y a aussi des attaques ciblées visant un défaut qui vient d'être divulgué, il en existe un actuellement sur /wp-login.php qui revient très souvent depuis début décembre. 
Note 2021 : les accès sur /wp-login.php existent toujours, j'en voit passer plusieurs par jour, tant en HTTPS qu'en HTTP.

Ceci semble prouver qu'une mise à jour régulière des logiciels est importante, je trouve régulièrement référence à des "exploits" adaptés à des versions antérieures à celles installées dans mes systèmes. 
Les attaques sur SMTP sont le plus souvent le fait de spammeurs recherchant des serveurs "open relay", en existe-t-il encore ?

Suricata version 2.0

Suricata version 2.0 jpp

Une nouvelle version (2.0) de Suricata "chauffait" depuis quelques temps et je l'ai chargée et compilée sans aucune nouvelle dépendance. 
Le 25 juin 2014 sortie de la version 2.0.2 : téléchargeable ici. (obsolete en 2017) 
Le 23 septembre 2014 sortie de la version 2.0.4 : téléchargeable ici. (obsolete en 2017) 
La version 2.0.4 se compile et s'exécute comme la version 2.0.2 (même paramétrage). 
A titre indicatif je "configure" avec le script suivant avant de lancer le "make" fatidique : 
#!/bin/bash 
PFX='--prefix=/opt/suricata/ ' 
CFG='--sysconfdir /opt/suricata/etc/ ' 
LOC='--localstatedir=/opt/suricata/var ' 
OPTIONS='--enable-gccprotect --enable-geoip --enable-nfqueue --enable-unix-socket' 
./configure $PFX $CFG $LOC $OPTIONS 2>&1 | tee LOG_CONFIGURE

Les options permettent d'utiliser des filtres "géographiques" et d'utiliser le mode IPS (utilisation de NFQUEUE). 

A première vue le paramétrage existant en 1.4 est parfaitement fonctionnel et le système tourne normalement. Il semble qu'une légère amélioration de performance soit présente, mais cela n'est pas transcendant et de toutes façons je suis limité par la liaison internet sur laquelle le maximum théorique #8Mo/s est atteint régulièrement.

Le fonctionnement en IPS est parfait et la mise en place de quelques "drop" permet de se débarrasser de quelques accès intempestifs. Le seul "manque" est que les "drops" ne laissent pas une trace spécifique dans l'interface de visualisation. De même le fichier "drop.log" ne contient aucune référence à la règle ayant provoqué le rejet et n'est pas affecté à un niveau de danger particulier ce qui est un peu dommage.

Il faut maintenant étudier la doc pour profiter des nouvelles fonctionnalités.

Suricata version 3.0

Suricata version 3.0 jpp

La version 3.0 est, au point de vue de la compilation de de l'utilisation peu différente de la version 2, j'ai mis à jour la page correspondant à l'installation
Actuellement Suricata est "en exploitation" chez moi et tourne sur la machine servant de pont vers Internet. 
Le fonctionnement est effectué en mode IPS et permet de bloquer quelques empêcheurs de surfer en rond et de repérer les tentatives d'accès du style "phpmyadmin" ... et d'autres. Au moment de Heartbleed un grand nombre de tentatives d'exploitation étaient visibles. 
La machine dispose de deux interfaces "BR0" (vers le modem) "BR1" vers le réseau interne, les autres machines du réseau accèdent toutes à Internet à travers un switch raccordé à "BR1". Suricata est utilisé en entrée et en sortie, tout est filtré ! 
Snorby permet de consulter l'historique des alertes et permet :

  • d'éliminer les  faux positifs,
  • de repérer les tentatives d'accès frauduleux.

Il est intéressant de "marquer" dans l'interface les noms DNS des serveurs "sûrs" afin de passer rapidement des alertes en "faux positif" ou de les détruire quand le responsable est "banni" par le pare-feu.

Suricata version 4.0

Suricata version 4.0 jpp

La dernière version de Suricata est la 4.0.0 parue au début du quatrième trimestre 2017. 
J'ai attendu quelque peu avant de l'installer et la 4.0.1 était sortie, c'est donc celle que j'ai installée. 
La compilation et l'installation sont identiques à celles des versions 3.x. Je n'ai pas non plus eu besoin de modifier les fichiers de paramétrage et tout a fonctionné au premier lancement.

J'ai depuis installé la version 4.0.4 de février 2018 sans plus de problèmes, that's all folks.
 

Snorby Gui alertes

Snorby Gui alertes jpp

Le couple Suricata/Barnyard2 détecte les événements réseau notables et les insère dans une base Mysql/MariaDB. 
C'est bien, mais pour visualiser ces alertes un outil sympa est "Snorby" : c'est une interface WEB très complète et assez agréable à utiliser. Son développement n'étant plus assuré cela risque à terme de poser problème.

Je l'utilise depuis un bon moment et j'ai presque toujours eu des problèmes lors de son installation ou lors de changement de version de système, même en changeant de machine j'ai rencontré des difficultés. 
Quelques articles résument des années d'utilisation. 
Juillet 2018, ce logiciel est toujours en cours d'utilisation ... 
Janvier 2019, Snorby n'a pas supporté les dernières mises à jour du système et je ne suis pas arrivé à le faire refonctionner ... 
J'ai donc réalisé un nouveau logiciel permettant de le remplacer, ainsi est né "Snorbis".  qui utilise les mêmes tables que Snorby toujours alimentées par Barnyard2.
 

Snorbis : remplacer Snorby

Snorbis : remplacer Snorby jpp

Cette application sans prétentions présentera :

  1. La même base de données que Snorby en y ajoutant une historisation dans des tables séparées des tables courantes, ainsi seules les anomalies non expliquées sont visibles dans les écrans de contrôle.
  2. Quelques statistiques
  3. Quelques fonctions d'automatisation destinées à simplifier en l'automatisant le traitement des "faux positifs" et des "anomalies normales" telles que les messages causés par une machine Debian effectuant sa mise à jour qui génère des enregistrements.

Le principe adopté est de ne pas utiliser de Framework pour limiter les dépendances, seul PHP7 et quelques librairies "de base" sont utilisées dans mes différents traitements. 
Cela avance bien, mais sans aucun framework c'est un peu un travail de fourmi ... Publication prévue pour avril 2020 le temps de peaufiner la doc et d'éradiquer les derniers bugs. 
NOTE février 2021 : Suricata ayant supprimé la sortie "unified2" la base de données "snorby" ne sera donc plus alimentée par Barntard2 ...  je suis en train de mettre au point un petit logiciel (Programme Python) pour alimenter une base équivalente et utiliser l'application "Snorbis" légèrement modifiée qui s'appellera alors "SURI-DB".
Voir quelques écrans de "Snorbis".

Snorbis : copies ecrans

Snorbis : copies ecrans jpp

Trois exemples d'écrans de Snorbis
Ecran de classification des événements : 
Ecran événements

Ecran de statistiques , page par jour :

 Snorbis : écran statistiques par jour

  Ecran de gestion de l'autopurge (purge automatique des événements de structure connue et à classifier comme "normaux") :

Ecran de gestion de l'autopurge

OSSEC

OSSEC jpp

 
OSSEC installation et usage. 
Ossec est un HID qui semble très complet, de conception assez récente il est actuellement détenu par une société privée (Trend Micro) qui propose une version libre et une version professionnelle. 
OSSEC n'est pas un logiciel très compliqué (au moins extérieurement) mais l'installation est un peu complexe car le produit n'est pas intégré dans une distribution et il faut résoudre soi même les problèmes de compatibilité (voir plus loin le problème posé lors d'un upgrade de version Debian). 
Mais les fonctionnalités sont engageantes et j'ai eu envie de le voir à l'oeuvre.

Note 2016 : le produit est toujours actif en version 2.8 et l'interface "Analogi" fonctionne toujours bien qu'il génère des messages d'erreur PHP dans les logs Apache. 

Note 2018 : Le passage de OSSEC en version 2.9.3 s'accompagne d'une modification du schéma de la base de données Mysql et Analogi devient impossible à utiliser (multiples erreur SQL). 
J'ai trouvé une version "compatible" utilisant Analogi comme fondation mais entièrement "revampée". Malheureusement cette version téléchargeable sur https://github.com/NunesGodinho/OSSEC-WUI n'est pas non plus adaptée aux versions >= 2.9.2. 
Je suis en train de reprendre cette version comme base et de l'adapter au schéma de la base de OSSEC 2.9.3 en y ajoutant quelques fonctionnalités : statistiques, mise à jour du mapping des signatures / catégories, authentification ... 
Cette version est aujourd'hui prête (voir ici un groupe d'articles avec copies d'écrans) et est diffusée sur github elle a été testée sur OSSEC V3.0.0 stable dont la structure de base de données est compatible.

Note 2021 : Fonctionnement en version 3.2 
Depuis la panne du serveur réparée en septembre je n'ai pas eu le loisir de réinstaller OSSEC ... 
Mais j'y pense.

Note 2023 : Je pense réinstaller la version 3.6 dès que possible et présenter les nouvelles fonctionnalités, notamment OSSEC+.

OSSEC : la vie avec OSSEC

OSSEC : la vie avec OSSEC jpp

La vie avec OSSEC est assez facile, le produit est, d'origine, très bien paramétré. Les options fournies par défaut permettent déjà une analyse très fine des événements qui se produisent dans vos machines. 
J'ai fait les tests avec : 
- un ossec serveur sur une Centos 5.5 
- un agent Windows sur une machine XP 
- un agent Linux sur une machine Debian. 
L'installation étant détaillée par ailleurs je n'y reviendrais pas, la bonne chose est que pour un petit réseau (moins de 10 machines) il n'y a pas besoin de retoucher le paramétrage. Le système est parfois un peu bavard (pas mal de mails) mais toutes les informations sont là : 
- les "login", on s'intéressera surtout aux login refusés ... 
- les fichiers modifiés (attributs, taille ....), certains fichiers sont peut-être superflus, mais on s'y habitue. 
- l'installation de logiciels est parfaitement repérée, que ce soit pas "yum update" ou "apt-get upgrade". 

Pour la partie interface Web, qui paraît un peu "spartiate au début", on peut faire rapidement un grand nombre d'interrogations ciblées : 
- y-a-t-il eu des tentatives de connexion multiples 
- Quels comptes ont été modifiés 
Les principaux critères de sélection sont (d'autres sont disponibles tels que le numéro de la règle ayant repéré l'erreur) : 
- fourchette date/heure

OSSEC : installation

OSSEC : installation jpp

Note : cet article est ancien (historique presque) voir la dernière version ici. 
L'installation pour tests a été faite sur une machine Centos 5.5 virtualisée avec XEN. 
Après récupération des sources (pour moi version 2.4.1) et détarage dans un répertoire d'installation il suffit de lancer le script "install.sh" 
Après le choix de la langue (fr pour moi) un récapitulatif de votre système s'affiche 
=====================================================================

OSSEC HIDS v2.4.1 Script d'installation - http://www.ossec.net 
  
 Vous êtes sur le point d'installer OSSEC HIDS. 
 Vous devez avoir une compilateur C préinstallé sur votre système. 
 Si vous avez des questions ou des commentaires, envoyez un email 
 à dcid@ossec.net (ou daniel.cid@gmail.com). 
  
  - Système: Linux machine.domaine 2.6.18-194.3.1.el5 
  - Utilisateur: root 
  - Hôte: machine.domaine 


  -- Appuyez sur Entrée pour continuer ou Ctrl-C pour annuler. --

====================================================================== 
On appuye bien sûr sur entrée ... et l'on doit alors choisir l'option d'installation entre : 
serveur    serveur d'analyse OSSEC 
agent    agent transmettant à un serveur     
local    machine indépendante 
Pour cette première approche je choisis "local" 
Pour le répertoire d'installation je garde "/var/ossec". Je configure les alertes par Email et saisis une adresse mail valide en précisant le serveur de mail à utiliser (localhost) puisque j'ai un serveur Postfix local. 
Je précise ensuite que je veux démarrer le démon de controle d'intégrité et le moteur de détection de rootkit. 
=======================================================================

1- Quel type d'installation voulez-vous (serveur, agent, local ou aide) ? local 

  - Installation en local choisie. 

2- Définition de l'environnement d'installation. 

 - Choisissez votre répertoire d'installation de OSSEC HIDS [/var/ossec]: 

    - L'installation sera faite sur  /var/ossec . 

3- Configuration de OSSEC HIDS. 

  3.1- Voulez-vous une alerte par email ? (o/n) [o]: o 
   - Quel est votre adresse email ? xxxxxx@xxxxxx 
   - Quel est l'adresse IP ou le nom d'hôte de votre serveur SMTP ? localhost 

  3.2- Voulez-vous démarrer le démon de vérification d'intégrité ? (o/n) [o]: o 

   - Lancement de syscheck (démon de vérification d'intégrité). 

  3.3- Voulez-vous démarrer le moteur de détection de rootkit ? (o/n) [o]: o 
  3.4- La réponse active vous permet d'éxécuter des commandes 
       spécifiques en fonction d'évènement. Par exemple, 
       vous pouvez bloquer une adresse IP ou interdire 
       l'accès à un utilisateur spécifique. 
       Plus d'information sur : 
       http://www.ossec.net/en/manual.html#active-response 
        
   - voulez-vous démarrer la réponse active ? (o/n) [o]: o 
   - Par défaut, nous pouvons activer le contrôle d'hôte 
     et le pare-feu (firewall-drop). Le premier ajoute 
     un hôte dans /etc/hosts.deny et le second bloquera 
     l'hôte dans iptables (sous linux) ou dans ipfilter 
     (sous Solaris, FreeBSD ou NetSBD). 
   - Ils peuvent aussi être utilisés pour arrêter les scans 
     en force brute de SSHD, les scans de ports ou d'autres 
     formes d'attaques. Vous pouvez aussi les bloquer par 
     rapport à des évènements snort, par exemple. 

   - Voulez-vous activer la réponse pare-feu (firewall-drop) ? (o/n) [o]: o 
     - pare-feu (firewall-drop) activé (local) pour les levels >= 6 

   - liste blanche (white list) par défaut pour la réponse active : 
      - 192.168.1.x 
      - 192.168.1.y 

   - Voulez-vous d'autres adresses IP dans votre liste (white list) ? (o/n)? [n] o

============================================================================= 
J'ajoute ici les adresses IP que je ne veux pas voir bannir lors des tests ... 
=============================================================================

3.6- Mise en place de la configuration pour analyser les logs suivants : 
    -- /var/log/messages 
    -- /var/log/secure 
    -- /var/log/maillog 

 - Si vous voulez surveiller d'autres fichiers, changez 
   le fichier ossec.conf en ajoutant une nouvelle valeur 
   de nom de fichier local. 
   Pour toutes vos questions sur la configuration, 
   consultez notre site web http://www.ossec.net
    
    
   --- Appuyez sur Entrée pour continuer ---

============================================================================= 
Ensuite la compilation commence et est très courte . 
=============================================================================

- Configuration correctement terminée. 

 - Pour démarrer OSSEC HIDS: 
        /var/ossec/bin/ossec-control start 

 - Pour arrêter OSSEC HIDS: 
        /var/ossec/bin/ossec-control stop 

 - La configuration peut être visualisée ou modifiée dans /var/ossec/etc/ossec.conf 


    Merci d'utiliser OSSEC HIDS. 
    Si vous avez des questions, suggestions ou si vous trouvez 
    un bug, contactez nous sur contact@ossec.net ou en utilisant la 
    liste de diffusion publique sur ossec-list@ossec.net 
    ( http://www.ossec.net/en/mailing_lists.html ). 

    Plus d'information peut être trouver sur http://www.ossec.net 

    ---  Appuyez sur Entrée pour finir (peut-être plus d'info plus bas). ---

============================================================================= 
Un script de démarrage "/etc/init.d/ossec" a été ajouté et activé correctement dans la machine. 
Un petit reboot pour valider le tout et ça repart, on peut au passage voir le démarrage de OSSEC. Un premier mail de lancement est aussitôt envoyé, c'est une alerte de niveau 3 (les niveaux vont de 1 à 15, 15 étant l'alerte maxi) me signalant le démarrage du démon : 
OSSEC HIDS Notification. 
2010 Jun 29 14:06:13 
Received From:machine.domaine->ossec-monitord 
Rule: 502 fired (level 3) -> "Ossec server started." 
Portion of the log(s): 
ossec: Ossec started. 
--END OF NOTIFICATION 

Je me connecte en "root" sur la machine, nouvelle alerte de niveau 4 cette fois. 
Je me connecte avec un autre utilisateur cela déclenche un nouveau mail de "first time user logged in". Une autre connexion avec le même utilisateur ne déclenche aucun mail. Tout cela semble bel et bon. 
 

OSSEC : installation agent Linux

OSSEC : installation agent Linux jpp

OSSEC : sur un "vrai" serveur

OSSEC : sur un "vrai" serveur jpp

Je n'ai pas pu tenir et disposant de quelques temps j'ai décidé de tenter l'installation de OSSEC sur mon serveur de mail. 
C'est un serveur permanent (basse consommation cf ) qui supporte déjà plein de trucs, mais c'est la seule machine en fonctionnement continu et donc apte à gérer les agents à déposer dans les autres machines. Comme c'est aussi la passerelle vers Internet, elle doit être particulièrement surveillée. 
Installer le logiciel serveur. 
Installer le support MYSQL : 
cd ..../ossec.../src 
make setdb 
Error: PostgreSQL client libraries not installed. 
Info: Compiled with MySQL support. 
Installer "libz et libz-devel" par un petit coup de "apt-get install zlib1g zlig1g-dev ". 
Il ne reste plus alors qu'à lancer la procédure d'installation. 
./install.sh 
Qui se déroule avec un petit problème car gcc me dit méchamment qu'il ne reconnait pas le switch "-R". 
Sur cette machine est installé "ZIMBRA" (Serveur mail et webmail) et ,je ne sais pas pourquoi, toutes les définitions de répertoires de librairies (par exemple : -L/usr/lib) étaient préfixés -R/usr/lib, ce qui m'a obligé à mettre un "front end" bidon pour "gcc" dont voici le script (facile !) : 
========================================================= 
#!/bin/bash 
PARAM=`echo $* |  sed 's\ /-R/\ -L/g'`  
/usr/bin/gcc $PARAM 
========================================================== 
C'est tout et la compilation se termine bien. On passe alors à la partie Mysql :

  • Créer un utilisateur dans la base MySql, c'est facile avec mysql-admin.
  • Créer le schéma de base de données,
  • Donner les droits adéquats au user
  • Lancer le script de création des tables : 
    cd .../ossec..../src/dbd_os 
    mysql --user=osssec_user --password=ossec_mot_de_passe -D nom_de_la_base <mysql.schema
  • Ajouter dans /var/ossec/etc/ossec.conf le morceau (choisi) juste après "<ossec_config>" et avant <global> : 
     <database_output> 
       <hostname>localhost</hostname> 
       <port>3306</port> 
       <username>ossec_user</username> 
       <password>ossec_mot_de_passe</password> 
       <database>ossec_base</database> 
       <type>mysql</type> 
    </database_output>
  • Surtout ne pas oublier l'incantation à "/var/ossec/bin/ossec-control enable database"   avant de lancer le service.


Installer l'interface WEB

  • Décompresser l'archive dans "/var/www"
  • Aller dans le répertoire "/var/www/ossec_......"  pour exécuter le script "setup.sh"
  • Ne pas oublier (comme moi la première fois), d'affecter le user de lancement de Apache (www-data pour Debian) dans le groupe "ossec" (et redémarrer Apache), sinon vous n'obtiendrez que des messages d'insulte de type "access denied" ou au mieux un message "No agent available" dans l'interface alors même que le mails sont émis normalement et que tout semble baigner.
  • Mettre en place le petit fichier de déclaration pour Apache (/etc/apache2/conf.d pour Debian, /etc/httpd/conf.d pour les redhat like) :


# This configuration file allows the manual to be accessed at  
# http://localhost/ossec/&nbsp;

AliasMatch ^/ossec(?:/(?:de|en|fr|ja|ko|ru))?(/.*)?$ "/var/www/ossec$1" 
<Directory "/var/www/ossec"> 
    Options Indexes 
    AllowOverride None 
    Order allow,deny 
    Allow from all 
</Directory> 

Tester le résultat. 
Premier lancement. 
C'est horrible ! Tous les messages inscrits par ZIMBRA dans "/var/log/syslog ou /var/log/messages" déclenchent un mail d'anomalie de quoi saturer rapidement une boite mail. Je stoppe donc rapidement le service OSSEC. 
Après une petite réflexion un plan d'action se dessine : 
Actions à réaliser : 
1) modifier les paramètres de rsyslog dasn "/etc/rsyslog.conf" (utilisé par défaut sur ce serveur)

  • la ligne  : *.*;auth,authpriv.none        -/var/log/syslog 
    devient  :  *.*;auth,authpriv.none,mail,local0,local1    -/var/log/syslog
  • la ligne  : mail,news.none        -/var/log/message  
    devient  :      mail,news.none;\ 
    local0,local1;            -/var/log/messages

Ainsi les traces de ZIMBRA devraient être supprimées des logs "standard" et ne plus polluer les détections d'anomalies. Mais en contrepartie les actions de ZIMBRA ne seront plus analysées. 
2) Chercher un moyen d'analyser les logs de ZIMBRA. Il faut pour cela créer un nouveau "parser" capable d'analyser les logs de Zimbra. 
Heureusement Internet est là (http://www.zimbra.com/forums/administrators/39764-ossec-rules.html) et on y trouve exactement ce qu'il nous faut. 
Le gars qui a écrit ces règles a l'air de savoir de quoi il parle, je lui fait donc confiance et intègre ces règles là ou il est dit de le faire. 
Deuxième lancement. 
C'est le pied ... les messages de Zimbra ne polluent plus les détections ... si, il reste une source de mails intempestifs, c'est l'analyse du fichier "auth.log" où les "sudo .... " de Zimbra génèrent encore une palanquée d'anomalies (deux ou trois toutes les deux minutes) il faut donc faire quelque chose car je veux pas traiter plus de 1000 messages par jour ! 
Là aussi un peu de réflexion et beaucoup de lecture de la doc (RTFM) permettent d'entrevoir une solution : 
Modifier le comportement d'une règle standard. Cette possibilité est géniale et permet de traiter sans problème, et avec élégance,  des cas particuliers. C'est un gros plus de OSSEC par rapport à d'autres outils. 
Il suffit de créer une règle (avec la plage de numérotation qui va bien (100000 à 110000) ). Je crée donc une règle "101001" qui référence la règle 5402 (if_sid) qui me cause des ennuis et ajoute une contrainte spécifique (match), si cette règle "matche" alors le niveau de l'erreur est ramené à zéro (pas d'erreur). Et ceci s'écrit : 
 <rule id="101001" level="0"> 
    <if_sid>5402</if_sid> 
    <match>COMMAND=/opt/zimbra/libexec/zmm</match> 
    <description>Kill ZIMBRA SUDO </description> 
 </rule>

Traduction : Si la règle 5402 est levée (les messages indiquent toujours le numéro de la règle qui les a déclenchés) et si la ligne "offensante" de log comporte la chaine "COMMAND=/opt/zimbra/libexec/zmm" alors le niveau d'erreur sera zéro. 
A ajouter dans le groupe de règles dans lequel on a déjà intégré les règles "zimbra" du site mentionné au dessus. 
Je ne suis pas un grand amateur de XML, mais à ce niveau là j'arrive à suivre. 
On redémarre le service et on attend un peu pour voir si la modification est efficace. Après plusieurs minutes pas un seul mail à ce sujet, c'est gagné. Vite un petit test avec un autre "sudo" et ... il apparait dans la liste, c'est donc vraiment gagné. 
Quelques messages générés par AMAVIS attirent mon attention, mais il ne s'agit "que" du traitement d'un mail dont l'adresse mail comporte le mot "error" ! 
Le stockage des données dans la base Mysql est réalisé avec un modèle de données simple qui promet une grande facilité de réalisation de requêtes ciblées. Ces requêtes sont surtout intéressantes dans un réseau important, mais ici on doit pouvoir effectuer quelques tests facilement. 
L'interrogation avec "Mysql-browser" est facile car on accède immédiatement aux messages, obtenir la liste des connexions par machine et/ou par utilisateur sera super simple. 
Quelques messages du firewall apparaissent, d'autres de "SNORT" : avec quelques " Destination Unreachable Communication with Destination Host is Administratively Prohibited [**][Classification: Misc activity] [Priority: 3] ". 
En bref, après mes tests sur des machines virtuelles, cela marche assez bien dans le monde réel (a quelques adaptations faciles près) en promettant de pas noyer un pauvre administrateur sous un tas de fausses alertes.

OSSEC : passage en Debian 6

OSSEC : passage en Debian 6 jpp

J'ai dernièrement passé la machine serveur de OSSEC de Debian 5 (Lenny) vers Debian 6 (Squeeze) et lors d'une mise à jour suivante OSSEC a refusé de démarrer avec un message "libmysqlclient_15 not found". 
J'ai vérifié la version installée, c'était la 16 qui avait désinstallé la 15. 
En attendant de tester une nouvelle version de OSSEC (2.5.1, version actuelle 2.4.1) j'ai cherché où trouver cette foutue librairie. 
Quelques recherches sur le site Debian m'ont montré que ce paquet était disponible dans "Lenny" sour le nom "libmysqlclient15off", le temps mettre la bonne ligne dans mon fichier "source.list" 
un "apt-get update" et un "apt-get install libmysqlclient15off" 
plus tard tout est OK. 
Ce paquet semble exister aussi pour Ubuntu dans certains depots "universe". 

Le prochain article sera consacré à l'upgrade de OSSEC 2.4.1 en 2.5.1 avec les problèmes pénibles (pas trop j'espère) d'une mise à niveau par un fichier "tar.gz" et donc une partie de compilation.

OSSEC : passage version 2.6

OSSEC : passage version 2.6 jpp

J'ai décidé d'upgrader mon installation de OSSEC de 2.4 en 2.6, il faut rester à la pointe du progrès. 
J'ai donc téléchargé le tar.gz de la 2.6 et je l'ai installé dans un petit coin tout propre. 
Là, dans le répertoire principal un joli petit script "install.sh" nous attends. 
Mais, d'abord sauvegardons le contenu "actuel" du logiciel : /var/ossec. 
Ensuite seulement on peut frapper le fatidique "./install.sh", Eh mais non, il faut d'abord activer l'accès Mysql. On va dans le répertoire "src" et on chante un petit truc comme "make setdb" et ... l'incantation fonctionne. Un petit "cd .." et le tentant "./install.sh" :

** Para instalação em português, escolha [br] 
  ** 要使用中文进行安装, 请选择 [cn]. 
  ** Fur eine deutsche Installation wohlen Sie [de]. 
  ** Για εγκατάσταση στα Ελληνικά, επιλέξτε [el]. 
  ** For installation in English, choose [en]. 
  ** Para instalar en Español , eliga [es]. 
  ** Pour une installation en français, choisissez [fr] 
  ** Per l'installazione in Italiano, scegli [it]. 
  ** 日本語でインストールします.選択して下さい.[jp]. 
  ** Voor installatie in het Nederlands, kies [nl]. 
  ** Aby instalować w języku Polskim, wybierz [pl]. 
  ** Для инструкций по установке на русском ,введите [ru]. 
  ** Za instalaciju na srpskom, izaberi [sr]. 
  ** Türkçe kurulum için seçin [tr]. 
  (en/br/cn/de/el/es/fr/it/jp/nl/pl/ru/sr/tr) [en]: fr

Il y a quelques hiéroglyphes mais je choisis bravement "fr".

OSSEC HIDS v2.6 Script d'installation - http://www.ossec.net&nbsp;
Vous êtes sur le point d'installer OSSEC HIDS. 
Vous devez, bien sûr, avoir un compilateur C préinstallé sur votre système. 
Si vous avez des questions ou des commentaires, envoyez un email 
à dcid@ossec.net (ou daniel.cid@gmail.com). 
  - Système: Linux kmail 2.6.39 
  - Utilisateur: root 
  - Hôte: xxxxxx 
  -- Appuyez sur Entrée pour continuer ou Ctrl-C pour annuler. -- 

Après un appui sur entrée : 
 - Vous avez déjà installé ossec. voulez-vous le mettre à jour ? (o/n): o 
 - Voulez-vous mettre à jour les règles ? (o/n): o 
Après 2 "o"+entrée la compilation démarre et 
Starting OSSEC HIDS v2.6 (by Trend Micro Inc.)... 
OSSEC analysisd: Testing rules failed. Configuration error. Exiting. 
/var/ossec/bin/ossec-dbd: /usr/lib/libmysqlclient.so.15: version `libmysqlclient_15' not found 
(required by /var/ossec/bin/ossec-dbd) 
- Configuration correctement terminée. 
- Pour démarrer OSSEC HIDS: 
        /var/ossec/bin/ossec-control start 
- Pour arrêter OSSEC HIDS: 
        /var/ossec/bin/ossec-control stop 
- La configuration peut être visualisée ou modifiée dans /var/ossec/etc/ossec.conf 
    Merci d'utiliser OSSEC HIDS. 
    Si vous avez des questions, suggestions ou si vous trouvez 
    un bug, contactez nous sur contact@ossec.net ou en utilisant la 
    liste de diffusion publique sur ossec-list@ossec.net 
    ( http://www.ossec.net/en/mailing_lists.html ). 
    Plus d'information peut être trouver sur http://www.ossec.net&nbsp;
    ---  Appuyez sur Entrée pour finir (peut-ếtre plus d'info plus bas). ---

La tuile, OSSEC utilise une vieille version de la librairie Mysql Client, heureusement que j'ai aussi de vieilles machines qui possèdent encore cette librairie, je copie le tout dans /usr/lib : 
lrwxrwxrwx 1 root root      24 Aug  2 23:19 libmysqlclient.so.15 -> libmysqlclient.so.15.0.0 
-rw-r--r-- 1 root root 1993916 Feb 17  2009 libmysqlclient.so.15.0.0 
lrwxrwxrwx 1 root root      26 Aug  2 23:19 libmysqlclient_r.so.15 -> libmysqlclient_r.so.15.0.0 
-rw-r--r-- 1 root root 2002908 Feb 17  2009 libmysqlclient_r.so.15.0.0 

C'est pas très beau (horrible ?) de faire ce genre de chose dans un beau système Debian bien ordonné mais un petit tour dans le fichier "Contents...." ne me montre aucune librairie en version 15 accessible dans les magasins où je me sers habituellement. Aux grands maux les grands moyens. 
Un petit "service ossec start" et aucun message d'insulte, tout est OK. 
Les processes OSSEC ont l'air "ps -ef | grep ossec" d'être là. Un petit tour par l'interface graphique pour constater que le serveur a repris contact avec ses clients préférés et que tout semble baigner dans le plus parfait bonheur. 

Au fait j'ai gardé le tar des librairies dans un magnifique répertoire de sauvegarde de vieux trucs, ça pèse quand même # 4Mo.

OSSEC : version 2.7 et nouveau serveur

OSSEC : version 2.7 et nouveau serveur jpp

L'ancienne machine était très économique mais son processeur 32bits commençait à dater, par exemple les nouvelles versions de ZIMBRA ne se font plus qu'en 64bits. 
Il était donc nécessaire de passer sur une carte mère 64bits avec un Corei3 en version ECO TDP de 35W maxi dans le même boitier. Je passe l'installation (toujours Debian) pour en arriver à OSSEC en version 2.7. 
L'installation par elle même n'a pas changé, voir les chapitres précédents. 
Toutefois, pour changer un peu, je n'ai pas intégré OSSEC dans la base MYSQL de ZIMBRA mais j'ai utilisé une base PostgreSQL. 
La procédure est identique (on travaille dans les répertoires "sources" et non dans les répertoires d'installation du logiciel) :

cd mes_sources_OSSEC/src 
make setdb 
cd .. 
./install.sh

cd  répertoire_d_installation 
./bin/ossec-control enable database 

Il faut alors, comme pour MYSQL mettre en place (au début du fichier etc/ossec.conf le paramétrage de notre base PostgreSQL, par exemple en début de fichier :

<ossec_config> 
  <database_output> 
    <hostname>127.0.0.1</hostname> 
    <port>5432</port> 
    <username>mon_user_ossec</username> 
    <password>le_password_qui_tue</password> 
    <database>ma_base_ossec</database> 
    <type>postgresql</type> 
  </database_output> 
</ossec_config>

Il faut ensuite créer une base PostgreSQL avec le user qui va bien et initialiser cette base à l'aide du script dans le répertoire "répertoire_source/ossec-hids-2.7/src/os_dbd", on lance alors psql pour créer les tables: 
psql -U un_user_admin -W ma_base_ossec <postgresql.schema

On peut ensuite démarrer OSSEC et le tour est joué.

Mais tout ça c'était avant la découverte d'un nouvel interface Web pour OSSEC : ANALOGI. 
Cet interface est à première vue surprenant mais très efficacce, manque de pot il ne marche qu'avec MYSQL, donc exit PostgreSql et retour à Mysql. 
Vite un article sur ANALOGI malheureusement aujourd'hui défunt que j'ai du remplacer par un petit développement "perso".

OSSEC : 2.7 et interface Web ANALOGI

OSSEC : 2.7 et interface Web ANALOGI jpp

Note 2019 : La version décrite ici est ancienne et incompatible avec les version récentes (>2.9) de Ossec, il est possible d'utiliser la version décrite ici pour Ossec >= 3.0.

En installant la nouvelle version 2.7 j'ai cherché un interface Web un peu plus "sexy" que l'ancien interface d'OSSEC. En cherchant un peu je suis tombé sur "AnaLogi "et j'ai décidé de le tester, mais comme indiqué dans l'article précédent pas de PostgreSql avec AnaLogi. 
Note 2018, Analogi n"est plus compatible avec les versions de OSSEC >= 2.9.3,  voir ici. 
On le trouve à l'URL suivante : https://github.com/ECSC . 
L'installation est assez simple, on dézippe le machin dans un coin et on se débrouille pour que Apache soit capable de le trouver (si vous préférez Nginx cela ne devrait pas poser de problèmes). 
Ajouter dans "sites-available" le fichier "ANALOGI" contenant :

<VirtualHost 127.0.0.1:83> 
    ServerAdmin webmaster@localhost 
    ServerName  analogi.xxxx.xxx 
    Include /etc/apache2/sites-available/ANALOGI_body 
</VirtualHost> 
L'adresse en 127.0.0.1 est due à l'utilisation de "haproxy" pour aiguiller les requêtes, vous pouvez bien entendu mettre directement une adresse visible de l'extérieur.

Le fichier ANALOGI_body contient :

#       "Body" du site AnaLogi 
        DocumentRoot /opt/AnaLogi     
        <Directory /> 
                Options FollowSymLinks 
                AllowOverride None 
        </Directory> 
        <Directory /opt/AnaLogi> 
                Options Indexes FollowSymLinks MultiViews 
                AllowOverride None 
                Order allow,deny 
                allow from all 
        </Directory> 
        DirectoryIndex  index.php 
        ErrorLog /var/log/apache2/ANALOGI_error.log 
        # Possible values include: debug, info, notice, warn, error, crit, 
        # alert, emerg. 
        LogLevel warn 
        LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" personnel 
        CustomLog /var/log/apache2/ANALOGI_access.log personnel

Créer ensuite le lien adéquat de "sites-enabled" vers "sites-available" et relancer Apache.

La page d'accueil présente dès le lancement un récapitulatif des résultats : 
Page d'accueil ANALOGI 
En bas les principaux "problèmes" rencontrés, ces liens sont cliquables et mènet à une page détail. 
La recherche est donc très rapide. 
La zone "Filters" permet de :

  • Limiter la période,
  • Effectuer une statistique par source (machine)
  • Par chemin (répertoire d'origine des informations)
  • Par niveau.
  • Par règle.

La zone "Top Loc" donne la principale origine des messages. la zone "Rare" signale les événements un peu originaux qui peuvent être les plus intéressants. 
Les liens cliquables mènent sur une page détail qui présente une courbe en fonction du temps et le détail des alertes en partie basse. 
Page détail

L'exemple affiché ici concerne des tentatives de relais de mail avec toujours le même emmerdeur qui veut envoyer un mail à "therichsheickc@yahoo.com" , la plupart des serveurs ne sont pas en relais ouvert ce genre de "truc" est donc un peu inutile.

La période d'affichage est réglée par défaut à 72 heures ce qui est beaucoup pour moi, mais il est très facile de modifier cette valeur : 
Fichier = config.php 
Ligne à modifier : "$glb_hours=72;" 
Je l'ai mis à 12 heures ce qui me semble suffisant.

En bref je suis enchanté de cet interface qui simplifie grandement la vérification des anomalies interceptées par OSSEC, à utiliser et conseiller sans modération.

Analogi fonctionne encore en version 2.8.x de OSSEC.

OSSEC passage V2.9

OSSEC passage V2.9 jpp

J'ai voulu passer à la dernière version, la 2.9, mais cela m'a posé quelques problèmes car le schéma de la base  de données est différent. Il faut donc "laisser tomber" l'ancienne base et en créer une nouvelle et perdre l'historique à moins de se lancer dans une reprise de données (qui, par ailleurs, ne semble pas trop complexe). 
J'ai installé ensuite le serveur à partir du package Debian fourni par "Atomic corp" en version 2.9.3. 
Mon interface favori (ANALOGI) ne fonctionne plus (schéma de base différent) mais j'ai trouve une version améliorée d'ANALOGI (adaptée à la 2.8) téléchargeable : https://github.com/NunesGodinho/OSSEC-WUI et je suis en train d'en tirer une version adaptée au nouveau schéma de base de données en y ajoutant quelques fonctionnalités. 
Je vais la tester sur la future version 3.0 de OSSEC ( voir les résultats ici)  avant de la diffuser, car le schéma de base de données est identique à celui présent en version 2.9.3.

OSSEC : V3.0 stable

OSSEC : V3.0 stable jpp

Test complet de Ossec V3.0.0 stable. 
Cela va me permettre de tester la nouvelle version de l'interface OSSEC_GUI en version adaptée pour la 3.0.  
Cette version est issue de Analogi et de OSSEC_WUI. Cette nouvelle version reste compatible avec la 2.9.3 au niveau de la base de données.

Note juin 2018 : la version adaptée de l'interface web est disponible, voir ici.

OSSEC GUI V3.0

OSSEC GUI V3.0 jpp

J'avais beaucoup apprécié l'interface Analogi qui permettait de suivre assez agréablement les événements enregistrés par OSSEC, j'avais d'ailleurs écrit un article sur ce logiciel
Lorsque j'ai migré mes systèmes en 2.9 cet interface agréable ne fonctionnait plus du fait de la différence de structure de la base de données. 
J'ai cherché un produit équivalent plus récent (Analogi n'est plus maintenu depuis longtemps) et j'avais trouvé une version dérivée baptisée OSSEC WUI que l'on peut trouver sur github.

Malheureusement cette version utilise le schéma de base de données antérieur. J'ai donc décidé de repartir de cette version en l'adaptant au nouveau schéma de la base. J'ai ensuite vu paraître une nouvelle version d'Ossec (version V3.0) et je me suis dépêché de la tester pour bien vérifier si le schéma de la base avait évolué. J'ai vite constaté que ce schéma était resté identique (à celui de la version 2.9.3) et je me suis penché un peu plus sur OSSEC-WUI pour l'améliorer encore et y ajouter quelques fonctions statistiques, la possibilité de détruire des rangs spécifiques et séparer la réorganisation de la base de données de l'application "Management". 
J'ai aussi pensé à une fonctionnalité nouvelle, fonctionner selon deux modes :

  • Mode "running" directement à partir de la base alimentée par OSSEC, les événements une fois expliqués et/ou résolus peuvent être supprimés ce qui permet de n'avoir que peu d'alertes "actives". Rassurez vous ils ne sont pas perdus mais reportés dans une deuxième base de données.
  • Mode "history" qui fonctionne à partir de la base de sauvegarde avec exactement les mêmes fonctionnalités.

Voir quelques images d'écrans.

Afin de "sécuriser" les données, surtout les données archivées, j'ai ajouté une fonction d'authentification avec trois niveaux de responsabilité :

  1. Niveau lecture seule
  2. Niveau "delete autorisé" sur la base "running"
  3. Niveau "Admin" qui a tous les droits sur les deux modes, y compris pour la mise à jour des utilisateurs.


Note 2018/06/09 cette version baptisée "OSSEC-GUI-3.0" est disponible sur github en release V3.0.

Le projet contient toutes les doc d'installation des différentes possibilités :

  • Installation "simple"
  • Installation avec ou sans mode "historique"
  • Mise en place possible d'une l'authentification


J'espère que les docs sont OK, sinon il est facile de signaler les problèmes dans Github.

OSSEC ne reçoit plus

OSSEC ne reçoit plus jpp

Petit ennui : Les agents n'envoient plus rien au serveur. 
Depuis environ le 11 avril les données des clients ne sont plus reçues par la machine serveur. 
L'analyse des logs montre un message, un peu cryptique, après chaque redémarrage : 
getaddrinfo: Name or service not known 
Sans autre explication et aidé par quelques congés j'ai presque un mois pour trouver une solution ! 
En fait il m'aurait probablement suffi de porter mon attention sur la ligne suivante des logs : 
ossec-remoted(1206): ERROR: Unable to Bind port '1514' 
Qui m'aurait probablement ouvert les yeux ou au moins mis sur la piste. 
Je ne sais pas ce qu'il s'est passé aux environ du 11/04 mais "getaddrinfo" s'est mis à ne plus donner de résultat ??? alors que le DNS fonctionne parfaitement bien. 
La solution : mettre dans le fichier "/etc/hosts" une ligne avec l'adresse IP de communication avec les clients et le nom du serveur : "192.168.2.2 xxxxx xxxxx.yyy.zzz". 
C'est d'ailleurs ce que je fais en général, mais j'avais du l'oublier ici. 
Depuis OSSEC reçoit de nouveau les données des clients, la commande suivante permet de vérifier la "bonne" ouverture du port UDP/1514 : 
lsof -Pn | grep UDP | grep :1514 
ossec-rem  9692         ossecr    4u     IPv4     41151085      0t0        UDP *:1514 
ossec-rem  9692  9694   ossecr    4u     IPv4     41151085      0t0        UDP *:1514 
..... 
Comme quoi il vaut mieux bien lire les logs en cas de problème !!!

IPSET une nouvelle arme contre les méchants ?

IPSET une nouvelle arme contre les méchants ? jpp

Note 2024 : cela fonctionne toujours avec les kernels de serie 6.

Note 2020 : depuis tous ce temps, (début 2013) j'utilise un pare-feu à base d'IPSET car  les règles iptables utilisant des IPSET sont très performantes. Un set rempli d'adresses "douteuses" n'est pas une cause de latence, c'est d'autre part beaucoup plus facile à maintenir, enlever ou ajouter une adresse est quasiment instantané et cela évite surtout un empilage de règles difficiles à maintenir et qui finissent par être une cause importante de latence. Il est par exemple très facile et performant créer un "set" d'adresses (ou plages d'adresses) de pays ou de FAI (trop "permissifs") que l'on ne désire pas voir accéder à un système.

Dès qu'une machine est reliée à Internet elle subit de nombreuses tentatives d'entrée ou de test. Un bon Firewall permet de contrôler en partie ces tentatives mais les services offerts par chaque machine ne peuvent que moins facilement être protégés des « méchants ». Si par exemple vous avez un serveur de mails vous recevrez de nombreux essais d'envoi de mail bien que votre serveur ne soit pas configuré en mode « open ». Un serveur HTTP entraînera un tas de tests sur des bugs de beaucoup de logiciels. 
C' est énervant, cela remplit bêtement les logs d'enregistrements inutiles et alourdit leur lecture, toute cette brume de tentatives indiscrètes peut finir par cacher certains messages utiles.

Note 2017 : IPSET est en version 6.30 et tout fonctionne toujours correctement avec un noyau 4.13.7.

Le site « emerging threats » fournit des listes d'adresses IP, voire de réseaux entiers, qui hébergent ces vilains pollueurs de logs qui peuvent quand même planter des services ou même réussir à faire pire encore. Ces listes sont régulièrement mises à jour.

On peut récupérer (ou créer) de longues listes de règles « iptables » qui ralentissent évidemment le fonctionnement de votre firewall et fait d'un simple « iptables -vnL » une liste infinie.

Et alors IPSET est arrivé …. en fait la fonctionnalité existe depuis longtemps mais était assez difficile à maîtriser. Aujourd'hui avec les noyaux récents et la dernière version du protocole (version 6) cela semble très stable et parfaitement maîtrisable avec des performances qui semblent excellentes.

Un simple "apt-get install ipset" est OK, mais votre noyau doit être compilé avec les options adéquates :

make menuconfig

Networking support / Networking options / Network packet filtering framework / Ipset support.

Vérifier aussi la version de protocole de "ipset" :

ipset --version 
ipset v6.12.1, protocol version: 6 
 

Les versions de "ipset" et du noyau doivent être "en phase" pour fonctionner, ce qui peut parfois poser quelques problèmes de compatibilité.

IPSET 6.19 fonctionne avec tous les noyaux de 3.2 à 3.11, IPSET 6.12 avec ceux de 3.2 à 3.10. 

Je n'ai pas essayé de noyaux < 3.2.

Mes tests ont été réalisés avec des noyaux 3.9, 3.10 et 3.11-rc2 afin d'avoir les fonctionnalités les plus récentes. Le programme "ipset" 6.19) a été chargé depuis la version "unstable" de Debian afin de disposer là aussi des éléments les plus récents compatibles avec ces noyaux.

L'ensemble est simple à utiliser :

  • coté « iptables » une simple règle permet d'éliminer d'un seul coup toutes les adresses contenues dans un « set »
  • coté gestion des « sets » la commande « ipset » permet de gérer assez simplement les choses.

Cette commande possède un paramètre permettant de remplacer d'un seul coup un « set » par un autre et ce sans stopper le firewall ni supprimer la règle. La commande « swap » réalise cette opération instantanément sans interruption de la sécurité. Vous pouvez donc préparer tranquillement un nouveau « set » puis le « swapper » instantanément avec un set existant.

Il existe différentes catégories de « sets » selon que l'on veut traiter :

  • des adresses IP
  • des réseaux en notation CIDR
  • des adresses/port
  • ….

Le tout en deux modes principaux : HASH et BITMAP.

N'ayant ici que besoin de traiter des adresses et des réseaux je ne me suis intéressé qu'aux deux types « iphash » et « nethash » qui semblent adaptés à mon besoin et sont d'une très grande rapidité.

J'utilise en entrée trois listes d'adresses sources :

  • une petite liste personnelle en notation CIDR
  • un fichier de « emerging threats » nommé « compromised-ips.txt » contenant des adresses IP et des adresses en notation CIDR
  • un autre fichier « emerging threats » nomme « rbn-malvertisers-ips.txt »

Un traitement simple des listes d'adresses élimine les commentaires et les ligne vides puis sépare les adresses simples des adresses CIDR. Chaque groupe d'adresses est ensuite trié avec élimination des doubles (la présence de doubles provoque un arrêt d'urgence des chargements de sets) et remplit les deux sets adresses IP et adresses CIDR.

Les règles iptables se limitent à deux (en PREROUTING pour stopper le plus tôt possible les paquets vicieux) :

iptables -t raw -I PREROUTING -m set --match-set BLACK_IP src -j DROP

iptables -t raw -I PREROUTING -m set --match-set BLACK_NET src -j DROP

On peut aussi créer une chaîne perso ici "NOUVIN" sur laquelle on redirige les connections "nouvelles". Par exemple :

iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 
iptables -A INPUT -m state --state NEW -j NOUVIN 
On insérera les règles "SET" dans cette chaîne "NOUVIN" :

iptables I NOUVIN -m set --match-set BLACK_IP  src     -j DROP 
iptables I NOUVIN -m set --match-set BLACK_NET src     -j DROP

Après un rechargement des deux sets nommés chez moi « BLACK_IP » et « BLACK_NET » il suffit, après récupération des fichiers et traitement préparatoire de créer et remplir deux nouveaux sets de travail. Remarque la commande « ipset » peut aussi être installée dans /usr/sbin.

SET=W_BLACK_IP

/sbin/ipset --create $SET iphash --hashsize 50000

puis de remplir le set par une boucle sur la lecture de la liste préparée sur la commande

/sbin/ipset --add $SET $ADDR

SET=W_BLACK_NET

/sbin/ipset --create $SET nethash --hashsize 4096

suivre le même process en utilisant :

/sbin/ipset –add $SET $ADDR $MASK

Une fois nos deux sets « W » prêts il suffit de les « swapper » avec les sets permanents :

/sbin/ipset swap W_BLACK_IP BLACK_IP

/sbin/ipset swap W_BLACK_NET BLACK_NET

puis de détruire les sets « W » de travail :

/sbin/ipset --destroy W_BLACK_IP

/sbin/ipset --destroy W_BLACK_NET


Et le tour sera joué ... et les méchants joués.

Nftables : remplacant de Iptables

Nftables : remplacant de Iptables jpp

NOTE février 2022 : CE "LIVRE" EST TOUJOURS EN COURS DE REALISATION. 
Le noyau utilise Nftables mais, par manque de temps, j'utilise toujours l'interface iptables + ipset, pour le moment cela fonctionne encore très bien. 
En plus je n'ai pas encore bien compris la philosophie sous tendue par Nftables et j'ai du mal à concevoir un pare-feu à la fois simple, complet et facile à maintenir. 
Nouveauté Mai 2016 : utilisation notation CIDR et intervalles dans un "set nommé", voir l'article spécifique.

"NFTABLES" :

C'est le remplaçant prévu des commande IPTABLES et IPSET utilisées par tous les pare-feux sous Linux. 
Le développement ne semble pas hyper actif ni réactif et de nombreuses commandes ne sont pas encore, à mon goût, complètes, notamment au niveau des "sets" (remplaçants de Ipset) ou suffisamment souples. 
Tout est prêt au niveau du noyau Linux depuis déjà quelques versions (3.16 en principe) mais je pense que pour des tests (NFTABLES ne semble pas encore prêt pour mise en exploitation) il vaut mieux utiliser une version très récente du noyau. 
Ici j'utiliserai une 3.19-rc6, la dernière disponible au moment de ces tests. 
Il faut utiliser un noyau compilé avec tous les modules spécifiques à NFTABLES, malheureusement dans "make menuconfig" les différentes options sont un peu dispersées. Il faut aussi se rappeler que NFTABLES concernera IpV6 aussi bien que IpV4, donc configurer le tout.

Il faut avoir configuré dans le noyau (>= 3.16, ici 3.19) les extensions pour "nftables": 
   <M> Netfilter nf_tables support 
   <M>   Netfilter nf_tables mixed IPv4/IPv6 tables support 
   <M>   Netfilter nf_tables IPv6 exthdr module 
   <M>   Netfilter nf_tables meta module 
   <M>   Netfilter nf_tables conntrack module 
   <M>   Netfilter nf_tables rbtree set module 
   <M>   Netfilter nf_tables hash set module 
   <M>   Netfilter nf_tables counter module 
   <M>   Netfilter nf_tables log module 
   <M>   Netfilter nf_tables limit module 
   <M>   Netfilter nf_tables masquerade support 
   <M>   Netfilter nf_tables redirect support 
   <M>   Netfilter nf_tables nat module 
   <M>   Netfilter nf_tables queue module 
   <M>   Netfilter nf_tables reject support 
Ajouter Ethernet bridge nf_tables support 
--- Ethernet Bridge nf_tables support    
  <M>   Netfilter nf_table bridge meta support 
  <M>   Netfilter nf_tables bridge reject support

Il est conseillé de charger tous les modules nécessaires au démarrage en constituant une liste des modules dans un fichier dédié (ici nftables.conf) dans /etc/modules-load.d pour une Debian "Testing" ou dans le fichier /etc/modules pour une Debian "stable". 
Les modules se situent dans /lib/modules/$(uname -r)/kernel/net/netfilter et commencent presque tous par "nft"  sauf les deux plus importants "nf_tables_inet" et "nf_tables". 
Liste des modules chargés : 
nf_tables 
nf_tables_inet 
nft_chain_nat_ipv6 
nft_chain_nat_ipv4 
nft_chain_route_ipv6 
nft_chain_route_ipv4 
nft_counter 
nft_ct 
nft_exthdr 
nft_hash 
nft_limit 
nft_log 
nft_masq 
nft_meta 
nft_nat 
nft_queue 
nft_rbtree 
nft_redir 
nft_reject_inet 
nft_reject 
nft_reject_ipv4 
nft_reject_ipv6 
On sera ainsi parés pour toutes les éventualités.  
 

Quelques références : 
http://wiki.gentoo.org/wiki/Nftables 
http://wiki.nftables.org/wiki-nftables/index.php/Main_Page 
 

NFTABLES : un peu de vocabulaire

NFTABLES : un peu de vocabulaire jpp

Aucune "table" n'est définie par défaut comme avec "iptables", c'est à vous de les définir ! 
Rappel
Plus de différence entre IPV4 et IPV6, tout peut être traité dans le même flot, si on utilise des tables "inet", par défaut c'est "ip" (IPV4) qui est choisi, on peut aussi utiliser "ip6" pour du spécifique IPV6. 

Commandes disponibles : 
list 
  ruleset 
  tables [famille] 
  table [famille] <nom> 
  chain [famille] <table> <nom> 
add 
  table [famille] <nom> 
  chaine [famille] <table> <nom> [paramètres de la chaîne] 
  rule [famille] <table> <chaine> <paramètres de la règle> 
  element [famille] <table> <set> { 1..n elements } 
table [famille] <nom> (raccourci pour "add table`) 
insert 
  rule [famille] <table> <chaine> <paramètres de la règle> 
delete 
  table [famille] <nom> 
  chain [famille] <table> <nom> 
  rule [famille] <table> <numero handle> 
  set [famille] <table> <set>     : il ne doit plus être référencé 
  element [famille] <table> <set> { 1..N elements a enlever } 
flush 
  table [famille] <nom> 
  chain [famille] <table> <nom> 

Remarques : 
La famille "ip" (ipv4) est prise par défaut. 
Attention à la syntaxe de "list" "list tables" et "list table ENTREE". 
Liste des familles de "tables" et l'outil iptables correspondant 
ip            iptables 
ip6          ip6tables 
inet         iptables and ip6tables 
arp          arptables 
bridge     ebtables 
Liste des "hooks" existants, tiens tiens ! Les noms me rappellent quelque chose : 
INPUT                    paquet entrant dans le système local 
OUTPUT                paquet sortant du système local 
FORWARD            paquet traversant 
PREROUTING      paquet entrant 
POSTROUTING    paquet sortant 
Liste des "types" de tables existants, là aussi les noms semblent familiers : 
filter        Valeur par défaut 
nat 
route      (mangle), ne semble utilisable qu'avec le hook "output". 
Ordres supportés par la commande "table" 
add 
delete 
list 
flush 
Ordres supportés par la commande "chain" : 
add 
create 
delete 
list 
flush 
rename 
Ordres supportés par la commande "rule" : 
add     ajoute une règle en fin de chaîne 
insert    ajoute une règle en début de chaîne 
delete    détruit une règle, utilisé avec un "handle" cf "nft -a list ...."

Ordres supportés par la commande "ruleset" : 
flush   efface tout 
list       liste tout

Destination des paquets 
accept 
reject 
drop 
snat 
dnat 
log 
counter 
return 
jump    <chaine> 
goto     <chaine> 

Quelques "mots clefs" pour les règles : 
oif                interface sortie suivi d'un numéro 
iif                 interface entree suivi d'un numéro 
oifname    nom de l'interface de sortie 
iifname     nom de l'interface d'entree 
type           suivi d'un type ICMP par exemple "echo-request" 
protocol   tcp, udp ... 
daddr        adresse destination 
saddr        adresse source 
dport        port de destination 
sport        port source 
ct               connexion tracking + state ( NEW, ESTABLISHED, RELATED, INVALID) 
C'est un bon début.

NFTABLES : premier test Debian testing

NFTABLES : premier test Debian testing jpp

Pour ce premier essai j'ai utilisé les paquets disponibles à ce jour sur "Debian testing" : 
libjansson4_2.7-1_amd64.deb 
libmxml1_2.6-2_amd64.deb 
libnftnl0_1.0.3-4_amd64.deb 
nftables_0.4-2_amd64.deb 
Une fois tout ce petit monde en place on peut commencer à tenter de se servir de ce nouvel outil remplaçant désigné de "iptables". 
Références : 
Accéder à "http://people.netfilter.org/wiki-nftables/index.php/Main_Page" pour tous les détails sur nftables. 
Un autre Wiki bien fait est celui d'Archlinux accessible à "https://wiki.archlinux.org/index.php/Nftables".

Premier essai : 
"nft list tables" ou "nft list tables ip6" ne donnent aucune sortie puisque avec Nftables rien n'est créé par défaut ! 
Par contre dès qu'une chaine existe une sortie est fournie : 
nft add table entree     
nft list tables 
--> 
table entree 
L'ensemble a donc l'air parfaitement fonctionnel. On va pouvoir passer à des choses plus sérieuses.

NFTABLES : quelques tests

NFTABLES : quelques tests jpp

Points importants :

  • Nftables est prévu pour fonctionner avec l'option "-f" avec laquelle les données sont contenues dans un fichier. Ce fichier peut être généré par la commande "list" et utilisé ensuite en entrée de la commande "nftables -f ".
  • A l'origine, rien n'est créé, les différentes tables et chaines existant par défaut avec "iptables" n'existent pas ici par défaut. Il faut donc créer toutes les "tables" et y attacher toutes les "chaines" nécessaires.

Quelques exemples : 
 

  • Création d'une table "ENTREE" (Ipv4 par défaut le parametre "ip" étant omis) :

nft add table ENTREE 

Liste des tables : 
nft list tables 
--> table ENTREE

  • Ajout d'une table "SORTIE"

nft add table SORTIE 
nft list tables 
--> 
table ENTREE 
table SORTIE

  • Destruction de la table "SORTIE" :

nft delete table SORTIE 

nft list tables 
--> 
table ENTREE 

Ajout d'une chaine nommée "INTERNE" dans la table ENTREE (type filter et Ipv4 par défaut) : 
nft add chain ENTREE INTERNE 

Destruction de la chaine "INTERNE" de la table ENTREE 
nft delete chain ENTREE INTERNE 

Addition d'une règle dans notre table ENTREE (à la fin) : 
nft add table ENTREE 
nft add chain ENTREE INTERNE 
nft add rule ENTREE INTERNE ip saddr 127.0.0.1 accept 
nft list table ENTREE 
--> 
table ip ENTREE { 
    chain INTERNE { 
         ip saddr 127.0.0.1 accept 
    } 
}

Remarque : On aurait pu ici utiliser aussi "nft list ruleset" pour lister l'ensemble des tables.

  • On accepte le port 22

nft add rule ENTREE INTERNE tcp dport 22 accept 
nft list table ENTREE 
--> 
table ip ENTREE { 
    chain INTERNE { 
         ip saddr 127.0.0.1 accept 
         tcp dport ssh accept 
    } 
}

  • Insérer une règle en début de chaîne

nft insert rule ENTREE INTERNE ct state established, related accept 
On fait une liste avec les numeros de "handle" (option "-a") : 
nft -a list table ENTREE 
--> 
table ip ENTREE { 
    chain INTERNE { 
         ct state established,related accept # handle 5 
         ip saddr 127.0.0.1 accept # handle 2 
         tcp dport ssh accept # handle 4 
    } 
}

  • On ne peut détruire une règle que par son numéro (handle), Ici on détruit la règle 4

nft delete rule ENTREE INTERNE handle 4 
nft -a list table ENTREE 
--> 
table ip ENTREE { 
    chain INTERNE { 
         ct state established,related accept # handle 5 
         ip saddr 127.0.0.1 accept # handle 2 
    } 
}

  • On sauvegarde notre table :

nft list table ENTREE >SAUVE

  • On efface tout

nft delete table ENTREE 
nft list tables 
--> ne retourne rien

  • On restaure notre jeu de test

nft -f sauve 
nft list table ENTREE 
--> 
table ip ENTREE { 
    chain INTERNE { 
         ct state established,related accept 
         ip saddr 127.0.0.1 accept 
    } 

On retrouve notre table telle qu'avant destruction, la sauvegarde d'un jeu de règles et sa restauration sont d'une belle simplicité.

  • On rajoute une autorisation pour SSH et on logue la connexion :

nft add rule ENTREE INTERNE tcp dport ssh log prefix \"MSG=Connect SSH \" 
nft -a list ruleset 
--> 
table ip ENTREE { 
    chain INTERNE { 
         ct state established,related accept # handle 2 
         ip saddr 127.0.0.1 accept # handle 3 
         tcp dport ssh log prefix "Connect SSH" # handle 4 
    } 
}

NFTABLES : on passe par la case COMPIL

NFTABLES : on passe par la case COMPIL durp11_admin

Les tests de "map" et autres joyeusetés n'ayant pas fonctionné avec les versions "standard" des ^packages, il faut passer par la case "compil" et récupérer les morceaux dans un petit répertoire bien tranquille (pour moi "/usr/src/PGM/BUILD/NFT"): 
git clone git://git.netfilter.org/nftables.git 
git clone git://git.netfilter.org/libmnl.git 
git clone git://git.netfilter.org/libnftnl.git 

Pré-requis : 
bison 
flex 
libgmp-dev 
libreadline-dev 
libmnl0 
libmnl-dev 
Remarque : il peut y avoir d'autres pré-requis, la machine ayant servi à la compil est une Debian "stable" avec "backports" qui a déjà beaucoup vécu et comporte déjà pas mal de packages "-dev".

Compilation de "LIBMNL" le script :

#!/bin/bash

cd NFT/libmnl ...... le répertoire source 
zzz=$(pwd) 
yyy=$(basename $zzz) 
case $yyy in 
    libmnl)        echo 'OK' 
            ;; 
    *)        echo 'pas dans libmnl' 
            exit 
            ;; 
esac

make clean

./autogen.sh

# configure libmnl 
CONFOPT=" --prefix=/usr/local/libmnl --exec-prefix=/usr/local/libmnl "

./configure ${CONFOPT} 2>&1 | tee LOG.CONF

make 2>&1 | tee LOG.MAKE

Ne pas oublier ensuite (en "root") le "make install". 

Compilation de "LIBNFTNL" le script :

#!/bin/bash

cd NFT/libnftnl 
zzz=$(pwd) 
yyy=$(basename $zzz) 
case $yyy in 
    libnftnl)        echo 'OK' 
            ;; 
    *)        echo 'pas dans libnftnl' 
            exit 
            ;; 
esac

make clean

./autogen.sh

# configure libnftnl 
CONFOPT=" --prefix=/usr/local/libnftnl --exec-prefix=/usr/local/libnftnl " 
CONFOPT=${CONFOPT}' LIBMNL_LIBS=/usr/local/libmnl ' 
CONFOPT=${CONFOPT}' LIBMNL_CFLAGS=/usr/local/libmnl'

./configure ${CONFOPT} 2>&1 | tee LOG.CONF

make 2>&1 | tee LOG.MAKE

Ne pas oublier (toujours) le "make install" en "root". 

Une fois tout vérifié j'ai copié : 
/usr/local/libmnl/lib/libmnl.* dans  /lib/x86_64-linux-gnu 
/usr/local/libnftnl/lib/libnftm* dans /lib/x86_64-linux-gnu 

et vérifié que la version Debian de "nft" fonctionnait toujours --> OK 

Compilation de "NFTABLES" le script :

#!/bin/bash

PKG_CONFIG_PATH=${PKG_CONFIG_PATH}':/usr/local/libnftnl/lib/pkgconfig' 
PKG_CONFIG_PATH=${PKG_CONFIG_PATH}':/usr/local/libmnl/lib/pkgconfig' 
export PKG_CONFIG_PATH

cd /usr/src/PGM/BUILD/NFT/nftables 
zzz=$(pwd) 
yyy=$(basename ${zzz}) 
case ${yyy} in 
    nftables)    echo 'OK' 
            ;; 
    *)        echo 'pas dans nftables' 
            exit 
            ;; 
esac

make clean

./autogen.sh

# configure nftables

CONFOPT=' --prefix=/usr/local/nftables --exec-prefix=/usr/local/nftables/bin ' 
CONFOPT=${CONFOPT}' --includedir=/usr/include ' 
CONFOPT=${CONFOPT}' LIBMNL_LIBS=/usr/local/libmnl/lib/libmnl.so  ' 
CONFOPT=${CONFOPT}' LIBNFTNL_LIBS=/usr/local/libnftnl/lib/libnftnl.so  '

./configure ${CONFOPT} 2>&1 | tee LOG.CONFIGURE

make 2>&1 | tee LOG.MAKE

echo 'PKG_CONFIG_PATH=('${PKG_CONFIG_PATH}')'

echo '' >./doc/nft.8

Ne pas oublier (encore) le "make install", puis on expédie "/usr/local/nftables/bin/sbin/nft" dans "/usr/sbin".

On pourra ainsi reprendre nos essais ... avec la dernière version, plus complète.

NFTABLES : version compilée tests

NFTABLES : version compilée tests jpp

Cette petite série de tests a été conduite avec la version compilée localement de "nft" car les autres versions essayées (paquets standard) ne "comprenaient" pas certaines nouvelles fonctionnalités.

Premier test : réaliser du NAT : 
Si la table existe un petit "flush" remet tout dans l'ordre, si la table n'existe pas cela déclenche une erreur fatale et rien n'est fait ! C'est très dommage pour l'atomicité des opérations. 
Pour être tranquilles il faut donc tester l'existence de la table et la créer (vide) si besoin. Cela peut se faire avec le petit bout de script suivant :


# On teste l'existence de la table !  

nft list table ip POSTROUTE 2>/dev/null >/dev/null 
ret=$? 

# On crée la table si elle n'existe pas !!! 

if [ $ret -ne 0 ] 
    then 
       nft add table ip POSTROUTE 
fi 
On peut maintenant lancer la suite du script avec : 
nft -f 
Mon fichier contient dans notre cas : 
flush table ip POSTROUTE;  
table ip POSTROUTE { chain DEFAUT { 
type nat hook postrouting priority 0; 
ip saddr 192.168.2.0/24 masquerade; 
ip saddr 192.168.3.0/24 masquerade; } }


On peut noter la création d'une table avec un nom "en français" pour faire plus beau !

Deuxième test, effectuer une redirection transparente de HTTP/HTTPS : 
Tous les "clients" HTTP à destination de l'extérieur sont "interceptés". Seules les adresses précisées subissent une redirection du HTTPS, le "set" GO_HTTPS contiendra les adresses sélectionnées. 
On ajoute des compteurs pour suivre le travail. 

flush table ip PREROUTE; 
table ip PREROUTE { chain DEFAUT { type nat hook prerouting priority 0; 
     ip daddr != 192.168.2.1/24 tcp dport 80 counter redirect to 3127 
     ip daddr != 192.168.2.1/24 
     ip saddr @GO_HTTPS tcp dport https counter redirect to 3129 
     } 
set GO_HTTPS { type ipv4_addr; }; 
}

Ensuite on ajoute les adresses au set :

nft add element PREROUTE GO_HTTPS { 192.168.2.9 } 
nft add element PREROUTE GO_HTTPS { 192.168.2.10 , 192.168.2.8} 
et on vérifie : 
nft list set PREROUTE GO_HTTPS 
set GO_HTTPS { type ipv4_addr elements = { 192.168.2.9, 192.168.2.8, 192.168.2.10} }

Troisième test : envoyer des paquets vers une "queue" en espace utilisateur par exemple pour un IPS
Ici l'IPS est Suricata, on mettra un compteur sur chaque règle. 
On utilise la "famille" inet pour intercepter aussi IPV6 et une priorité de -100 pour passer avant les autres chaines. On ne peut pas utiliser le type "route" qui ne fonctionne pas avec un autre "hook" que "output".

delete table inet IPS; 
table inet IPS       { 
    chain ENT_150    { type filter hook input         priority -100; 
            counter queue num 0 
            } 
     
    chain SOR_150    { type filter hook output        priority -190; 
            counter queue num 0 
            } 

    chain FOR_150   { type filter hook forward    priority -100; 
            counter queue num 1-2; 
            } 
}

Après quelques accès internet la commande " nft list table inet IPS " renvoie :

table inet IPS { 
    chain ENT_150 { 
         type filter hook input priority -100; 
         counter packets 1676 bytes 490186 queue num 0 
    } 

    chain SOR_150 { 
         type filter hook output priority -190; 
         counter packets 1969 bytes 398894 queue num 0 
    } 

    chain FOR_150 { 
         type filter hook forward priority -100; 
         counter packets 0 bytes 0 queue num 1-2 
    } 
}


Des paquets "locaux" sont bien passés dans la queue 0 et l'un d'entre eux a été "repéré" par Suricata car il contenait un mot de passe de connexion sur un site WEB.

A suivre ....

NFTABLES : sets, maps et dictionnaires

NFTABLES : sets, maps et dictionnaires jpp

NFTABLES :  

Nftables dispose d'un arsenal de modèles permettant de simplifier la réalisation des tests en utilisant des notions analogues à celles des "Ipsets" mais présentant quelques perfectionnements intéressants. 
Il existe plusieurs types de tables dans deux saveurs :

  • Gadgets "nommés", décrits "à part" et utilisés par une règle.
  • Gadgets "inline" non nommés qui peuvent faire partie d'une règle.

Les gadgets nommés permettent de réaliser des ajouts/suppressions "en ligne" gràce aux opérations sur les éléments (de manière analogue à "ipset").

Un certain nombre de "types" de données sont admis pour les éléments :

  • ipv4_addr/ipv6_addr      Adresses IPV4 ou IPV6, avec option "flags interval" pour notation CIDR ou intervalles, nécessite noyau >= 4.7-rc2 et dernière version nftables (à charger et compiler).
  • ether_addr                        Adresse MAC
  • inet_service                      Ports, sous forme numérique ou texte pour les plus connus (ssh, http, https ...)
  • inet_proto                         Prototype : ICMP, TCP ....
  • mark                                   Marque posée par une autre règle.

Ces différents types répondent à la plupart des besoins, il manquerait toutefois la possibilité de désigner un réseau sous forme CIDR en plus des adresses IP. Cette possibilité existe dans les "vmap" non nommées, mais pas pour cellles nommées ? Un oubli sans doute ? 
Juin 2016 : 
Cet oubli est corrigé dans la dernière version de Nftables et nécessite un kernel >= 4.7-rc2, la syntaxe de la création du set est légèrement différente, il faut ajouter "flags interval" dans la déclaration du set nommé qui devient : 
set MONSET ( type ipv4-addr; flags interval)

Une autre nouveauté intéressante de ces "gadgets" est donnée par le deuxième élément possible : l'action à réaliser si l'élément "matche", drop, jump table, goto table, accept ..... Cela ouvre des horizons assez sympatiques. 
Par exemple on peut en une seule règle refouler toutes les IP d'un pays à l'aide des listes fournies par différents sites par exemple "ipdeny.com". On peut récupérer la liste des réseaux concernés, mettre en forme la règle (un simple script AWK le fait très bien, générer un fichier au "bon" format et utiliser ce fichier dans un script "Nftables" à l'aide de l'instruction "include" (je vous avais bien dit que la syntaxe Nftables se rapprochait d'un langage !). Dommage d'être obligé d'utiliser un bloc de données non nommé car si on en a besoin plusieurs fois .... par exemple en Entrée et en Forward ou en sortie. 
Exemple de syntaxe pour la règle ci dessus :

add rule INPUT ENT_100 ip saddr vmap { 
1.0.1.0/24 : drop, 
1.0.2.0/23 : drop, 
1.0.8.0/21 : drop, 
........ 
254.254.0.0/24 : drop }

Qui ajoute une règle à la chaine "ENT_100" de la table "INPUT".

Ce fichier est appelé par  l'include suivant dans le script Nftables de création de la table "INPUT" : 
#include "le_chemin_de_mon_fichier" 
Autre petit exemple, répartir sur plusieurs "chaînes" les entrées en fonction de l'interface d'origine pour les compter, on utilisera une "vmap" :

flush table ip ENTREE;

table ip ENTREE { 
    chain INP_INT { 
         counter 
    } 
    chain INP_EXT { 
        counter 
    } 
    chain INP_LOC { 
        counter 
    } 
    chain DEFAUT { 
         type filter hook input priority 0; 
         iifname vmap { br0 : jump INP_EXT, br1 : jump INP_INT, 
                        lo  : jump INP_LOC  } ; 
    } 
}

Après quelques instants on liste :

nft list table ENTREE 
table ip ENTREE { 
    chain INP_INT { 
         counter packets 53 bytes 8010 
    } 
    chain INP_EXT { 
         counter packets 2 bytes 64 
    } 
   chain INP_LOC { 
         counter packets 12 bytes 774 
    }    chain DEFAUT { 
         type filter hook input priority 0; 
         iifname vmap { "lo" : jump INP_LOC, "br1" : jump INP_INT, "br0" : jump INP_EXT} 
    } 
}

C'est bien ce qui était demandé...

Attention en manipulant les sets il existe quelques problèmes lors de la mise à jour d'une table contenant des sets, il est impossible de "flusher" une table tant qu'il y a un set, il faut détruire le set d'abord avant de faire le flush de la table sinon on arrive à un crash système. 
Ce problème est résolu pour les noyaux >= 4.0.0-rc4. 
 

NFTABLES : sets nommés et notation CIDR

NFTABLES : sets nommés et notation CIDR jpp

Juin 2016 : depuis la version 0.5 de Nftables, la dernière que j'ai chargée et testée, on peut créer des sets nommés en utilisant les intervalles et/ou une notation CIDR. Il faut, en plus de cette version récente, disposer d'un kernel >= 4.7-rc2 avec toutes les options "NFT_...." activées en modules. 
Exemple de création d'une table avec deux sets nommés, un en IPV4, l'autre en IPV6 :

table ip TEST      { 
   chain ENT_100    { type filter hook input    priority -100 ; 
            counter; 
            }

    set DISPAT     { type ipv4_addr; flags interval; };  # bien noter les deux ";"

    chain BIDON    { type filter hook input    priority 0; 
            counter; 
            }

    set EXAMPLE    { type ipv6_addr; }; 
}

On peut ensuite ajouter des éléments aux sets, par exemple :

add element TEST  DISPAT    { 192.168.2.2,192.168.2.4 }; 
add element TEST  DISPAT    { 192.168.3.0/24 }; 
add element TEST  DISPAT    { 192.168.0.0/24, 192.168.1.0/24 }; 
add element TEST  DISPAT    { 192.168.4.10 - 192.168.4.127 }; 
La commande de liste du set donne le résultat suivant : 
nft list set TEST DISPAT 
table ip TEST { 
    set DISPAT { 
        type ipv4_addr 
        flags interval 
        elements = { 192.168.0.0/23, 192.168.2.1, 192.168.2.2, 192.168.2.4, 192.168.3.0/24, 192.168.4.10-192.168.4.127} 
    } 
}

On peut remarquer la "fusion" réalisée auto-magiquement de "192.168.0.0/24, 192.168.1.0/24". 
IPV6 n'étant pas activé chez moi (ni chez mon FAI) je n'ai pas fait de tests sur les sets IPV6.

NtopNG et scripts pour sécurité

NtopNG et scripts pour sécurité jpp

Logo NTOP
NtopNG intercepte et stocke des tas de données sur tous les événements réseau traités, l'exploitation de ces données permet, outre quelques statistiques, de repérer des événements liés à la sécurité.

Premier exemple : 
Exploiter les alertes NtopNG, repérer les accès sur des ports non actifs (fermés ou filtrés). 
Une version plus récente est disponible ici.

Deuxième exemple : 
Repérer les scans de ports, même lents.

Exploiter les alertes NtopNG

Exploiter les alertes NtopNG jpp

Note : cette description "date" un peu et une version plus récente est disponible ici.

Exploiter les alertes générées par NtopNG. 
Les dernières versions de NtopNG permettent d'activer un suivi d'alertes. Ces alertes sont levées pour différentes raisons :

  • Accès depuis une adresse "blacklistée" par utilisation d'une liste du site Emergingthreats.
  • Tentative d'accès à un port fermé ou bloqué
  • Autres anomalies de comportement

Or ces alertes sont stockées dans une base de données Sqlite (ou Mysql/MariaDB dans les versions suivantes) et donc très faciles à exploiter. 
Les tables comportent le même type de renseignements que celles enregistrant les flux dans une base de données plus traditionnelle. 
Les principales données sont :

  • Données temporelles    . timestamp, firstswitched, lastswitched
  • Données sur le client.    . cli_addr, cli_country (code pays), cli_port
  • Données coté serveur.    . srv_addr, srv_country, srv_port
  • Données quantitatives.    . cli2srv_bytes, srv2cli_bytes, cli2srv_packets, srv2cli_packets
  • Données "techniques".    . flags IP, blacklist ou pas, .....

La conservation de ces données est ajustable dans le logiciel selon différents critères dans le paramétrage de NtopNG. 
Il vaut mieux limiter un peu le volume car Sqlite n'est pas adapté aux gros volumes. 
On peut repérer à partir de ces données tout "hit" sur un port fermé et, par exemple, bloquer cette adresse avec un "ipset" bien placé dans un règle de pare-feu. 
Le petit script suivant permet de repérer ces adresses IP :

select min(first_switched),cli_addr 
from flows_alerts 
where cli_addr not like '192.168.1%' 
  and cli_addr not like '192.168.2%' 
  and cli_addr not like '192.168.3%' 
  and cli_addr not like '%:%'            -- éliminer IPV6 
  and cli_addr not like '0.0.0.0' 
  and srv_port < 32768 
  and first_switched > ${DATEMIN} 
group by cli_addr 
order by first_switched;

Il faut éliminer : 
- les enregistrements "anciens", la date minimum est au format "epoch", j'utilise les deux dernières heures : 
    DATEMIN=$(date +%s) 
    DATEMIN=$(expr ${DATEMIN} - 7200) 
- les origines dans son propre réseau : 
- ceux qui utilisent des ports "client d'un service local", ici seuls les ports inférieurs à 32768 sont pris en compte. Voir ces limites avec la commande "sysctl -a | grep local_port_range" . 
Il est parfois un peu délicat de repérer les bases Sqlite car les noms de répertoires sont différents selon les machines. Pour moi le répertoire principal est /var/tmp/ntopng et les bases sont dans 
13/alerts/alerts_v7.db et 15/alerts/alerts_v7.db sur une machine, sur une autre machine les répertoires sont 1 et 3 donc très différents. 
Ce script est très rapide car la base Sqlite contient assez peu de rangs (moins de 5000) et peut être lancé par "cron" avec une fréquence importante pour alimenter régulièrement un "set" de blocage par IP.

Exploiter les alertes NtopNG (V2)

Exploiter les alertes NtopNG (V2) jpp

Note 2024 : cette méthode fonctionne toujours mais il est possible de stocker les données dans une base Mysql/MariaDB qui permet de conserver beaucoup plus de données et d'obtenir le même genre de résultats et c'est ce que j'utilise maintenant avec possibilité de détecter des scans sur une période plus longue (plusieurs jours). Les dernières versions permettent d'utiliser une base "ClickHouse" voir ses caractéristiques ici.

NtopNG pour détecter les scans (V2).

Depuis plusieurs versions NtopNG utilise une petite base de données Sqlite pour stocker des données prises « au vol ». Au fil des versions le nombre de données, et de tables, a fortement augmenté. Certaines de ces données permettent de repérer les accès qui n’ont donné lieu à aucun transfert vers le « client » car ils tentaient un accès à un port fermé ou bloqué par le pare-feu. D'autres éléments indiquent des accès depuis des adresses "blacklistées".

A partir de ces données il est très facile, et rapide de repérer les scans de ports, même l’accès à un seul port est repérable. La base étant très légère (à la journée) les traitements sont très rapides et peuvent donc être exécutés souvent.

D’abord une mini description de la structure de ces bases de données situées dans /var/lib/ntopng dans une installation « « standard ».

L’organisation générale comporte 3 répertoires nommés : « -1 » « 0 » et « 1 ». chacun de ces répertoires contient plusieurs répertoires et nous nous intéresserons ici qu’à « alert ». 
Chacun de ces répertoires contient un fichier, ici « alert_store_v11.db » dont le nom varie, malheureusement, à chaque version. Les noms des colonnes ont aussi varié au cours des versions … 
En ouvrant ce répertoire dans SqliteBrowser on peu y voir la liste des tables et index.

Remarque : Il est normal que certains des 3 répertoires contiennent des tables vides … toute recherche doit donc concerner les trois répertoires. 
La table qui nous intéresse ici est « flow_alerts » dont les colonnes suivantes nous intéressent :

  • cli_ip et cli_port adresse et port de l’émetteur
  • srv_ip et srv_port adresse et port du destinataire

On y trouve d’autres colonnes intéressantes :

  • cli_name et srv_name les noms DNS
  • cli_country et srv_country les codes pays
  • cli_blacklisted et srv_blacklisted des indicateurs de qualité des adresses (0 ou 1) indiquant l’appartenance à une liste noire de l’adresse correspondante. Les listes noires sont maintenues à jour automatiquement et sont paramétrables dans l’interface Web de NtopNG, y compris leur fréquence de mise à jour?

Enfin les compteurs de la transmission en octets et paquets :

  • cli2srv_bytes / cli2srv_pkts et srv2cli_bytes / srv2cli_pkts ce sont principalement ces compteurs qui nous intéressent car une valeur à zéro implique le refus de transmission qui marque un port fermé ou bloqué par une règle de firewall.

Certaines colonnes telles is_cli_attacker , is_srv_attacker ou is_srv_attacker , is_srv_victim précisent les choses par leur valeur 0 je fais partie des gentils, 1 je suis un méchant !

Il est donc très facile de lister par des ordres SQL simples les adresses IP dont les accès n’ont donné lieu à aucun transfert en retour. 
Ensuite les adresses IP sont comparées aux « set » de "méchants" existants, si elles sont trouvées on abandonne car elles sont déjà bloquées, si elles ne sont pas trouvées elles sont stockées dans un set spécial d’attente, mais tout accès depuis une adresse présente dans ce set sera « dropé » par une règle iptables comme pour les adresses contenues dans les sets "permanents" de méchants.

Ce set est exploré toutes les heures et toute adresse présente depuis plus d’une heure est transférée dans un set permanent sauvegardé et détruite du set d’attente. 
Le transfert dans un set permanent entraîne par ailleurs l’analyse des accès liés à cette adresse sur les dernières 24 heures et l’envoi d’un message au site ABUSEIPDB.COM avec la liste des ports touchés pour faire profiter les autres de la découverte d’un vilain méchant et horrible qui scanne internet, probablement pour un but pas très honnête ...

Toutes ces opérations sont assez simples à réunir et quelques scripts, un peu de bash, de SQL et de mise en forme avec awk font l’affaire. 
Voir ci-dessous l'ordre SQL qui "va bien".

select min(first_seen),cli_ip from flow_alerts 
where cli_ip not like '192.168.1%'   and cli_ip not like '192.168.2%' 
  and cli_ip not like '192.168.3%'   and cli_ip not like '192.168.4%' 
  and cli_ip not like '%:%'          and cli_ip not like '0.0.0.0' 
  and srv_port < 32768 
  and tstamp > ${DATEMIN} 
  and srv_port not in (80,443) 
  and cli_port not in (liste de ports) 
group by cli_ip 
order by tstamp; 
.quit

DATEMIN est obtenu depuis le script bash : 
DATEMIN=$(date +%s) 
DATEMIN=$((${DATEMIN} - 3600 ))  # ou 7200 pour étendre ) 2 heures

Repérer les scans lents

Repérer les scans lents jpp

Repérer les scans "lents" avec NtopNG. 
SI vous stockez les données de flux dans une base Mysql/MariaDB avec une certaine durée il est possible de repérer les scans de ports, même lents, de manière simple à l'aide d'un ordre SQL basique. 
Cela permet de repérer les adresses IP qui scannent très lentement pour éviter d'être repérées trop facilement, et de les bloquer avec un "ipset" bien placé dans votre pare-feu. Attention les adresses IP sont stockées dans le format interne de Mysql et il faut utiliser les fonctions "inet_aton" et "inet_ntoa" pour les interpréter.
Ici on sélectionne les IP qui ont "atteint" plus de 10 ports (sans données retournees : OUT_BYTES = 0) sur les 10 derniers jours :

select  inet_ntoa(IP_SRC_ADDR) SRC,inet_ntoa(IP_DST_ADDR) DST, 
        count(distinct L4_DST_PORT) NPORT 
from flowsv4 
where FIRST_SWITCHED > UNIX_TIMESTAMP(DATE_SUB(now(), interval 10 day)) 
  and IP_SRC_ADDR not between inet_aton('192.168.1.1') and inet_aton('192.168.3.255') 
  and L4_DST_PORT < 32768 
  and OUT_BYTES 0
group by 1,2,4 
having NPORT > 10 
order by IP_SRC_ADDR;

Ne pas oublier de ne sélectionner que les ports inférieurs à la limite sur votre système : 
sudo sysctl -a 2>/dev/null | grep local_port_range  
afin de ne pas bloquer de clients légitimes. 
Cet ordre permet de repérer les adresses IP d'origine de scans lents sur 10 jours (ou plus si votre historique est plus long) concernant plus de 10 ports différents (de vrais scanneurs)
Il est très facile ensuite à partir de la liste obtenue de bloquer ces adresses en les intégrant dans un "set" exploité dans un pare-feu. 
L'exécution de ce script peut être assez longue selon le nombre de rangs contenus dans la table principale malgré un index favorable sur le timestamp, mais il peut être lancé quelques fois chaque jour sans surcharge excessive.

Ici ce type de recherche est exploité "manuellement" pour tenir à jour une liste d'adresses IP à éviter, voir article spécifique ici.

Listes adresses IP agressives

Listes adresses IP agressives jpp

Pour protéger l'accès à mes machines j'utilise plusieurs listes d'adresses IP réputées "BLACK", par exemple :

Il en existe pas mal d'autres mais celles-ci fournissent déjà une bonne protection et donnent chez moi plus de 2000 hits par jour. 
Une fois bien triées :

  • Les ip simples on élimine les doubles
  • Les sous-réseaux on les passe dans Ipcalc là aussi pour éliminer les doublons.

Ensuite les deux "paquets" sont chargés dans deux "sets" (un set IP et un set NET) et le tour est joué en utilisant ces sets pour filtrer INPUT,FORWARD et même OUTPUT.

Une autre méthode consiste à éliminer les réseaux en provenance de pays très laxistes sur la surveillance ou dont le piratage est un des piliers de l'économie. On trouve ces renseignements par exemple sur le site http://www.ipdeny.com/ipblocks/data/countries/INITIALES_PAYS.zone&nbsp;
Soit par exemple "http://www.ipdeny.com/ipblocks/data/countries/cn.zone" pour éliminer tous les chinois d'un coup ! 
Aujourd'hui j'utilise les données fournies par IP2location pour gérer cette partie "PAYS". La liste des pays actuellement "bloques" :

BAD_LAND_LIST = "ar br cl cn co eg ge hk id in ir kz lv mn mx ng ph pk ps ru sc th tr ve vn"

Toutes ces adresses ou réseaux chargés dans des sets assurent une meilleure tranquillité !

Blocage intempestif

Blocage intempestif jpp

Petite mésaventure avec une de ces listes d'adresses, une de celles que j'utilise a eu l'idée saugrenue de mettre dans cette liste une adresse non routable dans une plage réservée aux réseaux privés (192.168.1.x). 
Lors de la dernière mise à jour cette adresse a donc été intégrée au pare-feu dans un "ipset" me causant quelques désagréments. 
Le premier à se rendre compte d'une anomalie a été Shinken qui m'a signalé que mon site Web (accédé en local) était devenu inaccessible. 
Après quelque recherche je me suis aperçu que les contrôles de Shinken étaient bloqués par le pare-feu (tous les refus sont enregistrés), la page des services était presque entièrement passée au "rouge". 
J'ai repéré assez rapidement l'adresse fautive et l'ai supprimée du "set" et Shinken s'est trouvé libéré. 
Il m'a fallu un peu plus de temps pour trouver l'origine du phénomène et ajouter un petit bout de code dans ma procédure ( tester range 192.168.1.0 à 192.168.3.255 dans mon cas) pour éviter ce type d'ennui à l'avenir. 
OUF !

Listes IP douteuses

Listes IP douteuses jpp

Note 15 juin 2021 : mises à jour :

  • Liste "IP_DOUTEUSES" actualisée plusieurs fois par jour 
    Suite à une erreur de manip la liste n'a pas été mise à jour sur le site du 13 avril au 15 juin 2021 !!! 
    C'est réparé ...
  • Liste "Spéciale Web" (origine modsecurity) actualisée une à deux fois par jour
  • Liste "Spéciale Windows" actualisée une fois par jour 
    Une erreur de manip a bloqué la mise à jour sur le site du 13 avril au 15 juin 2021 !!! 
    C'est là aussi réparé et la liste sera mise à jour automatiquement chaque jour.

Note 23 Septembre 2019 : une fantaisie de "modsecurity" (liée au passage en Debian Buster ?) a gêné l'accès à la liste principale, c'est en principe réparé ...

Je tiens à jour pour mes besoins propres deux listes d'adresses IP "douteuses" ou franchement "hostiles", ces adresses sont repérées à partir des logs du système (via OSSEC par exemple), des données de Suricata, de Modsec, de NtopNG (scans lents) ou encore de l'analyse directe des logs de serveurs Web ou mail. 
J'ai utilisé pendant longtemps cette liste première liste "brute" pour remplir un "set" (ipset) permettant d'exécuter un drop pur et simple de tout ce qui provient d'une de ces adresses utilisées par d'infâmes personnages. Cette lisre s'ajoute à celles obtenus des listes déja citées et aux réseau de pays "bannis".
Cette liste, mise à jour souvent (au minimum deux fois par jour), peut être utilisée avec un set "ipset" dans un firewall "iptables" :

# pour ne pas permettre la sortie vers ces adresses 
iptables -t mangle -A PREROUTING  -o "internet" -m set --match-set BLOCK_TMP dst -j MARK --set-mark 99 
iptables -t mangle -A PREROUTING  -o "internet" -m mark --mark 99 -m limit --limit 30/h --limit-burst 10      -j LOG --log-tcp-options --log-prefix 'MSG=Le_message_desiré ' 
iptables -t mangle -A PREROUTING -A PRE_EXT -m mark --mark 99                -j DROP 
# pour ne pas permettre l'entrée depuis ces adresses 
iptables -t mangle -A PREROUTING  -i "internet" -m set --match-set BLOCK_TMP src -j MARK --set-mark 98 
iptables -t mangle -A PREROUTING  -i "internet" -m mark --mark 98 -m limit --limit 30/h --limit-burst 10      -j LOG --log-tcp-options --log-prefix 'MSG=Le_message_desiré ' 
iptables -t mangle -A PREROUTING -A PRE_EXT -m mark --mark 98                -j DROP

ou un set nommé dans un firewall "nftables." :

ip saddr @BLOCK_TMP log prefix " MSG=Le_message_désiré " drop

Pour chaque adresse un commentaire est fourni indiquant le principal problème lié à l'adresse, certains rangs récupérés de l'ancien fichier n'ont pas de commentaire indicatif. 
Certaines adresses sont munies d'un suffixe autre que /32 lorsque plusieurs adresses d'un même sous-réseau ont été repérées, ce sous  réseau est alors réputé "plein de pirates" ... ou faisant partie du réseau d'un FAI un peu trop "permissif". 
A l'occasion j'ai "modernisé" la méthode de gestion de ce "set" (à l'origine simple fichier) pour passer à une table dans une base de données (MariaDB) qui me permet "d'oublier" les adresses n'ayant pas donné signe de vie (dans les tables de NtopNG) depuis une date spécifiée en ne sélectionnant que les #180 jours précédents. Mes tables NtopNG étant actives depuis mi 2016 j'utilise actuellement ( juin 2020) la date de 2020/01/01 comme butée. La gestion est assurée par trois scripts :

  • Un script SQL pur à faire tourner "de temps en temps", au moins une fois par semaine qui permet de tenir à jour la date de dernière "visite" de ces adresses à partir des enregistrements de NtopNg. 
    La sélection est donc moins de 180 jours depuis la dernière visite.
  • Un script Bash + SQL qui permet d'extraire et mettre en forme les données.
  • Un script de chargement du set (ipset actuellement) qui fonctionne par chargement d'un set intermédiaire suivi d'un "swap" avec le set permanent et d'un drop de l'ancien set permanent.

Cette liste (#42000 adresses au 29/02/2024) rafraîchie plusieurs fois par jour est disponible ici.

Note : 
Afin de mieux protéger le réseau de l'extérieur quelques adresses ont été rajoutées "en dur" dans la table :

  • Adresses non routables telles : 10.0.0.0/8, 172.16.0.0/12,192.168.0.1 à 192.168.2.10
  • Plages "réservées pour usage futur" : 240.0.0.0/4 ...


Autre liste "spéciale Windows" (#5600 adresses au 15/02/2022) disponible ici et rafraîchie au moins une fois par jour. 
Cette liste de #5600 adresses comporte toutes les adresses ayant tenté un accès sur un des ports suivants : 
22,135,137,138,139,445,1433,3389 au cours des 60 jours précédents, je viens d'y ajouter le port 23 (telnet) à cette liste qui cible aujourd'hui les objets connectés. 
Note : certaines de ces adresses peuvent déjà figurer dans les "grandes" listes d'IP à éviter.

Nouvelle liste "spéciale web" établie à partir des logs de Modsec, elle aussi rafraichie plusieurs fois par jour. 
Cette liste ne comporte, pour le moment, que peu d'adresses (#1000 au 29/02/2024) car mon installation de Modsec est relativement récente et que Suricata stoppe pas mal de cochonneries sur le port 80, mais elle devrait s'enrichir rapidement, surtout pour les adresses utilisant le port 443. Elle est constituée d'adresses ayant, au moins une fois, tenté un accès douteux (/wp-login.php, xmlrpc.php, /phpmyadmin ...) ,ou plusieurs fois un accès par l'adresse IP seulement (Scanner bète et méchant). Je n'aime pas non plus les "visiteurs" qui n'ont pas de header, par souci de discrétion probablement. Cela concerne surtout des "attaques"  en HTTPS car la plupart de celles sur le port 80 sont bloquées par Suricata). Par ailleurs les attaques sur le port 80 ont tendance à diminuer car ce site ne réponds pllus sur le port 80.  
Le format de ce fichier est particulier : 
211.20.101.36    #1# 2018/12/26 12:55:36  Bad Bot (no header)                      
211.36.156.120   #2# 2018/09/30 19:16:17  Pirate, possible ?  / Host header is a numeric IP address

  1. Adresse IP
  2. #N# si N = 1 c'est une adresse ne présentant pas de danger "a priori" (script kiddy ?), mais cela peut aussi être de la reconnaissance. Ce type d'adresse n'apparaît que si au moins deux accès ont été constatés dans la période. Si N = 2 c'est une adresse ayant tenté des accès frauduleux de type : /admin/login.php ou /phpmyadmin/setup.php .... /wp-login ... un seul accès suffit alors pour passer dans la liste.
  3. Commentaire décrivant le type d'accès détecté.

Les adresses sont éliminées au bout de 120 jours, si leurs utilisateurs n'ont pas récidivé ! Une seule récidive entraîne la remise a zéro de la période de 120 jours?
Le site AbuseIPDB à connaître pour vérifier (ou rapporter) la "malfaisance" d'une adresse IP :

Image retirée. 

Bots sans DNS Name

Bots sans DNS Name jpp

De plus en plus de "crawlers" sont "anonymes", la présence d'un user agent n'est pas suffisante pour certifier l'origine, n'importe qui peut cloner un "user agent", l'avantage du DNS name est qu'il existe une bonne probabilité que le détenteur du nom de domaine soit identifiable et cela semble une preuve probablement suffisante de l'origine de ce robot et de la confiance que l'on peut lui accorder.
Un "robot" non identifié peut très bien n'être qu'un vulgaire "pirate" en train de chercher une faille dans votre site.

Depuis quelques temps je bloque donc systématiquement au niveau du firewall les adresses de ces robots "anonymes" afin de décourager cette pratique et je conseille à tous de faire la même chose afin d'obtenir un internet un peu plus sain.

Il semble, notamment, que les robots destinés à alimenter les moteurs d"IA sont anonymes pour ne pas montrer qu'ils se servent des idées des autres pour "éduquer" leurs services.

Filtrage DNS

Filtrage DNS jpp

Installer un filtrage DNS, quelle est son utilité ?
Cela permet, à condition de disposer de listes de "mauvais" sites, de ne pas prendre le risque d'y être envoyés ou redirigés par un site piraté ou peu scrupuleux. Cela peut aussi éviter certains sites de phishing. 
Plusieurs sources de liste de noms de domaines à éviter sont récupérables sur Internet, l'une de ces listes est maintenue par "abuse.ch" qui présente aussi d'autres listes liées à la sécurité. 
Si vous disposez d'un DNS bind9 la prise en compte d'une telle liste est extrêmement facile et ne nécessite que quelques petits ajouts dans le paramétrage de Bind9/named et l'installation d'un commande en "crontab" pour tenir à jour le fichier de référence. 
1) La première modification doit être faite dans le fichier de paramètres qui contient la définition de vos "zones" (en général "named.conf"). Cette modification consiste à créer une nouvelle "zone" ce qui se fait en ajoutant en fin de fichier la description de la nouvelle zone : 
zone "urlhaus.zone" { 
    type master; 
    file "/etc/bind/urlhaus.rpz"; 
    allow-query { any; }; 
    allow-update { none; }; 
    allow-transfer { none; }; 
};

2) Il faut ensuite définir la nouvelle fonctionnalité dans les "options" (en général dans le fichier "named.conf.local"). Il suffit d'y ajouter la ligne suivante dans le paragraphe "options" : 
response-policy { zone "urlhaus.zone"; }; 
Attention à bien placer cette ligne entre les deux accolades du paragraphe "options".

3) Récupérer ensuite le fichier sur le site, à l'aide du script suivant que vous pourrez référencer dans votre "crontab" (au moins une fois par jour) :

#!/bin/bash 

#    GET new RPZ file 
# --------------------------------------------------------------- 
cp /etc/bind/urlhaus.rpz /etc/bind/urlhaus.rpz_old 
wget -O /etc/bind/urlhaus.rpz https://urlhaus.abuse.ch/downloads/rpz/&nbsp;
chmod +r /etc/bind/urlhaus.rpz

Un simple "reload" de Bind9 suffit à activer cette nouvelle fonctionnalité et les sites "douteux" ne pourront plus être atteints par votre machine. 
On peut même (avec un gentil petit script) y ajouter des noms de domaines si on le désire. La seule bizarrerie (?) c'est que je n'arrive pas à me débarrasser de domaines en ".top", pour les autres cela fonctionne très bien. 
Mettez dans votre fichier personnel les lignes suivantes : 
toto.com CNAME .    ; commentaire 
*.toto.com CNAME .  ; autre commentaire 
et ... tout le domaine "toto.com" deviendra inaccessible ... c'est pas mal pour certaines pubs, le DNS réponds instantanément que le site n'existe pas, donc aucun risque d'aller y faire un tour pour qu'il vous en joue de mauvais.