Détecteur de vulnerability scanner

Contenu du snippet

Bonjour,

Ceux qui me connaissent savent qu'il y a une chose (parmi tant d'autres) que je ne supporte pas : les vulnerability scanner. Petit rappel sur ce qu'est un "vulnerability scanner", il s'agit d'un petit robot (bot) dont le but est de passer de serveur en serveur afin de vérifier l'existence d'un logiciel qu'il sait contenir une faille en vue de l'exploiter. Bien souvent ces vagabonds du web passent en revue de grandes plages d'adresses IP afin de trouver des victimes potentielles. Ici je vous propose une class qui, pour un serveur web, aide à détecter ces bots et à écrire un fichier de log en vue d'analyse.

Le principe est très simple, le contenu de l'URL et de l'user-agent sont analysées afin de définir si oui ou non c'est un vulnerability scanner qui a fait la requête. Une fois détecté une entrée contenant toutes les informations utiles est écrite dans un fichier de log afin de l'administrateur puisse l'utiliser afin de luter contre ces menaces.

A principe simple, utilisation simple. Un simple appel à la méthode start_analyze() est suffisant. Il faut cependant faire remarquer deux choses importantes :
1/ Il est nécessaire de faire un fichier bot_alerts.log afin que le script puisse y écrire. Ce fichier doit avoir 0622 comme droits. Une commande pour le créer est donc `touch bot_alerts.log && chmod 0622 bot_alerts.log`. On prendra soin de faire en sorte que le propriétaire du fichier ne soit pas le même utilisateur que celui utilisé par le serveur web afin d'éviter que le fichier ne soit visible depuis l'extérieur.
2/ Afin de connaître l'url demandée on utilise $_SERVER['REDIRECT_URL'] et non $_SERVER['QUERY_STRING']. La raison est simple : l'appel à cette classe se fera dans la page affichée lors d'une erreur 404. Ceci pour trois raisons évidentes :
- De tels bots ciblent des logiciels grand public tels que PHPMyAdmin, pas vos pages perso.
- Vu la quantité de tests fait ils déclenchent presque obligatoirement une erreur 404.
- Si vous avez bien fait votre travail il ne doit y avoir presque que les bots qui déclenchent des 404 (avec exception sur les demandes de favicon, apple-touch-icon.png etc).

Fonctionnalités :
- Permet d'obtenir un log précis sur les activités repérées comme étant des vulnerability scanner.
- Le fichier de log est épuré de tout caractère non affichable (meilleur lisibilité et prévention des risques d'attaques par utilisation de séquences d'échappement propres au terminal).
- En cas de détection d'un bot, termine prématurément le script.
- Redirige les bots vers un nom de domaine non valide (juste pour embêter ceux qui les suivent).

Pour ceux qui veulent modifier certaines parties, au lieux de modifier directement la classe il est recommandé d'en créer une nouvelle qui hérite de celle-là afin de surcharger les membres et méthodes désirés. Le code est suffisamment découpé pour permettre une bonne utilisation de la surcharge.

Nota :
La présence de "Windows 98" dans les recherches sur le useragent est du à un bot que je rencontre régulièrement et qui se fait passer pour un IE6 sur Windows 98. Le nombre de clients réels restant sous windows 98 et générant des 404 est tellement insignifiant que je me suis permis de l'ajouter comme tel.

Edit :
Désolé pour l'indentation un peu foireuse par endroits, les tabulations ne sont pas gérées ici de la même manière que sur emacs. Si j'ai le temps je rectifierai ce point.

Source / Exemple :


<?php
// BotDetector.php for BotAnalyzer in /home/tycho/sources/php/class
// 
// Made by Rodolphe Breard
// Mail    <rodolphe.breard@laposte.net>
// 
// Started on  Sat Nov 14 11:13:32 2009 Rodolphe Breard
// Last update Thu Nov 19 15:54:30 2009 Rodolphe Breard
// 
// Copyright (C) 2009 Rodolphe Breard
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

define('BOTDETECTOR_LOGFILE', './bot_alerts.log');

class		BotDetector
{
  protected	$log_msg = null;
  protected	$url_patterns = array('config', 'admin', 'adm', 'sql', 'shop',
				      'store', 'cart', 'include', 'pma');
  protected	$user_agent_patterns = array('Windows 98', 'Python', 'libwww',
					     'urllib', 'lwp',
					     'Morpheus', 'Fucking', 'Scanner',
					     'Toata', 'dragostea', 'pentru',
					     'diavola');

  public function	start_analyze()
  {
    $this->check_patterns($_SERVER['REDIRECT_URL'], $this->url_patterns);
    if (!empty($_SERVER['HTTP_USER_AGENT']))
      $this->check_patterns($_SERVER['HTTP_USER_AGENT'],
			    $this->user_agent_patterns);
  }

  protected function	bot_handler()
  {
    $this->write_log();
    header('Location: http://no_bots.invalid/');
    die();
  }

  protected function	write_log()
  {
    $LogFile = new SplFileInfo(BOTDETECTOR_LOGFILE);
    if (!$LogFile->isFile())
      throw new Exception('BotAnalyzer: write_log: invalid log file.');
    if ($LogFile->getPerms() & 0777 != 0622)
      if (!chmod(BOTDETECTOR_LOGFILE, 0622))
	throw new Exception('BotAnalyzer: write_log: bad log file mode.');
    if (!$LogFile->isWritable())
      throw new Exception('BotAnalyzer: write_log: unwritable log file.');
    $LogFile = $LogFile->openFile('a');
    $this->init_log_msg();
    $LogFile->fwrite($this->log_msg);
  }

  protected function	init_log_msg()
  {
    $datas = array(date('r'),
		   $_SERVER['REMOTE_ADDR'],
		   $_SERVER['REQUEST_METHOD'],
		   $_SERVER['SERVER_PROTOCOL'],
		   $_SERVER['HTTP_HOST'],
		   $_SERVER['REDIRECT_URL'],
		   (isset($_SERVER['HTTP_USER_AGENT']) ?
		    $_SERVER['HTTP_USER_AGENT'] : ''));
    foreach ($datas as $key => $val)
      $this->log_msg .= ($key != 0 ? ' - ' : '') . $this->protect_data($val);
    $this->log_msg .= "\n";
  }

  protected function	protect_data($str)
  {
    if (empty($str))
      return 'unknown';
    $rep = str_split(' !"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~');
    $replace = null;
    foreach ($rep as $val)
      $replace[urlencode($val)] = $val;
    return strtr(urlencode($str), $replace);
  }

  protected function	check_patterns($var, array $patterns)
  {
    foreach ($patterns as $pat)
      {
	if (stripos($var, $pat) !== false)
	  $this->bot_handler();
      }
  }
}

?>

Conclusion :


Ne vous attendez pas à ce que ça fasse le café, j'ai fait ça juste sur un coup de colère contre le présences quotidienne de ces saletés de bots dans un serveur dont j'ai la charge. Je doute que grand monde ne soit intéressé mais dans le doute je partage, et puis si certains ne connaissaient pas l'existence de ces vagabonds c'est une bonne occasion pour apprendre :)

Bonne chasse aux bots et tout mon amour aux filles du diable (les initiés comprendront).

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.