jeudi 21 mars 2013

Mes débuts en matière de défenses de mon serveur

 Contexte

J'ai un petit serveur à la maison qui me sert de NAS et de HTPC.
Je viens de modifier légèrement ma configuration de lighty pour utiliser simple_vhosts. Et comme jamais rien ne marche du primer coup j'obtiens un joli "404 Not Found".
Premier réflexe :
# tail /var/log/lighttpd/access.log
Pour voir ce que me retourne la recherche de chemin (mais au final je ne pense pas que ce soit ici, surtout que simple-vhost.debug n'est pas à enable).

Surprise : dans les dernières lignes je vois:
222.126.196.123 - - [20/Mar/2013:09:42:34 +0100] "GET /w00tw00t.at.ISC.SANS.DFind:) HTTP/1.1" 400 349 "-" "-"
Bon évidemment ça ne me plais pas trop.


Petites astuces (de débutant)

Utiliser des connexion chiffré (HTTPS, SSH, SFTP, ...)

Vérifier des requêtes étrangères

# grep -v "192.168." /var/log/lighttpd/access.log
 Voici ce qui ressort le plus
198.7.63.1 84.101.215.38 - [08/Mar/2013:13:14:52 +0100] "GET /phpMyAdmin/scripts/setup.php HTTP/1.1" 404 345 "-" "ZmEu"
avec les chemins :
 * /pma/scripts/setup.php
 * /db/scripts/setup.php
 * /admin/scripts/setup.php
 * /phpmyadmin-[version]/scripts/setup.php
 * ...
Enfin vous avez compris le concept. Ici M. 198.7.63.1 (dont je ne citerai pas le nom :-)) essaie de trouver le script de configuration de phpMyAdmin (mais en vain :-p).

Vous pouvez vérifier si certaines de ces attaques à trouvé une page existante :
# grep -v "192.168." /var/log/lighttpd/access.log | grep -v 404

Changer les chemins par défaut

Cette attaque n'a pas réussi car phpMyAdmin n'est pas accessible par une adresse habituelle.
Donc première chose à faire (à l'installation) ne pas utiliser de chemin classique.

Supprimer les fichiers d'installation

Pensez à supprimer les fichiers d'installation ou à les renommer. La plus part des CMS et autres sont fournis avec des scripts d'installation/configuration auxquels l'accès n'est pas protégé (faut bien rentrer son mot de passe une première fois pour qu'il existe). Et ces mêmes CMS et consort conseille de supprimer ces fichiers FAITE-LE !!!

Faite une redirection de port non triviale


Pour accéder aux différents services de votre serveur à partir d'internet (j'entends en dehors de votre réseau local) vous allez devoir faire de la redirection de port au niveau de votre box (ou de votre routeur adsl).
Ne redirigé pas bêtement le port 22 vers le port 22 de votre serveur.
Chercher une plage de port peu utilisée (ex: 11200-11300) et transposer les port classique dans cette plage (ex: 11225 -> 22, 11255 -> 25, ...).

Astuces pour serveur HTTP

J'utilise lighttpd comme serveur HTTP sur mon serveur. Je me sers de la fonction proxy pour rediriger les port inhabituels à partir du port 80.

Exemple de transmission

L'accès à l'interface web de transmsission est http://mon-serveur:9091, mais on voudrait y accéder de manière plus simple par http://mon-serveur/transmission.
Il suffit de quelques lignes dans la configuration de lighttpd:
$HTTP["url"] =~ "^/transmission" {
    proxy.server = ("" => (
        ( "host" => "127.0.0.1", "port" => 9091 ),
    ))
}
Et voilà le tour est joué. Et par exemple si votre box redirige le port 80 vers votre serveur, vous voulez sûrement sécuriser l'accès.
Ceci nécessite quelques étapes intermédiaires :
  1. Générer un mot de passe chiffré stocké dans un fichier
    $ htdigest -c fichier-password.txt "Transmission Restricted Area" nom-utilisateur
    cette commande va créer (ou l'écraser) le fichier fichier-password.txt, et sauver le mot de passe pour l'utilisateur nom-utilisateur.
  2. Modifier la configuration pour prendre en charge le module d'authentification.
    server.modules += ( "mod_auth" )
  3. Ajouter l'authentification pour les adresses IP externes.
$HTTP["url"] =~ "^/transmission" {
     $HTTP["remoteip"] !~ "^192\.168\.1\.\d+$" {
        auth.backend = "htdigest"
        auth.backend.htdigest.userfile = "fichier-password.txt"
        auth.require = ("" => (
            "method" => "digest",
            "realm"  => "Transmission Restricted Area",
            "require" => "valid-user"
        ))
    }
    proxy.server = ( ... )
}
Attention le realm doit être le même dans la configuration de lighttpd et dans la génération des mots de passes.

Forcer les connexions HTTP externes vers du HTTPS

Pour me permettre de gérer mes différents services depuis mon smartphone hors du réseau local, j'ouvre un peu mes pages vers l'extérieur.
Pour obligé les connexions HTTP externe a utiliser du HTTPS avec lighttpd c'est très simple.
On va "activer" le support de SSL:
$SERVER["socket"] == ":443" {
    ssl.engine   = "enable"
    ssl.pemfile  = "/path/to/file.pem"
}
Qu'est-ce que c'est que ce file.pem ?
Un fichier PEM est un fichier qui contient (dans ce cas) une clé privé et un certificat chiffré. Il permet au visiteur d'identifier le serveur (vous allez avoir la page qui dit "Attention ... je sais pas qui c'est ... êtes-vous sûr de vouloir continuer ?" dans votre navigateur, au passage n'acceptez tous quand vous naviguer sur internet). Comme, ici, je ne vais pas faire un cours sur les certificats et les clés, je vous conseille de bien vous renseigner.
Bref, pour faire un certificats auto-signé :
$ openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes
Quelques question sont posées pour vous identifier (c'est le but du certificat).

À partir de maintenant (moyennant un redémarrage du serveur), vous êtes en mesure de vous connecter en https://votre-server.loc.

Étape suivante : forcer la connexion en HTTPS.
Le principe est simple, si votre adresse IP n'est pas une adresse IP locale, alors je vous redirige vers le port 443.

# Adresse IP non locale
$HTTP["remoteip"] !~ "192\.168\.[01]\.\d+" {
    # connexion en HTTP
    $HTTP["scheme"] == "http" {
        # sert juste à récupérer le nom d l'hôte pour la redirection
        $HTTP["host"] =~ ".*" {
            # on redirige
            url.redirect = ( ".*" => "https://%0$0" )
        }
    }

    # éventuellement on peut ajouter une identification
    # à condition d'avoir configuré auth.backend ...
    auth.require = ( "/mysql-admin/" => (
        "method"  => "digest",
        "realm"   => "Restricted Area",
        "require" => "valid-user"
    )
}

2 commentaires:

  1. Le https est très important (surtout quand on sait que la NSA espionne beaucoup de terminaux !!!). Et un petit "nmap" depuis Internet est toujours utile afin de configurer au mieux le firewall. Le mieux est de ne pas utiliser du tout les 1024 premiers ports (éventuellement 80/443 avec le 80 qui redirige vers les autres mais pas plus).

    RépondreSupprimer
  2. pour le moment je galère un peu pour bien saisir le fonctionnement logiciel des certificats et des clés, je ré-écrirai la partie HTTPS dans un article dédié au SSL (SSH, HTTPS, ...).
    Tu me fais penser à mettre un petit chapitre sur namp, la gestion des ports, ...

    RépondreSupprimer