PHP-IDS, ou comment protéger son site web

Il y a quelques temps, j’ai découvert un outil indispensable, et qui plus est open source… Il n’en faut pas plus pour que je m’y jette dessus à corps perdus.

PHP-IDS, qu’est-ce que c’est?
Il s’agit d’un système de détection d’intrusion en php. Il s’interpose entre les pages du site, et les données entrées par l’utilisateur, et détecte les tentatives d’injection, que ce soit SQL, XSS ou autres. Utilisant un système de “points”, il va donner un poids a chaque détection, et si le total dépasse la norme tolérée, il interdit la poursuite de l’affichage de la page du site.



Attention, il ne s’agit pas pour autant d’une solution miracle! Il reste nécessaire de bien coder afin d’éviter des problèmes. Mais il fournit une protection suplémentaire au site sur lequel il est configuré.

Mise en place

  1. On récupère les sources sur le site officiel : http://php-ids.org/downloads/
  2. On décompresse nos sources
  3. On mets à jour les fichiers default_filter.xml et converter.php afin d’avoir des données le plus a jour possible
    https://svn.php-ids.org/svn/trunk/lib/IDS/default_filter.xml
    https://svn.php-ids.org/svn/trunk/lib/IDS/Converter.php
  4. On place le répertoire lib/IDS dans les librairies de notre projet
  5. On configure le fichier IDS/Config/Config.ini
    ; PHPIDS Config.ini
    
    ; General configuration settings
    
    ; !!!DO NOT PLACE THIS FILE INSIDE THE WEB-ROOT
    ; IF DATABASE CONNECTION DATA WAS ADDED!!!
    
    [General]
    
        ; basic settings - customize to make the PHPIDS work at all
        filter_type     = xml
        filter_path     = /chemin/vers/lib/IDS/default_filter.xml
        tmp_path        = /chemin/vers/lib/IDS/tmp
        scan_keys       = false
    
        ; in case you want to use a different HTMLPurifier source, specify it here
        ; By default, those files are used that are being shipped with PHPIDS
        HTML_Purifier_Path  = IDS/vendors/htmlpurifier/HTMLPurifier.auto.php
        HTML_Purifier_Cache = IDS/vendors/htmlpurifier/HTMLPurifier/DefinitionCache/Serializer
    
        ; define which fields contain html and need preparation before
        ; hitting the PHPIDS rules (new in PHPIDS 0.5)
        html[]          = __wysiwyg
    
        ; define which fields shouldn't be monitored (a[b]=c should be referenced via a.b)
        exceptions[]    = __utmz
        exceptions[]    = __utmc
    
        ; PHPIDS should run with PHP 5.1.2 but this is untested - set
        ; this value to force compatibilty with minor versions
        ;min_php_version = 5.1.6
        min_php_version = 5.1.2
    
    ; If you use the PHPIDS logger you can define specific configuration here
    
    [Logging]
    
        ; file logging
        ; non necessaire si log via DB
        path            = /chemin/vers/lib/IDS/tmp/phpids_log.txt
    
        ; email logging
    
        ; note that enabling safemode you can prevent spam attempts,
        ; see documentation
        recipients[]    = test@test.com.invalid
        subject         = "PHPIDS detected an intrusion attempt!"
        header          = "From: <PHPIDS> info@php-ids.org"
        safemode        = true
        allowed_rate    = 15
    
        ; database logging
    
        wrapper         = "mysql:host=localhost;port=3306;dbname=phpids"
        user            = phpids_user
        password        = phpids
        table           = intrusions
    
    ; If you would like to use other methods than file caching you can configure them here
    
    [Caching]
    
        ; caching:      session|file|database|memcached|none
        caching         = memcached
        expiration_time = 600
    
        ; file cache
        path            = /chemin/vers/lib/IDS/tmp/default_filter.cache
    
        ; database cache
        wrapper         = "mysql:host=localhost;port=3306;dbname=phpids"
        user            = phpids_user
        password        = 123456
        table           = cache
    
        ; memcached
        host           = localhost
        port           = 11211
        key_prefix     = PHPIDS
        tmp_path       = /chemin/vers/lib/IDS/tmp/memcache.timestamp
  6. La base de donnée n’est nécessaire que si l’on désire stocker les logs dedans. On peut en effet choisir si on désire un simple fichier de log, syslog, base de donnée, ou rien. Si vous désirez utiliser une base de donnée, il est nécessaire de créer la base seon les infos fournies dans le fichier de conf. POur la création de la table:
    CREATE TABLE `intrusions` (
      `id` int(11) unsigned NOT NULL auto_increment,
      `name` varchar(128) NOT NULL,
      `value` text NOT NULL,
      `page` varchar(255) NOT NULL,
      `userid` int(11) unsigned NOT NULL,
      `session` varchar(32) NOT NULL,
      `ip` varchar(15) NOT NULL,
      `reaction` tinyint(3) unsigned NOT NULL COMMENT '0 = log; 1 = mail; 2 = warn; 3 = kick;',
      `impact` int(11) unsigned NOT NULL,
      `created` datetime NOT NULL,
      PRIMARY KEY  (`id`)
    );
  7. Une fois configurer, il ne reste plus qu’a l’inclure dans nos sites. Pour cela, je vous conseille de créer un fichier prepend, et de configurer le htaccess pour le charger en priorité. Voici un exemple du fichier de traitement. A vous de l’adapter selon vos besoins:
    <?php
    
    // On rajoute le chemin de la lib
    set_include_path(
        get_include_path()
        . PATH_SEPARATOR
        . '/chemin/vers/lib/'
    );
    
    // Inclusion de PHP-IDS
    require_once 'IDS/Init.php';
    
    /*
     * Un exemple d'utilisation consiste à utiliser try()
     * afin de récupérer d'éventuelles erreurs
     */
    try {
        // Attention à l'ordre des variables EGPCS
        $request = array_merge_recursive($_GET, $_POST, $_COOKIE);
        $init = IDS_Init::init(APPLI_ROOT.'/lib/IDS/Config/Config.ini');
    
        // lancement de l'IDS
        $ids = new IDS_Monitor($request, $init);
        $result = $ids->run();
    
        // Decision...
        if (!$result->isEmpty()) {
            /*
             * Pour le DEBUG il suffit de faire
             * echo $result;
             */
            // Exemple d'interpration : on affiche un msg d'erreur
            echo "Sorry, but it seems your browser has sent incorrect data.<br>";
    
            // On loggue l'attaque
            /*
             * Dans le cas d'un fichier de log :
             * require_once 'IDS/Log/File.php';
             */
            require_once 'IDS/Log/Database.php';
            require_once 'IDS/Log/Composite.php';
    
            $compositeLog = new IDS_Log_Composite();
            $compositeLog->addLogger(IDS_Log_Database::getInstance($init));
            /*
             * Dans le cas d'un fichier de log
             * $compositeLog->addLogger(IDS_Log_File::getInstance($init));
             */
    
            $compositeLog->execute($result);
            die();
        } else {
            // On peut afficher quelque chose pour dire que PHPIDS tourne
            //echo '<a href="?test=%22><script>eval(window.name)</script>">No attack detected - click for an example attack</a>';
            echo "PHPIDS is running";
        }
    } catch (Exception $e) {
        printf(
            'An error occured: %s',
            $e->getMessage()
        );
    }
  8. Il ne reste plus qu’a tester l’application! Vous pouvez avoir un exemple de ce qui doit se passer ici: http://demo.php-ids.org/

Remarque: PPH-IDS nécessite au minimum PHP 5.1.2 pour fonctionner. De plus, si vous désirez logguer les données dans une base mysql, vous devrez avoir activer PDO et PDO Mysql

Posted on February 17, 2009 at 12:25 by Onet · Permalink · 3 Comments
In: Informatique, Php, Programmation, Tutoriaux, Web securité · Tagged with: , , , , ,

IspCP: upgrade Etch à Lenny

J’ai effectué ma mise à jour de Etch vers Lenny sur mon serveur en prod. Celui est gérer pour la partie hébergement par IspCP. J’avoue que je commence gentiment à retrouver mon souffle, et à destresser… J’ai eu, comment dire… Un peu de stress!

Le problème? Oh, pas grand chose… Juste qu’aucuns de mes vhosts ne voulaient fonctionner… Ou plus précisément que les scripts phps refusaient de fonctionner.. Comme ca, tout a coup! J’avais le droit à une erreur 500 dés le moment ou je tentais d’accéder a un script php.

A titre d’informations, voila la commande qui m’a posé souci:

aptitude dist-upgrade



C’est à dire la vrai mise à jour complète de mon système!

Après plusieurs recherches, voila l’information que j’avais dans un apache2ctl configtest:

Warning: SuexecUserGroup directive requires SUEXEC wrapper.
Warning: SuexecUserGroup directive requires SUEXEC wrapper.
Warning: SuexecUserGroup directive requires SUEXEC wrapper.
Warning: SuexecUserGroup directive requires SUEXEC wrapper.

Donc problème avec Apache. Une recherche google me signale que je dois faire un chmod 4711 /usr/lib/apache2/suexec. Je m'exécute... Manque de bol, je ne recois qu'une information comme quoi suexec n'existe pas... Ok, ca doit venir de la...

aptitude install suexec
reboot

Après un reboot, le système refonctionnait parfaitement! J’ai pu terminer ma mise à jour par un

aptitude safe-upgrade
aptitude full-upgrade

Et me voila avec une magnifique bécane sous Debian Lenny, à jour!

Si je peux éviter des sueurs froides à certains d’entre vous, j’en serais heureux ;)

Backup journalier serveur – script

Quand on a un serveur dédié, ou même un poste sous Linux, on désire effectuer des sauvegardes, de manière régulière.

Je vous propose ici le script que j’utilise se mes serveurs dédiés, afin d’effectuer une sauvegarde journalière de mes sites, ainsi que de la base de donnée concernée. Le script permets de garder un historique de 7 jours des fichiers et des bases de données. Il ne s’agit pas d’un backup incrémentiel, mais bien total. Pourquoi? Par simplicité, pour éviter d’éventuels problèmes de perte de données intermédiaires, et parce que le backup que j’utilise (backup fournis avec mon dédié chez OVH) ne me permets que de faire du ftp => pas de rsync.

Le script effectue 2 sauvegardes. Tout d’abords il récupère un dump de la base de donnée (dump complète), puis il compresse chaque répertoire séparément. Finalement, il effectue un backup complet directement sur le ftp. Il faut prévoir suffisament de place sur le disque. D’autant que le script garde en local une copie des backups des 7 jours. Il est possible de les supprimer, pour cela, il suffit de faire un rm -rf du répertoire du jour (1-7) et de le recréer.

Néanmoins, je vous proposerais prochainement un script plus perfectionner, permettant de faire à la fois du rsync sur un serveur distant, et du ftp. Il s’agit d’un script sans grandes prétentions, mais qui permets d’avoir un backup fiable et simple à mettre en place!

N’oubliez pas d’adapter les informations de configuration en haut du script, de lui donner les droits d’exécution, et de le placer dans le crontab! Parmis les outils nécessaires au fonctionnement du script, pensez à installer ncftp (aptitude install ncftp), afin de disposer du programme ncftput.

#!/bin/bash



# Les constantes
ftp_login=”’
ftp_pwd=”
ftp_host=”
bdd_login=”
bdd_pwd=”
path_site=”
path_bkp=”
path_ftp=”
email_log=”
date=`date`

# erreurs de ncftput
declare -a CDERR
CDERR[1]=”Could not connect to remote host.”
CDERR[2]=”Could not connect to remote host – timed out.”
CDERR[3]=”Transfer failed.”
CDERR[4]=”Transfer failed – timed out.”
CDERR[5]=”Directory change failed.”
CDERR[6]=”Directory change failed – timed out.”
CDERR[7]=”Malformed URL.”
CDERR[8]=”Usage error.”
CDERR[9]=”Error in login configuration file.”
CDERR[10]=”Library initialization failed.”
CDERR[11]=”Session initialization failed.”
CDERR[142]=”Delai depasse pour la connexion.”

start=”file debut : $date — ”
id=`date +%u`

`mysqldump -u $bdd_login -p$bdd_pwd –all-database > $path_bkp/$id/mysqldump_$id.sql`
for site in `ls $path_site`
do
`rm -Rf $path_bkp/$id/$site”_”$id.tgz`
`tar czf $path_bkp/$id/$site”_”$id.tgz $path_site/$site`
done

`tar –create –gzip –file – $id | ncftpput -v -u $ftp_login -p $ftp_pwd -c $ftp_host $path_ftp/$id.tgz`

res_ftp=$?
if [ $res_ftp != "0" ]; then
`echo ${CDERR[$res_ftp]} | mailx -s “ERREUR LORS DU BACKUP DES FICHIERS !!!” $email_log`
fi

date=`date`
echo $start “fin: $date”

`ls -la $path_bkp/$id/ | mailx -s “Backup du $date” $email_log`

Posted on February 16, 2009 at 12:53 by Onet · Permalink · Leave a comment
In: Linux, Programmation, Tutoriaux · Tagged with: , , , , ,

La voila enfin… Debian Lenny est passée en stable !

22 mois après la sortie de la version 4.0 de Debian (Debian Etch), datée du 08 avril 2007, la fondation Debian annonce avec fierté la naissance de son dernier bébé: Debian 5.0 Lenny !

La sortie d’une version de Debian est toujours attendue avec beaucoup d’impatience par la communauté!

Parmis les nouveautés de cette version 5.0, citons, de manière non exhaustive:

En tout, plus de 23’000 paquets prêt à l’emploi, accessible simplement par la commande aptitude !

De plus, la sécurité à été un élément important de cette release, sur plusieurs points, notamment PHP (suoshin configuré en standard), la réduction du nombre de port ouvert lors d’une installation de base, la diminution du nombres d’applications nécessitant des droits ROOT pour fonctionner, etc…

Plusieurs images peuvent être téléchargées, directement depuis le site officiel (http://www.debian.org), allant du CD/DVD standards au liveCD permettant de tester la compatibillité de son système dans procéder à l’installation complète!

Pour les heureux détenteur d’une version de Debian Etch, il suffit maintenant d’effectuer la mise à jour du système, via l’outils aptitude (pensez à modifier les sources, si dans celles-ci vous spécifier la version à installer…

vim /etc/apt/sources.list
Vérifiez la présence de la version (normalement vous etes soit en “etch” soit en “stable”)
Dans le premier cas, changer de “Etch” vers “lenny”, dans le second, vous n’avez rien a faire
aptitude update && aptitude upgrade

Lors du premier aptitude update, on recoit une erreur pgp. Pour la corriger:

gpg ?keyserver pgpkeys.mit.edu ?recv-key 4D270D06F42584E6
gpg -a ?export 4D270D06F42584E6 | apt-key add -

De plus, il y a de fortes chance que le serveur mysql refuse de redémarrer, et nous renvoie un fail, a cause d’un souci de log. Pour le régler (dans le cadre d’un système single de mysql), il faut commenter ces 2 lignes dans /etc/mysql/my.cnf:

#expire_logs_days = 10
#max_binlog_size = 100M

N’oubliez pas de jeter un oeil aux informations de mises à jour, disponible ici: http://www.debian.org/releases/lenny/releasenotes

Bonne installation à tous ;)

Posted on February 16, 2009 at 09:29 by Onet · Permalink · One Comment
In: Debian Etch, Debian Lenny, Informatique, Linux, Tutoriaux · Tagged with: , ,

Mise en relation client – prestataire

Peut être êtes-vous à la recherche d’un prestataire dans le monde du développement, du graphisme, ou autre? Ou à l’opposer, vous êtes développeur, graphiste autre freelance, et vous recherchez des clients?

Je viens de remplir mon premier contrat sur http://www.codeur.com, et j’attends à l’heure qu’il est la validation du client, et le payement.

Comment cela fonctionne? C’est tout simple. En temps que client, vous créer un appel d’offre, contenant le plus de détail sur votre projet, ainsi que son délai, son stade et le budget que vous avez. Puis, vous attendez. En temps que prestataire, vous pouvez visualiser les projets, etfaire une proposition à ceux qui vous sembles convenir.

Une fois que le client dispose d’assez d’offre, il en sélectionne une, et lui octroye le projet. La réalisation peut commencer! Le prestataire et le clients reçoivent chacun les coordonnées de l’autre, et se mettent en relation directe.

Une fois le projet terminé, le client effectue le payement sur un compte sécurisé, et vous pouvez lui livrer le travail. Dans le meilleur des cas, tout se passe bien, le client est satisfait, et libère la somme. Dans le cas contraire, vous utilisez codeur.com comme intermédiaire afin de récupérer votre argent.

Voila un moyen simple et efficace de travailler, en freelance, tout en gardant une certaine sécurité de payement.

A l’attention des freelanceurs Suisse: Pour vous inscrire, vous devez fournir un numéro de TVA. En france, ils appelle cela le portage salariale. Etbien sur, nous n’y avons pas accès! Enfin, presque… En effet, une entreprise permets de le faire. N’hésitez pas à me contacter via mon blog si vous désirez leur adresse!

Posted on February 11, 2009 at 09:13 by Onet · Permalink · Leave a comment
In: Php, Programmation · Tagged with: , , , , , , , ,