Salut,

Ayant eu un peu de temps et souhaitant améliorer la sécurité de mon serveur, j'ai étudier et mis en pratique différentes approches que j'ai trouvé un peu partout sur le net.
Fort de ces lectures et de mes compétences, j'ai écrit un script qui rajoute une couche de sécurité à un serveur linux (basé sur debian).

Ce script travaille sur plusieurs points :
- Sécurisation de SSH ( Changement du port d'écoute, empêche root de ce connecter, n’autorise qu'un ou des utilisateurs prédéfinis et met en place une double-authentification par OTP.)
- Met en place un firewall basique (iptables ne filtrant que l'input).
- Met en place knockd.
- Met en place un honeypot ssh basique.
- Met en place fail2ban.

Si vous me suivez, vous aurez compris ici l'idée globale :
- Le serveur expose le minimum de ports (principe de base de la sécurité). tous les autres sont droppés.
- Le port ssh (22) est ouvert, mais conduit vers un container spécialement prévu faisant croire au hacker qu'il est sur le serveur alors qu'il est isolé dans un environnement prédéfini.
- Le "vrai" port ssh lui, est fermé par défaut et ne s'ouvre que si le serveur reconnais la séquence prédéfinie. Evidemment, elle ne s'ouvre que pour l'IP qui a donné la bonne séquence.
- Une fois ouvert, l'utilisateur doit fournir, en plus de son mot de passe, un code OTP géré par google authenticator et disponible par une application sur smartphone.
- Si l'utilisateur donne trois mots de passe erronés, son IP est bannie pour 1h.

J'ai choisi délibérément de ne pas passer par une clé ssh ( ouhouuuuuuuuuu le vilain ! ) car je trouve plus facile d'utilisation la méthode que j'ai choisie :
- Il est facile de se souvenir de la séquence du port-knocking.
- On a toujours son smartphone sur soit.

Les clés ssh elles, doivent être stockées en sécurité et ne sont pas forcément accessible à tout moment.
Alors certes, ce serait encore plus sécurisé avec des clés (Pour ceux qui y tiennent, on peut très facilement rajouter les clés à tout ce qui est déjà mis en place ici !), mais est-ce vraiment nécessaire ?
Un mot de passe + OTP est déjà qualifié d'authentification forte. Ici, je rajoute le pot de miel, le port caché, et le ban au bout de 3 essais erronés sur le vrai port.

A vous de voir, mais je pense que si vous mettez tout en place tel que je le dit et que vous vous faites quand même pirater, alors c'est que le gars en face n'est pas le premier script-kiddie venu et qu'il vous en voudra personnellement !
Libre à vous ensuite de creuser les sujets et de vous amuser comme vous voudrez.

Pour vous donner une idée de l'ambiance, voici le nombre de tentatives de connexions sur le port 22. Plus de 180k en tout juste 3 heures :
2500# docker logs ssh-honeypot_droberson | wc -l
181951

Mode d'emploi :
- Ouvrez DEUX terminaux sur votre serveur.
- Vérifier et adaptez les quelques variables en début de script.
- Exécutez le.
- Quand le script vous le demande, allez sur le second terminal et générez le code OTP avec l'utilisateur qui aura le droit de ce connecter avec la commande :
google-authenticator
- Flashez le QR Code et notez les codes de secours.
- Pour ceux qui ont la flemme de tout lire, séquence de réponses rapides : y / y / n / y
- Revenez sur le premier terminal et validez en tapant "yes" suivis de la touche "entrée".
- Ouvrez un 3ème terminal et tentez une connexion (pensez à installer knockd 🙂 en remplaçant l'ip, le port et la séquence par les votre :
knock IP_DU_SERVEUR -v 7000 8000 9000 10000 11000 && ssh -p 42069 utilisateur@IP_DU_SERVEUR
- Il doit vous demander le code OTP. Rentrez le lui et... magie !

Une fois le processus validé, vous pouvez tout quitter sereinement 🙂

Avant de lancer un grand "GO, vous pouvez l'utiliser les yeux fermés !", j'aimerai avoir les retours de quelques personnes qui ont les moyens techniques et les connaissances nécessaires pour le tester.
Non pas que je ne suis pas sûr de moi, mais il peut toujours y avoir des cas particuliers à prendre en compte.

https://github.com/zerpex/scripts/blob/master/server/securize_new_server.sh

Notes techniques :

  • Actuellement, si le firewall ne bloque pas l'output, c'est à cause de docker. Je n'ai pas encore trouvé de façon totalement propre et transparente de le gérer en le désactivant dans docker.
    Pour les connaisseurs, les commandes commentées dans la section iptables fonctionnent seulement dans un environnement simple où les containers sont "seuls". Dès qu'on a une architecture un peu plus compliquée avec des réseaux virtuels type backends/frontends, il faut rajouter des forwards à la main et ça ne me plait pas. Je cherche une solution qui gère ces cas de manière transparente... Oui, c'est un appel aux idées 😉

  • Le container "ssh honeypot" rempli parfaitement son rôle, mais j'aimerai trouver un "vrai" honeypot. Un truc qui fasse croire à un hacker qu'il est vraiment sur le serveur quoi. Je n'ai pas eu le temps de chercher autant que je voudrai, mais je suis certain que ça existe. Alors avant d'écrire le mien, si quelqu'un a une piste, je prend 😉

  • Commande simple pour vérifier si le container "ssh honeypot" a été compromis :
    docker diff ssh-honeypot_droberson
    Si cette commande vous affiche plus de 2 lignes, alors il y a eu compromission. Vous pouvez soit prendre le temps d'analyser tout ça, soit simplement détruire le container et le recréer :
    sudo docker run -d -m 256m --cpus=".5" -p 22:22 --name ssh-honeypot_droberson txt3rob/docker-ssh-honey

Voili voilou.
z.

    Je prend évidemment aussi des avis critiques sur la méthode et d'éventuelles suggestions pour améliorer le tout !

    Je trouve ca vraiment bien, bravo pour l'initiative (meme si je n'ai pas encore teste).
    L'idee du honeypot ssh me parait egalement super, j'avais jamais pense a quelque chose de semblable, mais ca me dit bien de mettre ca en place...
    Je suis le genre de personne qui prefere eviter les scripts tous faits, pas parce qu'ils ne feraient pas bien le boulot ou parce que je n'aurais pas confiance, mais plutot parce que je prefere tous faire "a la main", comme ca de une, j'apprends quelque chose et de deux, je sais exactement ce que j'ai fais sur le serveur et comment.
    Par contre pour les personnes qui veulent un serveur securise sans trop se prendre la tete, ca peut etre pas mal.
    En ce qui me concerne, ton post m'a permis d'apprendre le "concept" de honeypot (que je n'avais pas imagine). Merci.

    J'espere que quelqu'un ici aura l'utilite de ton script 🙂

    • zer a répondu à ça.

      zer Je vais l’essayer demain, une question me viens d'avance à l’esprit :

      # Set users (separated with a space) that will have the right to log in through ssh :
      SSH_USER="zer"

      si par la suite on veut rajouter un autre user, on relance le script ?

      On tout cas l’ensemble m'a l'aire bien pensée/conçue, à voir

      • zer a répondu à ça.

        Malakai Merci, et je partage parfaitement ton point de vue.. Je fais pareil : ces scripts, je les écris avant tout pour moi, mais s'ils scripts peuvent servir à d'autres, tant mieux 🙂

        Le honeypot est un vieux concept dans l'informatique, et "normalement" très poussé puisqu'on peut aller jusqu'à construire tout un faux réseau avec différents serveurs et de fausses données. Le but est de faire croire au pirate qu'il a réussi son coup alors qu'il repart avec des informations fausses 🙂

        Celui que j'ai intégré est extrêmement basique puisqu'il se contente de loguer les tentatives de connections ssh.

        Je travaille actuellement sur un plus poussé (crowrie pour les connaisseurs), mais je n'ai pas encore de solution simple à intégrer à mon script, donc je laisse le basique qui fait juste ce que je lui demande pour le moment !

        Et même si tu n'utilises pas mon script, rien que le fait qu'il ai pu t'apprendre quelque chose me satisfait 😉

        Erusaris Merci !

        En l'état, ce script est prévu pour être exécuté une seule fois car je n'ai pas encore intégré de test pour vérifier si des éléments sont déjà installés et configurés... à rajouter pour la version "finale" pour tout le monde 🙂

        Tu me fais penser que ça peut-être dangereux et que je ne l'ai pas précisé... Honte à moi !
        Pour le moment, ce script nécessite :
        - Un serveur basé sur debian
        - Docker
        - qu'il n'y ai pas de firewall actuellement

        Désolé, comme j'ai fais mes tests sur un scaleway vierge que je ré-installai entre chaque tests, j'ai été trop rapide sur ce point. Je vais donc rajouter des contrôles asap.

        Pour rajouter un utilisateur par la suite, il suffit de le rajouter son nom dans la ligne AllowUsers dans /etc/ssh/sshd_config et de lui faire éxécuter google-authenticator pour générer un QR code.

        En attendant d'avoir le temps de mettre en place tous les tests/savegardes à intégrer, et pour éviter des déconvenues, j'ai simplement rajouté un warning avec demande de confirmation en début de script.

        Pas mal ce script, il a l'air simple et efficace 😉

        Pas de portsentry ?

        Bien vu l'utilisation de debconf-set-selections 😉

        Quelques notes sur ton script

        • Pour vérifier que ce soit un serveur debian, perso je sourcerai /etc/os-release et tu vérifies que $NAME et pour savoir si Docker est installé, perso j'utilise cette fonction que j'ai écris :
        # Check if a package is installed
        # $1 = Package to check
        # 0 = No
        # 1 = Yes
        is_package_installed() {
            if [[ ! -z $1  ]]; then
                echo $(dpkg-query -W -f='${Status}' $1 2>/dev/null | grep -c ' installed')
            fi
        }
        • PS: Le contenu de os-release sur un serveur Debian
        PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
        NAME="Debian GNU/Linux"
        VERSION_ID="9"
        VERSION="9 (stretch)"
        ID=debian
        HOME_URL="https://www.debian.org/"
        SUPPORT_URL="https://www.debian.org/support"
        BUG_REPORT_URL="https://bugs.debian.org/"
        • Je vois que tu modifies le PermitRoot de prohibit-password en no, y'a pas tellement d'intérêt à ça. Dans tous les cas, si tu n'as pas de key, t'es pas autorisé à te connecter, donc c'est bon 😃

        • Fais un test que tu exécutes bien le script en root et vire tous les sudo (Par exemple, j'ai pas sudo d'installé sur mon serveur)

        sudo /etc/init.d/ssh restart

        Soit moderne, passe par systemctl :p (Pareil pour knockd)

        • Un truc que j'ai pas compris, tu changes le port SSH, mais tu ne l'ajoutes pas aux ports ouverts ?

        J'ai finis mes remarques o/

        • zer a répondu à ça.

          BXT Merci pour ces remarques et la fonction de test, je vais intégrer ça 🙂

          Concernant portsentry, je ne connaissais pas... et effectivement, ça complète bien le reste. Comme quoi c'est toujours utile ce genre de threads, merci !

          Tu as raison pour le PermitRoot. Il faudrait que je prenne plus large et remplace juste la ligne sur 'PermitRootLogin' histoire de prendre en compte les cas où il est sur 'yes' aussi.

          Concernant le port que je n'ouvre pas dans le script, c'est normal vu que c'est knockd qui le gère. Et avec les règles que j'ai mises par défaut, la session en cours ne sera pas coupée, donc autant le fermer, non ?

          z.

          Ah ok, je n'ai jamais mis enn place de knockd, mais ça semble logique ce que tu dis 😃

          Pour ton PermitRoot, tu peux te baser sur cette commande :

          sed -i 's/^plugins=(.*)$/plugins=(git common-aliases docker docker-compose)/' ~/.zshrc
          10 jours plus tard

          MAJ du script :

          • Ajout de portsentry.
          • "service" remplacé par "systemctl" :p .
          • PermitRootLogin remplacé seulement si positionné à "yes".
          13 jours plus tard

          Salut,
          Je viens de réinstaller mon serveur. Il est maintenant temps de passer à la partie sécurité ! Le problème c'est que je ne maitrise absolument pas cette partie (déjà que c'est bof pour le reste...)
          Est-ce que ton script est 100% fonctionnel et surtout est-ce qu'il y a des risques de "détraquer" mon serveur en sachant par exemple que j'ai déjà configurer un nouveau port ssh, bloqué l'utilisateur root et mis en place logwatch ?
          Autre chose, vu que c'est un script j'ai peur que si j'ai un soucis je ne sache pas du tout ou chercher ! Est-ce que tu as mis en place des configurations particulière ou est-ce que c'est "général" (je ne sais pas si je suis clair, en gros il faudrait que j'ai une chance de retrouver mon problème en cherchant sur le net).

          Voilà, beaucoup de question mais j'hésite à me lancer tête baissée dans un script

          Merci d'avance

          P.S : J'ai aussi mis en place un système de clés...

          Répondre…