Sécurisation serveur et site intra/internet


.: Informations :.

Description :

Comment sécuriser un minimum son serveur et son site.
Sommaire :
|-- Sécuriser
	|-- Le système
		|-- Pile TCP/IP
		|-- SSH
		|-- Console
		|-- Syslog-NG
		|-- rkhunter
		|-- fail2ban
		|-- Snort
		|-- ACIDbase
		|-- Webmin
		|-- Les fichiers "perdus"
	|-- Le serveur
		|-- Contexte
		|-- ddclient
		|-- mod-security2
		|-- Peaufiner Apache
		|-- PHP
		|-- Les fichiers sensibles
	|-- Partie programmation
		|-- Relations MySQL
		|-- Commande système
		|-- Inclusion
		|-- Envoi de fichiers
	|-- Avant/après
		|-- Empreintes
		|-- BruteSSH
		|-- Failles web
|-- Note de fin
|-- Sources
|-- Historique


.: Pile TCP/IP :.

Même si la pile TCP/IP du système d'exploitation GNU/Linux est reconnue comme étant une des plus stables, appliquer ce principe de précaution est bien loin d'être un mal, au contraire !

Ouvrir le fichier /etc/sysctl.conf, puis inscrire à la suite ceci :

# Ignorer les messages 'ICMP Redirects' :
	net.ipv4.conf.all.accept_redirects=0
	
# Ignorer les messages 'ICMP Echo Request' :
	net.ipv4.icmp_echo_ignore_broadcasts=1
	net.ipv4.icmp_echo_ignore_all=1
	
# Ignorer les messages 'ICMP Bogus Responses' :
	net.ipv4.icmp_ignore_bogus_error_responses=1
	
# Interdire 'Source Routing' :
	net.ipv4.conf.all.accept_source_route=0
	
# Surveiller 'martians' (adresse source falsifiée ou non routable) :
	net.ipv4.conf.all.log_martians=1
	
# Se protéger de l'IP Spoofing' (vol d'adresse IP) :
	net.ipv4.conf.all.rp_filter=1
	
# Se protéger des attaques 'SYN Flood' :
	net.ipv4.tcp_syncookies=1


.: SSH :.

Installation :

root@btg # aptitude install ssh
On va faire en sorte que l'authentification se fasse par un système de clés publique/privée pour contrer les futurs essais de brut force. De plus on ne sera plus obligé d'entrer un mot de passe à chaque fois.

Côté serveur :
root@btg # ssh-keygen -t rsa
Plusieurs informations seront demandées, dans l'ordre :
     - ne pas changer l'emplacement ni le nom
     - entrer une passephrase complexe
     - retaper la passephrase

Copier la clef générée dans la liste des clefs autorisées :
root@btg # cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
Copier la clef vers le client de confiance :
root@btg # scp ~/.ssh/id_rsa uilisateur@adresse_client:/home/utilisateur/.ssh/

Côté client :
root@btg # ssh-agent
root@btg # ssh-add ~/.ssh/id_rsa
Entrer la passephrase. Modifier le fichier /etc/ssh/sshd_config pour changer la permission de se connecter en tant que root :
PermitRootLogin no

Autoriser seulement l'authentification par clefs :
AuthorizedKeysFile %h/.ssh/authorized_keys

Ainsi qu'interdire l'accès à l'aide de mot de passe :
PasswordAuthentication no
Redémarrer SSH :
root@btg # /etc/init.d/ssh restart


.: Console :.

Ne donner l'accès à une console qu'aux seuls utilisateurs qui en ont besoin (root et utilisateur de travail) en modifiant le fichier /etc/passwd.

Par défaut, la console est définie tel quel à la fin de chaque ligne :

/bin/sh ou /bin/*sh (suivant le shell utilisé)

Pour interdire l'accès, il suffit de le modifier en :
/bin/false


.: Syslog-NG :.

Pour se tenir informé de ce qu'il se passe sur votre serveur et système tout entier, on va installer Syslog-ng :

root@btg # aptitude install syslog-ng
Configuration de quelques programmes.


.: rkhunter :.

Installer cet outil qui vérifiera régulièrement la présence de rootkit et autres programmes modifiés sans que vous ne le sachiez :

root@btg # aptitude install rkhunter
Si jamais la version du dépôt est plus vieille que celle disponible sur le site officiel, l'installer tel quel :
root@btg # wget -c "http://downloads.sourceforge.net/rkhunter/rkhunter-1.3.4.tar.gz"
root@btg # tar -xzf rkhunter-1.3.4.tar.gz
root@btg # cd rkhunter-1.3.4
root@btg # sh installer.sh --layout /usr --install
root@btg # cd ..
root@btg # rm -rf rkhunter-1.3.4*
Paramétrage de rkhunter, ouvrir le fichier /etc/rkhunter.conf.

Décommenter et modifier la ligne 62 et spécifier une ou plusieurs adresse(s) courriel :
MAIL-ON-WARNING=root@localhost btg@bobotig.fr

Décommenter et modifier les lignes 134 et 469 pour avoir des informations dans Syslog-NG :
USE_SYSLOG=authpriv.warning
(...)
ALLOW_SYSLOG_REMOTE_LOGGING=1
Mettre le programme à jour et créer un fichier log :
root@btg # rkhunter --update --nocolors -l rkhunter.log
Lancer une analyse et insérer un résumé dans un fichier log :
root@btg # rkhunter -c --rwo --sk -l rkhunter.log
Avec :
-c				: vérifier le système entier
--rwo (report-warnings-only)	: n'afficher que les erreurs ou alertes
--sk (skip-keypress)		: ne pas attendre d'intervention de la part de l'utilisateur


.: fail2ban :.

Afin de bloquer les attaques de type force brute, on va installer fail2ban :

root@btg # aptitude install fail2ban
Il va falloir activer certaines prisons qui ne le sont pas par défaut.
Pour ce faire, copier le fichier /etc/fail2ban/jail.conf en /etc/fail2ban/jail.local et modifier à votre goût :
(...)
bantime  = 600			# Temps de ban en secondes
maxretry = 3			# Nombre de tentatives avant ban

(...)
destemail = root@localhost	# Votre adresse courriel

(...)
[ssh]
enabled = true
maxretry = 3

(...)
[ssh-ddos]
enabled = true
maxretry = 3

(...)
[apache]
enabled = true
maxretry = 3

(...)
[apache-multiport]
enabled   = true
maxretry  = 3

(...)
[apache-noscript]
enabled = true
maxretry = 3

(...)
[apache-overflows]
enabled = true
maxretry = 2

(...)
[named-refused-udp]
enabled  = true

(...)
[named-refused-tcp]
enabled  = true
Démarrer fail2ban :
root@btg # /etc/init.d/fail2ban restart
Vérifier que les prisons sont bien en place :
root@btg # cat /var/log/fail2ban.log
Devrait retourner :
2009-03-25 00:26:52,321 fail2ban.filter : INFO   Set findtime = 600
2009-03-25 00:26:52,322 fail2ban.actions: INFO   Set banTime = 600
2009-03-25 00:26:52,336 fail2ban.jail   : INFO   Jail 'apache-noscript' started
2009-03-25 00:26:52,349 fail2ban.jail   : INFO   Jail 'named-refused-udp' started
2009-03-25 00:26:52,381 fail2ban.jail   : INFO   Jail 'ssh-ddos' started
2009-03-25 00:26:52,439 fail2ban.jail   : INFO   Jail 'apache-multiport' started
2009-03-25 00:26:52,467 fail2ban.jail   : INFO   Jail 'apache-overflows' started
2009-03-25 00:26:52,635 fail2ban.jail   : INFO   Jail 'ssh' started
2009-03-25 00:26:52,650 fail2ban.jail   : INFO   Jail 'apache' started
2009-03-25 00:26:52,779 fail2ban.jail   : INFO   Jail 'named-refused-tcp' started


.: Snort :.

Snort est un IDS qui vous permettra de détecter d'éventuelles intrusions, de gérer vos logs et sniffer votre réseau.
Il est possible d'obtenir de plus amples informations concernant ce logiciel sur Wikipédia.

Installation :

root@btg # aptitude install snort-mysql

Choisir le réseau qui vous convient, ici je choisis de ne surveiller que la plage d'adresses allant de 192.168.0.0 à 192.168.0.255 :



Chez moi à partir de ce moment, j'ai une erreur. Mais c'est normal étant donné que l'on n'a pas paramétré snort. Il va falloir créer une base de données :
root@btg # mysql -u root -p -h localhost
        mysql > CREATE DATABASE `snort` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
        mysql > CREATE USER `snortu`@`localhost`;
        mysql > SET PASSWORD FOR `snortu`@`localhost`=PASSWORD('snortp');
        mysql > GRANT INSERT, SELECT, UPDATE on `snort`.* to `snortu`@`localhost`;
        mysql > quit

Ainsi qu'y créer les tables :
root@btg # cd /usr/share/doc/snort-mysql/
root@btg # zcat create_mysql.gz | mysql -u root -p -h localhost snort
Copier le fichier de configuration de snort tel que :
root@btg # cp /etc/snort/snort.conf /etc/snort/snort.interface.conf
Note : remplacer interface par votre interface réseau, chez moi eth0.


Ouvrir le fichier /etc/snort/snort.eth0.conf.

Modifier le réseau surveillé, ligne 46 :
var HOME_NET 192.168.0.0/24

Envoyer les rapports à MySQL, ligne 759 :
output database: alert, mysql, dbname=snort user=snortu password=snortp host=localhost

Appliquer les règles sur les SellCodes, ligne 944 :
include $RULE_PATH/shellcode.rules

Optionnel : commenter certaines règles qui, ici, ne sont d'aucune utilité :
#include $RULE_PATH/web-cgi.rules
#include $RULE_PATH/web-coldfusion.rules
#include $RULE_PATH/web-iis.rules
#include $RULE_PATH/web-frontpage.rules
#include $RULE_PATH/community-web-iis.rules
#include $RULE_PATH/x11.rules
#include $RULE_PATH/oracle.rules
#include $RULE_PATH/community-oracle.rules
#include $RULE_PATH/pop2.rules
#include $RULE_PATH/nntp.rules
#include $RULE_PATH/community-nntp.rules
#include $RULE_PATH/community-sip.rules
Étant donné que tout à l'heure, pendant la configuration, il y a eu une erreur, un fichier a été automatiquement créer afin de bloquer le démarrage du démon, on va le supprimer :
root@btg # rm /etc/snort/db-pending-config
Et enfin, lancer snort :
root@btg # /etc/init.d/snort start

Note : lorsque l'on utilise une autre interface qu'eth0 (par exemple wlan1), il faut lancer snort manuellement [1] :
root@btg # snort -u utilisateur -c /etc/snort/snort.wlan1.conf -i wlan1 -D


.: ACID :.

ACID est un analyseur de log pour Snort, il permet de visualiser facilement les log par l'intermédiaire d'une interface web.

Installation :

root@btg # aptitude install acidbase










Copier le fichier de configuration d'acidlab pour pouvoir se rendre sur l'interface web :
root@btg # cp /etc/acidbase/apache.conf /etc/apache2/sites-available/acidbase

Éditer ce fichier pour donner accès à une machine distante de confiance, ajouter ceci en dessous de allow from 127.0.0.0/255.0.0.0 :
allow from 192.168.0.3

Activez-le :
root@btg # a2ensite acidbase

Relancer apache :
root@btg # /etc/init.d/apache2 reload
Ouvrir le fichier /etc/acidbase/base_conf.php et modifier tel que :
$BASE_Language = 'french';
$colored_alerts = 1;
Maintenant, vous pouvez vous rendre à l'adresse http://www.test.sec/acidbase/ pour terminter l'installation d'ACID(BASE) et décortiquer les alertes.


.: Webmin :.

Webmin est une interface web permettant de gérer son serveur. Il est d'autant plus utile qu'il permet de voir ses logs, notammement ceux de syslog-ng et fail2ban.

Créer le fichier /etc/apt/sources.list.d/webmin.list et y inscrire :

# Dépôt Webmin
deb http://download.webmin.com/download/repository sarge contrib

Installer la clef gpg :
root@btg # wget -c "http://www.webmin.com/jcameron-key.asc"
root@btg # apt-key add jcameron-key.asc
root@btg # rm jcameron-key.asc

Mettre à jour les dépôts :
root@btg # aptitude update

Installer le programme :
root@btg # aptitude install webmin
Accéder à Webmin par https://www.test.sec:10000/, on va passer à la configuration.

Arrivé sur la page d'accueil, si vous avez une mise à jour disponible, installez-là.

Rendez-vous dans Webmin > Webmin Configuration > Language et choisir French (FR).
Rafraîchir la page pour prendre en compte la nouvelle langue.

Rendez-vous dans Un-used Modules et prendre System Logs NG.
Cliquer sur module configuration et ajouter le chemin du fichier log (/etc/syslog-ng/syslog-ng.conf).

Rendez-vous dans Système > Journaux système cliquer sur Ajouter un nouveau journal système, nous allons ajouter la prise en charge des fichiers log de fail2ban :

Vous pouvez en ajouter autant que vous le souhaitez de cette façon.


.: Les fichiers "perdus" :.

Par perdus j'entends là les fichiers qui n'ont pas de propriétaires ou qui ne devraient pas avoir les droits qu'ils ont.
Deux choses, l'une concerne les fichier sans propriétaire, l'autre les fichiers qui contiennent un SUID alors qu'il n'en ont pas besoin.


.: Contexte :.

Système d'exploitation : Debian Lenny
Serveur : Apache 2
PHP : PHP 5
Site : www.test.sec
Emplacement : /var/www/


.: ddclient :.

ddclient est un utilitaire très pratique qui permet d'automatiser la mise à jour d'une adresse IP dynamique reliée à un nom de domaine.

Installation :

root@btg # aptitude install ddclient
Après la configuration, éditer le fichier /etc/ddclient.conf et ajouter cette ligne :
ssl=yes

Ceci permettra de crypter les données envoyées, à faire si vous ne voulez pas qu'avec une attaque MITM, ces informations soient récupérables facilement.

Il faut bien vérifier que le module perl IO::Socket::SSL soit installé sur votre système :
root@btg # cpan -i IO::Socket::SSL


.: mod-security2 :.

On va installer mod-security2 (pare-feu web) pour Apache.

Créer le fichier /etc/apt/sources.list.d/mod-security2.list et y inscrire :

### Dépôt pour mod-security2 ###
deb http://etc.inittab.org/~agi/debian/libapache-mod-security2 ./

Installer la clef gpg :
root@btg # gpg --keyserver pgpkeys.mit.edu --recv-keys C514AF8E4BA401C3
root@btg # gpg --export -a C514AF8E4BA401C3 | apt-key add -

Mettre à jour les dépôts :
root@btg # aptitude update

Installer le module :
root@btg # aptitude install libapache2-mod-security2 mod-security2-common
Configuration du module, créer le fichier /etc/apache2/conf.d/mod-security.conf et ajouter ceci : <IfModule mod_security2.c> Include /etc/modsecurity/*.conf </IfModule>
Il va falloir créer le dossier /etc/modsecurity et copier les fichiers de configuration :
root@btg # mkdir /etc/modsecurity
root@btg # cd /usr/share/doc/mod-security-common/examples/rules
root@btg # cp *.conf /etc/modsecurity/

De plus, il faut créer le dossier pour les logs :
root@btg # mkdir /etc/apache2/logs
Optionnel : commenter la ligne contenant Host header is a numeric IP address du fichier /etc/modsecurity/modsecurity_crs_21_protocol_anomalies.conf pour autoriser l'accès au site par l'intermédiaire d'une adresse IP.

Optionnel : pour changer la signature du serveur, modifier la ligne contenant SecServerSignature du fichier /etc/modsecurity/modsecurity_crs_10_config.conf. Activer le module :
root@btg # a2enmod mod-security

Enfn, relancer Apache :
root@btg # apache2ctl restart
Vérifier que le module est bien chargé :
root@btg # cat /var/log/apache2/error.log | grep ModSecurity
Devrait renvoyer :
[Mon Mar 16 13:37:37 2009] [notice] ModSecurity for Apache 2.1.5 configured
Bien qu'il s'agisse là d'un excellent module et d'une protection fiable, il se peut qu'il soit un peu chiant lorsque vous développez en local, le comportement de PHPmyAdmin peut être altéré, certains scripts retournerons une erreur car jugés dangereux.
Afin de parer ce soucis, et ce seulement en développement, vous pouvez ajouter une règle dans les options du vhost ou dans un .htaccess qui désactivera mod-security :
SecRuleEngine Off

Bien entendu, une fois le développement terminé, il est plus que fortmement conseillé de rétablir la sécurité.


.: Peaufiner Apache :.

On va désactiver diverses divulgations d'informations comme la signature du serveur, la méthode TRACE, et caetera.

Éditer le fichier /etc/apache2/apache2.conf et ajouter ces lignes :

ServerSignature Off
ServerTokens Prod
TraceEnable Off

Optionnel : si le module rewrite est installé et activé, voici quelque protections supplémentaires, à placer dans un fichier .htaccess :
# Empêcher les attaques par include de fichier externe
RewriteEngine On
RewriteCond %{QUERY_STRING} =http://
RewriteRule .* - [F,L]
# Bloquer l'accès au site pour libwww-perl
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} libwww [NC]
RewriteRule .* - [F,L]

Optionnel : autre protection, à placer aussi dans un fichier .htaccess :
# Protection contre les attaques se servant de register global on
SetEnv REGISTER_GLOBALS 0
Redémarrer apache :
root@btg # /etc/init.d/apache2 restart
Dans les fichiers d'options des vhosts ou dans un fichier .htaccess il est possible de bloquer certaines actions.


Note : pour combiner plusieurs options, il faut les mettres à la suite tel que :
Options -Indexes -FollowSymLinks -MultiViews
Attention : il est déconseillé de sécuriser un répertoire par un accès à l'aide de la méthode d'authentification d'Apache.
Le pourquoi du comment est simple : les informations transitent en clair, de ce fait, à l'aide d'une attaque MITM, il est très facile d'obtenir celles-ci.


.: PHP :.

Modifier le fichier /etc/php5/apache2/php.ini. Le mode sécurité

Si activé, un certain nombre de fonctions sont limitées ou désactivées (celles dédiées aux commandes systèmes, notamment) [http://www.php.net/manual/fr/features.safe-mode.functions.php], une vérification stricte des permissions d'accès des fichiers (basées sur l'UID et le GID) est faite sur les fonctions concernées et les variables d'environnement sont protégées.

Activer le mode de sécurité de PHP :

safe_mode = On

Spécifier un ou plusieurs répertoires dans lesquels les fonctions affectées par le safe_mode seront disponibles :
safe_mode_exec_dir = /private_dir/

Restreindre les répertoires d'inclusion et d'excution :
safe_mode_include_dir = /path/to/dir
safe_mode_exec_dir = /path/to/exec/dir
Ne pas fournir la version de PHP :
expose_php = Off

Ne pas afficher les erreurs :
display_errors = Off
Interdire l'enregistrement des variables globales :
register_globals = Off

Restreindre les emplacements du site :
open_basedir = /chemin/racine/du/site
De ce fait, si je me place à la racine du site, il me sera impossible d'inclure le fichier ../../../../../../../etc/passwd par exemple.
Note : cette directive n'est pas supportée par l'équipe de sécurité PHP, mais ça peut être une option utile. Désactiver certaines commandes :
disable_functions = php_uname, getmyuid, getmypid, passthru, leak, listen, diskfreespace, tmpfile, link, ignore_user_abord, shell_exec, dl, set_time_limit, exec, system, highlight_file, source, show_source, fpaththru, virtual, posix_ctermid, posix_getcwd, posix_getegid, posix_geteuid, posix_getgid, posix_getgrgid, posix_getgrnam, posix_getgroups, posix_getlogin, posix_getpgid, posix_getpgrp, posix_getpid, posix, _getppid, posix_getpwnam, posix_getpwuid, posix_getrlimit, posix_getsid, posix_getuid, posix_isatty, posix_kill, posix_mkfifo, posix_setegid, posix_seteuid, posix_setgid, posix_setpgid, posix_setsid, posix_setuid, posix_times, posix_ttyname, posix_uname, proc_open, proc_close, proc_get_status, proc_nice, proc_terminate, phpinfo
Interdire l'ouverture et l'inclusion de fichiers distants :
allow_url_fopen = Off
allow_url_include = Off

Si vous n'utilisez pas de formulaires pour l'envoi de fichiers, il est bon de désactivé le système d'envoi :
file_uploads = Off

Par contre si vous avez ce genre de formulaire, il faut limiter un répertoire d'envoi et une taille maximale :
upload_tmp_dir = /var/php_tmp
upload_max_filezize = 2M
Enfin, une dernière chose des plus convoitée, les sessions.
Enregistrement des sessions :
session.save_path = /var/lib/php

Il est déconseillé demanipuler vos sessions à l'aide de JavaScript.
À l'aide de cette directive, JavaScript ne pourra lire les sessions (afin d'éviter le XSS) :
session.cookie_httponly = 1
De ce fait, JavaScript ne pourra accéder qu'aux cookies. Fichier log.

Demander de créer un fichier log contenant les erreurs peut toujours être pratique :
log_errors = On

Ne pas logguer une erreur récurrente :
ignore_repeated_errors = On

fichier log :
error_log = /var/log/php_errors.log
Ou bien configurer-le tel qu'il redirige les messages vers syslog-NG (voir section Syslog-NG).


.: Les fichiers sensibles :.

Il faut bien veiller à ce que certains fichiers ne soient accessibles pour tout le monde qu'en lecteur seule.
Il s'agit de ce genre de fichiers :
         - robots.txt
         - .htpasswd
         - .htgroup
         - fichiers contenant des infos sensibles comme les identifiants MySQL

De plus, il est conseillé de changer les nom des fichiers .htpasswd ou .htgroup en les spécifiant dans le .htaccess :

AuthUserFile /var/www/admin/.drowssap
AuthGroupFile /var/www/admin/.puorg


.: Relations MySQL :.

Avant d'ajouter une quelconque information de votre base de données, échaper les caractères spéciaux à l'aide de la commande mysql_real_escape_string() :

Code PHP :

$chaine = mysql_real_escape_string($chaine);
Avant de vérifier une information sensible dans la BDD comme le nom d'un utilisateur et son mot de passe, il faut toujours s'assurer que l'on n'entre pas de caractères spéciaux qui pourraient corrompre la requête.

Code PHP :
$utilisateur = trim(htmlspecialchars(addslashes($utilisateur)));
$motDePasse = trim(htmlspecialchars(addslashes($motDePasse)));

$interdit = array(
	'/&/', '/#/', '/\[/', '/\]/', '/\//', '/\'/', '/%/', '/=/',
	'/\(/', '/\)/', '/;/', '/--/', '/=/', '/ /', '/,/',
	'/(\<|\>|;|UNION|ALL|SELECT|WHERE|AND|OR|FROM|COUNT)/', '/\*/');

foreach ( $interdit as $valeur ) {
	if ( preg_match($valeur, $utilisateur) || preg_match($valeur, $motDePasse) ) {
		die ('Caractère interdit : tentative d\'injection SQL ?!');
	}
}
Dernier point, et non des moindres, créer un utilisateur ayant des droits restreints pour toutes transactions.
Notamment, la base information_schema ne doit pas pouvoir être lue.

Pour ce faire, il suffit de créer un utilisateur et de lui affecter les drois minimums sur la BDD utilisée :
root@btg # mysql -u root -p -h localhost
        mysql > CREATE USER `utilisateur_restreint`@`localhost`;
        mysql > SET PASSWORD FOR `utilisateur_restreint`@`localhost`=PASSWORD('mdp_complexe');
        mysql > GRANT INSERT, SELECT, UPDATE, DELETE on `base`.* to `utilisateur_restreint`@`localhost`;
        mysql > quit
Tel que créé ci-dessus, votre utilisateur utilisateur_restreint pourra interroger, insérer et supprimer des données dans la/les table(s) de la base de données base mais n'aura absolument aucun accès aux autres bases.


.: Commande système :.

La façon le plus fiable est de passer la commande directement grace à system('commande'), mais si vous devez le faire par l'intermédiaire d'une variable tel que system('$cmd'), il faut bien faire attention à empêcher le caractère pipe (|) :

Code PHP :

if ( (strstr($cmd, '|')) || (strstr($cmd, '%7c')) ) {
	die ('Erreur : caractère interdit !');
}


.: Inclusion :.

Toujours vérifier les possibles fichiers à inclure, ne pas laisser un trop grand choix d'inclusions et vérifier l'extension du fichier inclu.

Note : si vous avez installer le module mod-security2 pour apache, vous ne risquez pas grand chose quant au type d'inclusion visant un fichier sortant du répertoire web.

Exemple de code si vos inclusions doivent être dynamiques (essayer d'entourer le fichier inclu par un préfixe et un suffixe).

Code PHP :

if ( isset($_GET['page']) && !empty($_GET['page']) ) {
	if ( file_exists('page-'.$_GET['page'].'.html') ) {
		include 'page-'.$_GET['page'].'.html';
	}
}

Exemple de code si vos inclusions sont statiques (vous connaissez la page à inclure, il n'y a pas de doute).

Code PHP :
if ( isset($_GET['page']) && $_GET['page'] == 'page.php' ) {
	include $_GET['page'];
}


.: Envoi de fichiers :.

Toujours vérifier les fichier envoyés, si vous demandez une image de type PNG, il est hors de question de laisser passer un fichier PHP ou je ne sais quoi d'autre. L'idéal serait de pouvoir filtrer l'extension en plus du type mime.

Si vous autorisez l'envoi de scripts, quelque soit le langage, faîtes une copie en fichier texte et n'autoriser personne à l'exécuter hormis root :

Code PHP :

copy($fichier, $fichier.'.txt');
chmod($fichier.'.txt', 400);
Vérifier l'extension et le nom du fichier uploadé.

Exemple de script qui va regarder qu'il n'y ait pas de caractères spéciaux comme "/" ou "\" :

Code PHP :
$extensions = array('.jpeg', '.png', '.gif');
$fichier = $_FILES['fichier']['name'];

if ( preg_match('#[\x00-\x1F\x7F-x9F/\\\\]#', $fichier) ) {
	echo 'Le nom du fichier comporte des caratères interdits';
}

$extension = strrchr($fichier, '.');

if ( !in_array($extension, $extensions) ) {
	echo 'Le format de fichier n\'est pas accepté. Seuls le jpeg, le png et le gif sont acceptés.';
}
Vérifier la taille du fichier uploadé.

Exemple de script qui va regarder si le fichier n'excède pas une taille donnée :

Code PHP :
$taille_max = 10000;
$taille_fichier = filesize($_FILES['fichier']['tmp_name']);

if ( $taille_fichier > $taille_max ) {
	echo 'Le fichier est trop gros, envoi impossible, la taille maximale est de 10Mo.';
}


.: Empreintes :.

Voici différents outils avec lesquels on peut trouver des informations sur le serveur comme les modules chargés par apache, la version du serveur, le système d'exploitation, et caetera.

Avant

Commande :

root@btg # ./httprint -h www.test.sec -s signatures.txt
httprint v0.301 (beta) - web server fingerprinting tool
(c) 2003-2005 net-square solutions pvt. ltd. - see readme.txt
http://net-square.com/httprint/
httprint@net-square.com

Finger Printing on http://192.168.0.198:80/
Finger Printing Completed on http://192.168.0.198:80/
--------------------------------------------------
Host: 192.168.0.198
Derived Signature:
Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny2 with Suhosin-Patch mod_python/3.3.1 Python/2.5.2 mod_perl/2.0.4 Perl/v5.10.0
9E431BC86ED3C295811C9DC5811C9DC5050C5D32505FCFE84276E4BB811C9DC5
0D7645B5811C9DC5811C9DC5CD37187C11DDC7D7811C9DC5811C9DC58A91CF57
FCCC535B6ED3C295FCCC535B811C9DC5E2CE6927050C5D336ED3C295811C9DC5
6ED3C295E2CE69262A200B4C6ED3C2956ED3C2956ED3C2956ED3C295E2CE6923
E2CE69236ED3C295811C9DC5E2CE6927E2CE6923

Banner Reported: Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny2 with Suhosin-Patch mod_python/3.3.1 Python/2.5.2 mod_perl/2.0.4 Perl/v5.10.0
Banner Deduced: Apache/2.0.x
Score: 135
Confidence: 81.33
------------------------
Scores:
Apache/2.0.x: 135 81.33
Apache/1.3.[4-24]: 127 65.87
Apache/1.3.27: 126 64.09
Apache/1.3.26: 125 62.34
TUX/2.0 (Linux): 123 58.93
Apache/1.3.[1-3]: 122 57.27
Apache/1.2.6: 112 42.34
Agranat-EmWeb: 86 15.87
Stronghold/4.0-Apache/1.3.x: 77 10.20
Com21 Cable Modem: 70  6.81
WebSitePro/2.3.18: 70  6.81
Microsoft-IIS/6.0: 69  6.39
Lexmark Optra Printer: 65  4.87
Oracle Servlet Engine: 64  4.53
Jetty (unverified): 64  4.53
Netscape-Enterprise/4.1: 63  4.20
dwhttpd (Sun Answerbook): 63  4.20
SMC Wireless Router 7004VWBR: 63  4.20
thttpd: 62  3.89
Intel NetportExpressPro/1.0: 62  3.89
Lotus-Domino/6.x: 60  3.30
EMWHTTPD/1.0: 60  3.30
Belkin Wireless router: 60  3.30
Microsoft-IIS/5.0 ASP.NET: 59  3.03
Microsoft-IIS/5.1: 59  3.03
Apache-Tomcat/4.1.29: 57  2.52
Netscape-Enterprise/3.6 SP2: 54  1.85
cisco-IOS: 54  1.85
Netscape-Enterprise/6.0: 53  1.65
AOLserver/3.5.6: 52  1.46
RealVNC/4.0: 52  1.46
Linksys WRTP54G: 52  1.46
JRun Web Server: 51  1.28
Netscape-Enterprise/3.5.1G: 50  1.11
TightVNC: 50  1.11
CompaqHTTPServer/1.0: 50  1.11
MikroTik RouterOS: 50  1.11
IDS-Server/3.2.2: 50  1.11
VisualRoute 2005 Server Edition: 50  1.11
Microsoft-IIS/4.0: 49  0.95
Microsoft-IIS/5.0: 49  0.95
Boa/0.94.11: 49  0.95
RomPager/4.07 UPnP/1.0: 49  0.95
JC-HTTPD/1.14.18: 49  0.95
Stronghold/2.4.2-Apache/1.3.x: 47  0.67
HP-ChaiServer/3.0: 46  0.54
Ipswitch-IMail/8.12: 46  0.54
Linksys with Talisman firmware: 27  0.47
Linksys AP2: 28  0.47
Zeus/4.0: 26  0.47
GWS/2.1 Google Web Server: 29  0.46
AkamaiGHost: 25  0.46
NetWare-Enterprise-Web-Server/5.1: 24  0.45
WebLogic Server 8.x: 24  0.45
WebLogic Server 8.1: 24  0.45
Hewlett Packard xjet: 30  0.45
HP Jet-Direct Print Server: 30  0.45
Jetty/4.2.2: 30  0.45
CompaqHTTPServer-SSL/4.2: 23  0.44
squid/2.5.STABLE5: 23  0.44
Tanberg 880 video conf: 31  0.44
Microsoft-IIS/URLScan: 21  0.41
MiniServ/0.01 Webmin: 33  0.39
AssureLogic/2.0: 33  0.39
Netscape-Enterprise/3.6: 20  0.39
fnord: 20  0.39
MiniServ/0.01: 20  0.39
Tcl-Webserver/3.4.2: 20  0.39
Resin/3.0.8: 19  0.37
AOLserver/3.4.2-3.5.1: 34  0.36
Jana Server/1.45: 34  0.36
Oracle XML DB/Oracle9i: 17  0.32
Zeus/4.1: 36  0.28
Xerver_v3: 36  0.28
CompaqHTTPServer/4.2: 36  0.28
Allied Telesyn Ethernet switch: 36  0.28
WebLogic XMLX Module 8.1: 36  0.28
Lotus-Domino/5.x: 15  0.27
Microsoft ISA Server (external): 15  0.27
Netgear MR814v2 - IP_SHARER WEB 1.0: 15  0.27
EHTTP/1.1: 14  0.25
Microsoft-IIS/5.0 Virtual Host: 14  0.25
Tomcat Web Server/3.2.3: 14  0.25
Adaptec ASM 1.1: 14  0.25
Zeus/4_2: 37  0.23
Orion/2.0x: 37  0.23
BaseHTTP/0.3 Python/2p3.3 edna/0.4: 43  0.21
Surgemail webmail (DManager): 43  0.21
SunONE WebServer 6.0: 12  0.19
Netscape-Enterprise/4.1: 12  0.19
Cisco-HTTP: 11  0.17
Cisco Pix 6.2: 11  0.17
RemotelyAnywhere: 10  0.14
3Com/v1.0: 10  0.14
Microsoft ISA Server (internal): 10  0.14
WebSENSE/1.0: 10  0.14
Domino-Go-Webserver/4.6.2.8: 39  0.11
Linksys Print Server: 8  0.10
Netscape-Enterprise/3.5.1: 40  0.04
ServletExec: 5  0.04
Zope/2.6.0 ZServer/1.1b1: 41  0.03
Ubicom/1.1: 2  0.01
Ubicom/1.1 802.11b: 2  0.01
Snap Appliances, Inc./3.x: 1  0.00
Linksys AP1: 0  0.00
Linksys Router: 0  0.00
NetBuilderHTTPDv0.1: 0  0.00
NetPort Software 1.1: 0  0.00
Linksys BEFSR41/BEFSR11/BEFSRU31: 0  0.00
MailEnable-HTTP/5.0: 0  0.00

--------------------------------------------------

Commande :
root@btg # amap -bvq www.test.sec 80
Using trigger file ./appdefs.trig ... loaded 30 triggers
Using response file ./appdefs.resp ... loaded 346 responses
Using trigger file ./appdefs.rpc ... loaded 450 triggers

amap v5.2 (www.thc.org/thc-amap) started at 2009-04-01 10:28:48 - MAPPING mode

Total amount of tasks to perform in plain connect mode: 23
Waiting for timeout on 23 connections ...
Protocol on 192.168.0.198:80/tcp (by trigger http) matches http - banner: HTTP/1.1 200 OK\r\nDate Wed, 01 Apr 2009 142848 GMT\r\nServer Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny2 with Suhosin-Patch mod_python/3.3.1 Python/2.5.2 mod_perl/2.0.4 Perl/v5.10.0\r\nLast-Modified Wed, 01 Apr 2009 125817 GMT\r\nETag "1b3c2-2d-4667dde844c
Protocol on 192.168.0.198:80/tcp (by trigger http) matches http-apache-2 - banner: HTTP/1.1 200 OK\r\nDate Wed, 01 Apr 2009 142848 GMT\r\nServer Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny2 with Suhosin-Patch mod_python/3.3.1 Python/2.5.2 mod_perl/2.0.4 Perl/v5.10.0\r\nLast-Modified Wed, 01 Apr 2009 125817 GMT\r\nETag "1b3c2-2d-4667dde844c

amap v5.2 finished at 2009-04-01 10:28:54

On voit bien que nous sommes sur un serveur Debian (Lenny) avec Apache 2.2.9 et PHP 5.2.6.

Après

Commande :

root@btg # ./httprint -h www.test.sec -s signatures.txt
httprint v0.301 (beta) - web server fingerprinting tool
(c) 2003-2005 net-square solutions pvt. ltd. - see readme.txt
http://net-square.com/httprint/
httprint@net-square.com

--------------------------------------------------
Host: www.test.sec
ICMP request time out on www.test.sec

--------------------------------------------------

Commande :
root@btg # amap -bvq www.test.sec 80
Using trigger file ./appdefs.trig ... loaded 30 triggers
Using response file ./appdefs.resp ... loaded 346 responses
Using trigger file ./appdefs.rpc ... loaded 450 triggers

amap v5.2 (www.thc.org/thc-amap) started at 2009-04-01 12:02:11 - MAPPING mode

Total amount of tasks to perform in plain connect mode: 23
Waiting for timeout on 23 connections ...

amap v5.2 finished at 2009-04-01 12:02:23

Du coup, on ne voit plus rien !


.: BruteSSH :.

BruteSSH est un script python qui, comme son nom l'indique, permet de brute forcer un serveur SSH via un dictionnaire.

Rendez-vous sur le blog de benjy (http://benjy-blog.blogspot.com/2009/03/brutessh-video.html) afin d'y voir une vidéo traitant sur Brutessh et voir l'efficacité de l'attaque par force brute.

Commandes

Voyons si le port SSH est ouvert :

root@btg # nmap www.test.sec

On voit bien la ligne :
22/tcp  open  ssh


Démarrons le brute forçage :
root@btg # python brutessh.py -h www.test.sec -u root -d /root/liste.txt

Avant

Si le mot de passe est trouvé, voici ce que le script affichera :

On voit bien :
Auth OK ---> Password Found: azertyu

Après

Le script s'interrompt... Grâce à fail2ban, je viens de me faire bannir ;)

Contenu du fichier log /var/log/fail2ban.log :

2009-04-01 182:05:02,100 fail2ban.actions: WARNING [ssh] Ban 192.168.0.168
2009-04-01 182:05:02,362 fail2ban.actions: WARNING [ssh] 192.168.0.168 already banned

De plus, si vous avez mis en place une authentification par clefs seulement, adieu BruteSSH.


.: Failles web :.

On va tester le site web tournant sur ce serveur à l'aide de Nikto.

Commande

root@btg # ./nikto.pl -h www.test.sec

Avant

- Nikto v2.03/2.04
---------------------------------------------------------------------------
+ Target IP:          192.168.0.198
+ Target Hostname:    www.test.sec
+ Target Port:        80
+ Start Time:         2009-04-02 11:44:50
---------------------------------------------------------------------------
+ Server: Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny2 with Suhosin-Patch mod_python/3.3.1 Python/2.5.2 mod_perl/2.0.4 Perl/v5.10.0
- Allowed HTTP Methods: GET, HEAD, POST, OPTIONS, TRACE
+ OSVDB-877: HTTP method ('Allow' Header): 'TRACE' is typically only used for debugging and should be disabled. This message does not mean it is vulnerable to XST.
+ Apache/2.2.9 appears to be outdated (current is at least Apache/2.2.10). Apache 1.3.41 and 2.0.63 are also current.
+ mod_perl/2.0.4 appears to be outdated (current is at least 5.8)
+ OSVDB-877: TRACE / : TRACE option appears to allow XSS or credential theft. See http://www.cgisecurity.com/whitehat-mirror/WhitePaper_screen.pdf for details
+ OSVDB-3092: GET /phpmyadmin/ : phpMyAdmin is for managing MySQL databases, and should be protected or limited to authorized hosts.
+ OSVDB-3092: GET /manual/ : Web server manual found.
+ OSVDB-3268: GET /icons/ : Directory indexing is enabled: /icons
+ OSVDB-3268: GET /manual/images/ : Directory indexing is enabled: /manual/images
+ OSVDB-3233: GET /icons/README : Apache default file found.
+ 3577 items checked: 10 item(s) reported on remote host
+ End Time:        2009-04-02 11:45:06 (16 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Test Options: -h www.test.sec
---------------------------------------------------------------------------

De plus, si sur le serveur, il y a un CMS, cet utilitaire peut révéler la possibilité de XSS ou d'injection SQL...

Après

Plus rien ne filtre grâce à Mod-security2 :

- Nikto v2.03/2.04
---------------------------------------------------------------------------
+ Target IP:          192.168.0.198
+ Target Hostname:    www.test.sec
+ Target Port:        80
+ Start Time:         2009-04-02 12:10:27
---------------------------------------------------------------------------
+ Server: Apache
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ 3577 items checked: 0 item(s) reported on remote host
+ End Time:        2009-04-02 12:10:39 (12 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Test Options: -h www.test.sec
---------------------------------------------------------------------------
Server: Apache est la valeur que j'ai indiqué dans /etc/modsecurity/modsecurity_crs_10_config.conf.


.: Note de fin :.

Certains des programmes décrits plus haut permettent l'envoi de courriel en cas d'erreur critique ou par simple avertissement régulier.
Pour donner la possibilité de sortir du local, éditer le fichier /etc/postfix/main.cf et si votre FAI est Orange :

relayhost = smtp.orange.fr
Redémarrer postfix :
root@btg # /etc/init.d/postfix restart
Maintenant vous avez toutes les billes pour sécuriser votre système, surtout au niveau du serveur apache.

Rappelez-vous toujours : 99% des problèmes se trouve entre la chaise et le clavier.
Mais aussi que chaque programme est susceptible de contenir une ou plusieurs faille(s), pensez à vérifier régulièrement les mises à jour de sécurité.

Non optionnel : abonnez-vous à la liste de diffusion debian-security (http://lists.debian.org/debian-security-announce/) !


.: Sources :.


.: Historique :.