Herkeios

Système de détection des intrusions

Comportement anormal



   L'évolution des IDS concerne surtout l'intégration des concepts d'intelligence artificielle dans l'étude du système. Effectivement, il reste beaucoup de choses dont un humain peut se rendre compte facilement à l'oeil nu, alors qu'un système quelconque aura vraiment du mal à analyser. En réalité, ceci est dû au fait que la machine n'a pas le concept de "normalité".
S'il peut paraître bizarre à un humain qu'une batterie de connexion réseau soit ouverte par rapport à d'habitude, que le transfert de fichiers vers l'extérieur paralyse le réseau ou qu'une majorité de connexions n'aboutissent pas, le système lui ne verra qu'une suite de fait isolés qui ne forment pas la signature d'une attaque. D'ailleurs, 10 connexions sur une machine peuvent constituer une anormalité, alors qu'il s'agira plutôt de 100 sur une autre. La réponse à ce problème se retrouve dans l'analyse statistique et probabiliste des différents évenements. Ie, un évenement avec une faible probabilité d'arriver ou dépassant les maximums statistiques observés résulte d'un disfonctionnement (disfonctionnements liés en général à une mauvaise utilisation où à une intrusion)
Nous n'avons pas choisi de commenter cette partie suivant nos sources comme dans les parties précédentes, car l'implémentation est finalement plus du domaine de l'algorithmie et la notre n'est en rien exemplaire.

Apprentissage
   Comme nous l'avons déjà entrevu, l'étape d'apprentissage est fondamentale dans l'étude statistique du système. C'est à ce moment que le système va comprendre les règles que doit suivre le système et celles qui indiquent un problème lorsqu'elles sont violées. Dans notre cas d'analyse des sockets entrants/sortants, ceci revient à echantilloner de manière régulière les transactions réseau et de dresser des statistiques à terme plus ou moins long. Durant cette période, le système doit dresser une moyenne des statistiques à un instant t (états, nombre de connexions, etc..). Dans le même temps, il doit repérer les maximums, c'est-à-dire les "pics" de transfert.

Par conséquent, il ne faut pas lancer ce genre de procédure à n'importe quel moment et avec n'importe quelle durée. Effectivement, si la durée est trop longue, les données notamment les pics ou les différences d'affluence aux heures de la journée seront noyées ; il est evident qu'une durée trop petite a de faibles chances d'être représentative du réseau. Dans notre cas, nous avons fixé le temps de détection à 2 jours et à une période d'échantillonage de quelques minutes.
De plus, il faut s'assurer que le réseau soit en situation normale (pas de période de mises à jour, de vacances, etc..), ceci afin de ne pas sur-évaluer ou sous-évaluer le traffic, ce qui réduirait de façon conséquente l'utilité du programme (trop de faux positifs ou niveau de détection beaucoup trop haut).

Détection
   L'étape d'echantillonnage passée, il est possible de continuer l'étalonnage du système. Cette solution ne nous paraît pas forcément la meilleure. Si on pense avoir une représentation crédible du système actuel, pourquoi ne pas la garder ainsi ? Un apprentissage au fur et à mesure favoriserai l'intégration de fausses données et une intrusion se faisant par essais successifs serait intégrée aux statistiques et pourrait empêcher des détections ultérieures.
Quoi qu'il en soit, la dernière étape consiste en l'application de prédicats simples définis par l'utilisateur. Voici par exemple une partie de notre fonction d'analyse des résultats :
    void analyse(struct stats * s_stats[]) {

      struct stats ** saved_stats = get_svg(), *temp;
      int i,j;

      printf("%d connexions soit %d%% de la normale (pic à %d)\n", [...]);
      printf("%d%% de connexions tcp, contre %d%% en temps normal (pic à %d%%)\n", [...]);
      printf("%d%% de connexions udp, contre %d%% en temps normal (pic à %d%%)\n", [...]);

      for (i = 0;i < NUM_ANALYSED;i++) {
        if (!(DETECTION_LEVEL & (1 << i))) continue;
        switch(i) {

          case LOCAL_ADDR:
            printf("%d serveurs, contre %d en temps normal (%d%%)\n",[...]);
            break;
          case REM_ADDR:
            j=0;
            for (temp=s_stats[i] ; temp != NULL ;temp = temp->next)
              if (!get_num(saved_stats[i],temp->whatever))
                j++;

            printf("%d communiquants externes contre %d connus\n",longueur(s_stats[i]),longueur(saved_stats[i]));
            printf("%d communiquants externes inconnus\n",j);
            break;

          case LOCAL_PORT:
            printf("%d ports contre %d connus\n",longueur(s_stats[i]),longueur(saved_stats[i]));
            break;

          case REM_PORT:
            printf("%d ports contre %d connus\n",longueur(s_stats[i]),longueur(saved_stats[i]));
            break;

          case STATE:
            printf("%d etats differents contre %d d'habitude\n",longueur(s_stats[i]),longueur(saved_stats[i]));
            for (temp=s_stats[i] ; temp != NULL ;temp = temp->next)
              printf("%d sockets à l'état %d, contre %d en temps normal (pic à %d)\n", [...]));
            break;

          [...]

          case OWNER:
            printf("%d utilisateurs utilisent des sockets, contre %d en temps normal\n",[...]);
            printf("%d sockets root, contre %d en temps normal\n",get_num(s_stats[i],0),[...]);
            break;

          [...]
        }
      }

      free(saved_stats);
    }
Nous laissons entrevoir ici comment nous avons choisi de stocker les statistiques, mais le but n'est pas là. Ceci permet de montrer le type de règles que l'on peu fixer à partir d'un échantillon simple comme celui-ci : le pourcentage de sockets root ne doit pas dépasser la normale de 10%, la nombre de connexions à l'instant t ne doit pas dépasser le pic de plus de 5%, il ne doit pas y avoir de communiquants externes inconnus (pour les réseaux fermés). On peut même spécifier des règles plus poussées comme le fait que la proportion de socket à l'état 3 (= SYN_RECV, c'est-à-dire en attente d'acquittement de l'ouverture de la connexion) ne doit pas dépasser un certain seuil, afin d'éviter par exemple le SYN Flood.
Bref, la compilation des règles que l'on peut implémenter avec des échantillons simples mais intéressants comme les ports de connexion, la proportion de tel ou tel protocol ou le propriétaire du socket est énorme.

L'analyse statistique peut s'appliquer depuis l'analyse en temps réel, pour par exemple repérer la fréquence de réception de paquets RST qui indiquent souvent quelque chose de mauvais en grand nombre (détournement TCP/IP au milieu de la connexion, scans en début de connexion, ..).



Site sur la sécurité informatique - Qu'est-ce qu'un IDS ? - L'équipe Herkeios