06 Jan

RsyncScan – Identifier les modules accessibles anonymement

Description

J’avais une liste assez longue de serveurs Rsync sous la main et avec Nmap je voulais m’assurer qu’aucun module (~répertoire) n’était accessible « anonymement » (comme lors d’un pentest par exemple).

Mais avec Nmap je ne pouvais uniquement voir les modules ou lancer un bruteforce (test de couples login/mot de passe) mais c’est tout. Je cherchais le moyen d’identifier si on pouvait accéder à ces modules et lire le contenu (lecture seule à minima), à la manière du script NSE smb-enum-shares pour le protocole SMB.

N’ayant pas de solution, j’ai crée ce script Bash qui est capable d’analyser une grande liste de hosts (adresses IP ou noms d’hôtes) en parallèle (réglable) et d’identifier ceux qui utilisent Rsync pour la synchronisation à distance :

Paramètre « p » pour le mode parallèle
Mode séquentiel par défaut

Il permet de parcourir les modules visibles et tente de se connecter sur chacun d’eux de manière anonyme pour identifier ceux qui sont accessibles. Tous les serveurs et modules accessibles sont ensuite enregistrés dans un fichier texte (commande Rsync complète pour validation) :

Serveurs et modules vulnérables/accessibles
30 Juil

Déployer un scanner sur OpenStack (API OVH)

Déployer et lancer automatiquement le scanner MassVulScan depuis des instances OpenStack du Cloud Public d’OVH.

Introduction

Les entreprises, notamment, devraient s’assurer de ne pas exposer sur l’Internet des ports réseaux de manière indésirable.

Dans ce but, j’ai voulu aller plus loin avec le scanner MassVulScan en permettant d’effectuer un scan depuis n’importe où sur l’Internet sans devoir louer plusieurs serveurs chaque mois et tout réinstaller à chaque fois.

En effet, lorsque l’on utilise continuellement la ou les mêmes adresses IP source pour scanner son réseau on risque de masquer certaines failles de sécurité : certaines autorisations (théoriquement) accordées qu’à celles-ci, utilisation de mécanismes de sécurité comme fail2ban qui les bloqueraient..

Du coup, malgré des scans réguliers, certains ports peuvent rester ouverts longtemps à tout va sans que l’on s’en aperçoive.. je parle par expérience !

J’ai donc cherché et réfléchi à une solution qui répondrait à ce cahier des charges :

  • Facilité, simplicité et rapidité du déploiement
  • Lancement automatique d’un scan complet
  • Faible coût de fonctionnement et ne payer qu’à l’usage
  • Fournisseur Cloud disposant de plusieurs Data Center répartis sur la planète
  • Fournisseur Cloud tolérant cette pratique

Solution

Voici le script Bash que j’ai développé qui répond à mes besoins : osic4MVS

osic4MVS a.k.a. OpenStack Instance Creation For MassVulScan

J’ai retenu le fournisseur de Cloud OVH que j’utilise de longue date, meilleur rapport qualité/prix selon moi. La facturation du Cloud Public est claire (à la demande et sans coûts cachés), la tarification est attractive (0.03$ CAD pour mes scans sur BHS3), et leur interface Web est simple et efficace.

Le script Bash va donc s’appuyer sur l’API d’OVH pour déployer en quelques minutes un instance OpenStack sur laquelle sera installée MassVulScan.

Prérequis

Script

Le script Bash ne fonctionne que sur les OS de la famille Debian.

Le serveur à partir duquel sera lancé ce script devra avoir accès à l’Internet, plus précisément :

  • ICMP Echo Reply (ping)
  • SSH port TCP 22

Voici la liste des paquets à installer, suivant si vous utilisez Python 2.x ou Python 3.x :

apt update
apt install python-openstackclient s-nail screen dnsutils ipcalc netcat

Ou :

apt update
apt install python3-openstackclient s-nail screen dnsutils ipcalc netcat

Fournisseur OVH

Vous devez bien-sûr posséder un compte OVH et créer votre projet Cloud Public : OVHCloud

Ici mon projet s’appelle tout simplement « SCANS » :

Mon projet « SCANS »

Ensuite il faut créer un utilisateur OpenStack, rendez-vous dans : Public Cloud / Project Management / Users & Roles

Comptes utilisateurs et rôles

Ajoutez un nouvel utilisateur (avec une description) en lui affectant le rôle « Compute Operator » :

Ce rôle est suffisant pour le fonctionnement du script

On ne peut pas choisir le nom d’utilisateur qui est généré aléatoirement sous la forme « user-XXXXXXXXXXXX », tout comme le mot de passe. Voici notre nouvel utilisateur créé pour notre démonstration :

Nouvel utilisateur en cours de création – Notez bien le mot de passe

N’oubliez pas de noter le mot de passe ! En cas d’oubli, cliquez sur les trois petits points à droite du compte utilisateur pour accéder aux options et en regénérer un nouveau :

Les options du compte utilisateur

Profitez-en pour télécharger de suite le fichier OpenStack RC qui correspond en fait à vos variables d’environnement, il nous sera utile pour la suite. Lors du téléchargement on vous demandera sur quelle région ( = quel Data Center et pays) ce fichier s’appliquera, j’ai choisi ici l’Amérique du nord et leur centre Canadien BHS3 :

Sélectionner une région ou plutôt un centre de données attaché au fichier OpenStack

Rendez-vous sur l’interface Web Horizon pour gérer votre instance OpenStack : Public Cloud / Management Interfaces / Horizon

Choisissez bien votre région, ici BHS3 :

Choisir la région, ici BHS3, Canada

Ensuite, nous allons générer une paire de clés SSH : Project / Compute / Key Pairs

Créez votre paire de clés comme ici, elle se nommera « demo » :

Création d’une paire de clés SSH (privée/publique)

Une fois la création terminée, votre clé SSH privée sera automatiquement téléchargée, comme ici :

Ma clé privée pour la démonstration

C’est terminé, nous avons donc nos quatre éléments importants pour le script Bash :

  1. Un compte utilisateur OpenStack chez OVH Cloud Public
  2. Un fichier OpenStack RC contenant nos variables d’environnement
  3. Une paire de clé SSH
  4. Le nom de notre clé SSH publique

Installation et utilisation

Installation

L’installation du script Bash est très simple :

git clone https://github.com/choupit0/osic4MVS.git
cd osic4MVS
chmod +x osic4MVS.sh && chmod +x deploy.sh

Ensuite, afin d’automatiser l’utilisation nous allons indiquer le mot de passe directement dans le fichier OpenStack RC. Commentez les lignes 25 à 27 puis ajoutez-en une nouvelle contenant le mot de passe de l’utilisateur OpenStack, comme ceci :

On ajoute le mot de passe de l’utilisateur

Sans cela, il vous sera demandé de saisir le mot de passe plusieurs fois durant le déroulement du script Bash.

Après, déposez votre clé privé et votre fichier OpenStack RC dans un endroit sécurisé et protégez-les comme ici :

chmod 600 openrc.sh
chmod 600 demo.pem

Lecture/écriture pour le propriétaire uniquement, cela peut-être le compte « root », utilisez ensuite « sudo » pour appeler le script Bash par exemple.

Utilisation

On y arrive !!!

Un beau menu vous attend 🙂

Vous aurez besoin de préciser quatre arguments pour pouvoir lancer le script Bash :

  1. Le chemin vers le ou les fichiers contenant les noms d’hôtes et/ou adresses IPv4, format CIDR
    • Un fichier obligatoire : celui contenant les hosts à scanner
    • Un fichier optionnel : celui contenant les hosts à exclure
      • Pour exclure les passerelles de vos opérateurs par exemple
  2. Le chemin vers votre fichier OpenStack RC
  3. Le chemin vers votre clé SSH privée
  4. Le nom de votre clé publique SSH

Le script doit être lancé avec les droits « root » (avec « sudo » ou non), comme ceci :

./osic4MVS.sh -f scanme-nmap -r conf/openrc.sh -k keys/demo.pem -p demo

Et voilà le résultat, ici l’exécution complète du script, en 4 minutes et 20 secondes :

Script Bash exécuté en moins de 5 minutes !!!

Rapports

Voici les rapports générés suite au scan du site « scanme.nmap.org » utilisé dans la démonstration :

Suivre le déroulement

Après avoir vérifié les arguments passés, le script Bash effectuera les étapes suivantes :

  1. Vérifier l’accessibilité du Cloud Public d’OVH
  2. Vérifier les instances OpenStack existantes
  3. Analyse du ou des fichiers sources (pour ne garder que les entrées valides)
  4. Création de l’instance
  5. Attente de la disponibilité du serveur (ping + SSH)
  6. Déploiement du scanner MassVulScan
  7. Envoi du ou des fichiers hosts
  8. Lancement du scan MassVulScan : Masscan puis Nmap + vulners.nse
  9. Récupération des rapports en local via SCP (si il y a lieu)
  10. Suppression des sessions screen et OpenStack

Screen

Il vous sera possible de suivre l’installation et le scan en live si vous le souhaitez à travers une session screen. Comme ici avec le précédent scan de démonstration :

Session screen pour le suivi ou surveillance

En l’occurrence, vous aurez juste à taper dans un second terminal (droits « root ») :

screen -r scan_2021-07-30_121820

Et pour sortir sans fermer la session, faites au clavier :

CTRL + A et D

Courriels

Pour s’assurer du bon fonctionnement du script et/ou si vous prévoyez de lancer un gros scan de plusieurs heures, vous avez la possibilité de renseigner une ou plusieurs adresses courriels et un serveur SMTP(S).

Vous serez avertis à trois moments différents :

  1. Au démarrage effectif du scan
  2. A la fin du scan vous recevrez les rapports (si il y a lieu)
  3. Une fois la session screen et instance OpenStack supprimées

Il vous suffit pour cela de modifier les variables suivantes dans le script :

  • smtp_server = serveur SMTP(S) à utiliser
  • from_address = adresse email d’émission/retour
  • recipient = liste des destinataires (séparer par une virgule », »)
  • auth_user_pass = utilisateur et mot de passe encodés dans un URI (si besoin)

Un exemple ci-dessous pour l’encodage dans un URI :

root@HTB:~/osic4MVS# printf 'urlcodec encode demo@ovh.com' | s-nail -#
demo%40ovh.com
root@HTB:~/osic4MVS# printf 'urlcodec encode *ThisIsMyGreatPassW0rd!' | s-nail -#
%2AThisIsMyGreatPassW0rd%21

Il suffit d’assembler les deux informations en ajoutant deux point « : » entre les deux, comme ici :

auth_user_pass="demo%40ovh.com:%2AThisIsMyGreatPassW0rd%21"

Des exemples ci-dessous de courriels envoyés depuis les serveurs d’OVH :

Exemples de courriels envoyés durant la vie du script

Conclusion

J’utilise régulièrement cet outil (professionnellement) pour m’assurer de ne pas laisser de ports ouverts par inadvertance, surtout lorsque l’on travaille à plusieurs. Il suffit d’une erreur humaine ou d’appliquer une mise à jour pour se retrouver exposer sans le vouloir.

Vous pouvez programmer un lancement hebdomadaire via une tache cron, comme ici toutes les fins de semaine :

0 0 * * 0 bash /home/superuser/audit/ovh/osic4MVS.sh

Et avec les courriels on peut s’assurer du bon fonctionnement et on récupère les rapports facilement.

N’hésitez pas à laisser vos commentaires ! Merci d’avoir lu jusqu’au bout 😉

07 Jan

Calculer la bande passante consommée des interfaces réseaux d’un Fortigate

Introduction

Je cherchais le moyen d’obtenir à intervalles réguliers la bande passante consommée (en entrée et sortie) de chacune de mes interfaces réseaux, notamment celles « virtuelles », à savoir des VPN (IPSec), sur mes firewalls.

Pour une architecture réseau en étoile (Hub and spoke en anglais) le plus simple est bien-sûr d’interroger l’équipement central qui s’interconnecte avec chacun des sites distants. Ce qui était mon cas.

L’objectif étant au final d’obtenir un fichier source avec toutes les valeurs me permettant ainsi d’alimenter un script pour ensuite générer une carte d’utilisation de bande passante (network weathermap en anglais) rafraîchie toutes les 5 secondes. Comme ci-dessous :

Script Bash

Explications

Vous trouverez plus bas le script Bash que j’ai utilisé pour récupérer les données via SNMP et les traiter. Comme les compteurs des interfaces réseaux s’incrémentent sans cesse, l’idée est de prendre les valeurs à l’instant T puis de les reprendre à l’instant T + 5 secondes.

Puis par un simple calcul on obtient la bande passante consommée en entrée et sortie. Enfin, en appelant régulièrement le script (crontab ou boucle), vous obtiendrez différentes valeurs qui pourraient alimenter d’autres scripts comme PHP Weathermap par exemple, que j’utilise.

Pensez à mettre les bons paramètres (variables) avant de lancer le script :

  • host = hostname/IPv4 de votre firewall
  • community = nom de la communauté SNMPv2

Bien-sûr, au préalable vous devez configurer SNMPv2 sur votre firewall (https://kb.fortinet.com/kb/documentLink.do?externalID=FD45755) et donner les droits en lecture (uniquement) au serveur qui l’interrogera.

J’utilise SNMPv2 dans mon cas car les données récupérées ne sont pas sensibles et il suffit de bien configurer les droits.

J’utilise la MIB standard (ISO/CCITT) pour interroger le firewall, ce qui est le cas avec beaucoup de fournisseurs/marques avec laquelle ils sont compatibles.

Par contre, il était important de prendre les compteurs 64 bits (ifHCInOctets/ifHCOutOctets) et non 32 bits (ifInOctets/ifOutOctets), au risque de voir le compteur repartir à zéro rapidement, surtout si vous avez de gros liens/débits.

En sortie vous aurez ce type d’affichage :

VPN-XXX-C-WS-3G 0 2
VPN-XXX-E-WS-3G 0 2
VPN-XXX-C-ES-OR 1637 1360
VPN-XXX-E-ES-OR 1391 370
VPN-XXX-C-ES-O3 0 6
VPN-XXX-E-ES-O3 0 2
VPN-XXX-C-OU-OR 2047 480
VPN-XXX-E-OU-OR 408 3164
VPN-XXX-C-OU-O3 14 434

Pour finir, vous aurez juste à retirer le nom de fichier « bandwidth.txt » de la ligne 62 pour le générer et le conserver sur disque pour l’intégrer avec un autre script si besoin.

Code source

Voici le script en question, suffisamment commenté je pense :

Sinon, vous pouvez le télécharger ci-dessous :

Conclusion

Voilà, j’espère que ce sera utile à certains d’entre vous. A noter que ce script Bash devrait pouvoir fonctionner tel quel avec d’autres équipements que les Fortigate.

Pour d’autres types de réseaux ou besoins, on pourrait très bien imaginer avoir une liste de firewall en entrée qui serait parcouru et ainsi chacun serait interrogé avec ce script en parallèle pour gagner du temps. Je ferai un article là dessus aussi je pense.

Dernière chose, pour ceux qui s’interrogent sur la mise en forme du code dans l’article, j’ai utilisé l’excellent site : https://carbon.now.sh/

20 Fév

MassVulScan.sh, identifiez rapidement les ports ouverts sur votre réseau et les hosts vulnérables

Introduction

Il y a quelques temps, je cherchais le moyen d’identifier rapidement et efficacement tous les ports accessibles sur différents sites distants connectés à Internet (la quantité de hosts publics représentait un /24). Et je voulais m’assurer, par la même occasion, qu’il n’y avait aucun host qui exposait un service comportant des failles connues.

Jusqu’à présent j’utilisais indépendamment différents outils comme les classiques, mais efficaces, Masscan et Nmap pour obtenir ce que je voulais. Après traitement des résultats, j’exportais cela dans un fichier texte ou un bête fichier HTML. C’est plutôt fastidieux et le processus mal optimisé.

J’ai commencé à chercher un outil qui permettait d’identifier rapidement les ports ouverts et de ne scanner que les hosts ayant un ou plusieurs de ces ports ouverts (et que ceux-ci). Le tout en traitement parallèle afin de gagner du temps. Et pour finir, qu’un beau rapport soit généré, facilement exploitable. Mais n’ayant pas trouvé ce que je cherchais, j’ai décidé de le développer moi-même (en bash) et le voici ! MassVulScan.sh !

L’idée est de combiner la puissance du scanner Masscan pour trouver des ports ouverts, l’efficacité du scanner Nmap pour identifier les services ouverts et leur version, et enfin le script NSE vulners.nse pour identifier les vulnérabilités potentielles (CVE).

Pour accélérer la phase de reconnaissance de Masscan, une phase préalable de découverte permet d’identifier rapidement les hosts en ligne à scanner.

Une fois la phase de reconnaissance terminée, le fichier de sortie est traité afin de trier et rassembler tous ports à scanner par host. Ce qui permet d’optimiser les scans de Nmap. Il y aura autant de sessions Nmap qu’il y aura de hosts à scanner avec des ports ouverts (deux sessions différentes par host si des ports sont découverts avec TCP et UDP).

Pour finir, deux rapports seront générés, l’un concernant les hosts ayant de potentielles vulnérabilités et le second concernant l’exhaustivité des hosts ayant des un ou plusieurs ports ouverts.

Téléchargement et installation

Vous trouverez tous les détails sur Github pour l’installation : https://github.com/choupit0/MassVulScan

Certains pré-requis seront nécessaires pour son fonctionnement, dont voici la liste :

  • apt : build-essential git wget tar libpcre3-dev libssl-dev libpcap-dev net-tools locate xsltproc ipcalc dnsutils netcat
  • git : masscan (min v1.0.5) et vulners.nse
  • source : nmap (min v7.70)

Pour ceux qui utilisent un OS de la famille Debian, leur installation ou mise à jour sera automatique 🙂

Paramètres

  • -f | –include-file : fichier des hosts à scanner, IP ou nom d’hôtes (paramètre obligatoire)
  • -x | –exclude-file : fichier des hosts à exclure du scan
  • -i | –interactive : choix des ports à scanner, vitesse (Masscan) et script NSE
  • -c | –check : détection des hosts en ligne
  • -a | –all-ports : scan exhaustif de tous les ports (1-65535, TCP/UDP), à 2k paquets/seconde et script vulners.nse
  • -r | –report : conserver la liste des adresses IP ayant un ou plusieurs ports ouverts
  • -n| –no-nmap-scan : détecter uniquement les ports ouverts

Explications

Le seul paramètre obligatoire est le fichier en entrée (-f | –include-file) qui doit inclure la liste des hosts ou sous-réseaux à scanner. J’ai fait ce choix car dans mon cas, de nombreux sous-réseaux (privés ou publiques) sont scannés, c’est plus simple à gérer avec des commentaires pour chacun.

Par défaut, seuls les 1000 ports les plus populaires seront scannés à une vitesse maximum de 2500 paquets par minute (pour Masscan) avec le script vulners.nse.

Il est aussi possible d’exclure des hosts ou sous-réseaux (-x | –exclude-file), même format de fichier que le fichier en entrée.

A noter que le script est compatible avec des adresses IP ou des noms d’hôtes.

Un autre paramètre peut être ajouté (-c | –check) si l’on souhaite au préalable identifier les hosts qui sont en ligne avant de lancer la phase d’identification des ports ouverts avec Masscan. Cela peut être un gain de temps considérable pour Masscan.

Une autre option disponible (-a | –all-ports) permet d’indiquer au script de scanner la totalité des ports de 1 à 65535 pour les protocoles TCP et UDP à une vitesse maximum de 2000 paquets par minute (pour Masscan). Attention, sur certains réseaux cela peut être trop élevé, passez par le mode interactif dans ce cas (ci-dessous). En effet, il peut y avoir des perturbations et vous risqueriez de perdre le contrôle… je vous suggère d’utiliser la commande « timeout » si vous n’êtes pas sûr de vous au début, c’est bien pratique.

Un autre paramètre est le mode interactif (-i | –interactive) qui vous permet de choisir la liste des ports à scanner ainsi que la vitesse de scan de Masscan et le script NSE (nmap) à utiliser.

Fonctionnement et particularités

Interfaces réseaux

J’ai commencé récemment à m’amuser sur le site de pen-testing https://www.hackthebox.eu, j’ai ainsi eu l’occasion de tester mon script et de l’améliorer pour le coup.

Il faut savoir que pour accéder aux différents labs, un VPN est monté avec OpenVPN. Dans mon cas, une nouvelle interface « tun0 » est créée avec une IPv4 dans le subnet 10.10.14.0/23, ainsi qu’une route pour atteindre les différents serveurs virtuels (10.10.10.0/24 via 10.10.14.1).

Le problème c’est que Masscan, qui est appelé au début du script, n’utilisera par défaut que l’interface qui possède la route par défaut, en l’occurrence celle d’Internet (« eth0 » par exemple)… du coup impossible de scanner les serveurs.

Le script détectera donc si plusieurs interfaces réseaux existent et vous demandera de sélectionner celle à utiliser pour atteindre les hosts. Pas de problèmes pour Nmap qui gère cela correctement : le scan d’un côté pour identifier les services (interface « tun0 ») et la récupération des CVE associées via une API chez https://vulners.com (interface « eth0 »).

Masscan -> Nmap, passage de relais

Dans un soucis d’efficacité, le script rassemblera tous les ports identifiés comme ouvert par host. C’est à dire qu’une fois que Masscan aura identifié tous les ports ouverts, le script fera un tri pour que Nmap puisse lancer la reconnaissance de services uniquement sur les ports ouverts. Exemple de fichier intermédiaire trié et préparé pour Nmap :

Fichiers d’entrées TCP et UDP pour Nmap

Nmap, plus rapide avec le parallélisme

Toujours dans un soucis de performance, le script lance autant d’instances Nmap qu’il y a de hosts à scanner, elle fonctionnent toutes en parallèles :

Lancement des scans Nmap

Ce qui fait que le temps maximum d’exécution de Nmap dépendra donc uniquement du scan qui aura pris le plus de temps, et non du temps total des scans Nmap si nous étions en mode « série » (à la queue leu-leu).

Il y a une gestion de queue avec une limite de 50 scans en parallèles maximum (variable à changer si besoin). Dès qu’un scan est terminé, un autre prend le relais.

Identification des CVE avec vulners.com

Pour l’identification des CVE, le script s’appuie donc sur le site de https://vulners.com via une API. Il en existe d’autres mais c’est le plus fiable que j’ai trouvé. De plus, il trie directement les CVE par ordre de criticité, ce qui est bien pratique :

Exemple de vulnérabilités identifiées et triées pour un host donné sur le port SMB/SAMBA

Le site fait un gros travail pour fournir des données les plus à jour possibles.

Rapports

Si après analyse des hosts ont été détectés comme « potentiellement » vulnérables, un fichier au format TXT sera généré comportant uniquement ceux-ci. Cela permet de se concentrer dessus (avec tentative de résolution reverse DNS) :

Rapport sur les hosts vulnérables

Ensuite, un second fichier au format HTML sera cette fois généré comportant l’exhaustivité des hosts identifiés avec des ports ouverts. Pour ce dernier, j’utilise l’excellent template Nmap XSL avec bootstrap « nmap-bootstrap.xsl » qui produit de beaux rapports et qui surtout permet de filtrer et trier nos résultats :

Rapport Nmap avec le template « nmap-bootstrap.xsl » sur les hosts ayant des ports ouverts

Performance

Pour évoquer la performance du script, un dessin vaut mieux qu’un long discours. Ci-dessous une capture d’écran du déroulement complet d’un scan dont voici les caractéristiques :

  • 235 hosts scannés
  • concernant 131068 ports (65534 ports tcp + 65534 ports udp)
  • à raison d’une cadence de 2500 paquets par seconde (Masscan)
  • puis 82 scans Nmap lancés en parallèles pour détecter les services actifs et vulnérabilités éventuelles
  • concernant 236 ports ouverts
  • et enfin génération des rapports
Seulement 03h30 pour scanner 235 hosts sur 131068 ports…

Il est toujours possible d’améliorer encore la vitesse d’execution du script en augmentant le nombre de paquets par seconde de Masscan, tout dépend de la qualité de vos liens Internet et de votre réseau interne.

Mais attention à ne pas perturber votre infrastructure, changez la valeur graduellement.

Mot de la fin

Voilà, j’espère que cet article vous donnera envie de tester mon script.

J’apporte régulièrement de nouvelles fonctions et cherche à l’optimiser constamment, je suis ouvert aux critiques et propositions d’amélioration.

Dernière chose, mon anglais n’est pas parfait, soyez indulgent ! (je parle du script).

Merci de m’avoir lu jusqu’au bout, j’attends vos commentaires maintenant 😉

05 Fév

Authentification RADIUS sous Linux OS Debian (PAM)

Introduction

Dans ce 1er article nous verrons ensemble comment nous authentifier sur un serveur Linux en nous appuyant sur le protocole RADIUS (pour Remote Authentification DIal-in User Service, protocole AAA).

Il s’agit plus d’une découverte du « système » PAM (Pluggable Authentication Modules) car son implémentation peut devenir relativement complexe. Il peut notamment permettre la mise en place de diverses stratégies et mécanismes d’authentification comme LDAP, kerberos, lecteur d’empreinte digital etc… PAM fait également office d’API, de librairie… Ce qui ouvre beaucoup de possibilités aux développeurs et différents langages de programmation.

Si vous utilisez déjà un serveur d’annuaire Microsoft pour authentifier vos utilisateurs en entreprise (Active Directory), l’intérêt sera de pouvoir se baser sur ce dernier pour authentifier de la même manière les linuxiens 😉

Cela permet de faciliter la gestion des utilisateurs (une seule base de données), d’augmenter le niveau de sécurité et d’apporter plus de confort à l’utilisateur final.

Nous nous attarderons un peu sur la partie débogage que je trouve intéressante.

Pré-requis

  • Un serveur RADIUS opérationnel avec les règles qui vont bien comme FreeRADIUS ou NPS Server de Microsoft
  • Un serveur Linux sur une architecture Debian assez récente (Debian 8 ou Ubuntu 16.04 par exemple)
  • Un compte utilisateur ayant un accès avec privilèges (via sudo ou root directement)
  • Un accès console SSH ou un terminal
  • Un éditeur de texte comme vi
  • Un accès Internet
  • Un serveur Active Directory Microsoft

Installation et configuration du module PAM

Important: Assurez-vous de garder un shell ouvert durant les opérations, afin de vous assurer de toujours avoir la main et de faire un rollback en cas de soucis

Nous installons la librairie RADIUS en premier lieu :

sudo apt-get update && sudo apt-get upgrade
sudo apt-get install libpam-radius-auth

Nous devons ensuite créer les comptes utilisateurs sur le serveur Linux. Ils doivent strictement correspondre au logon name c.-à-d. au champ « sAMAccountName » dans l’annuaire :

sudo useradd -s /bin/bash -m -G sudo admin

A noter que l’on ne créé pas de mot de passe pour cet utilisateur.

On modifie les propriétés du fichier de configuration de la librairie ainsi que les droits associés. Par sécurité, il ne doit appartenir qu’au compte root en lecture/écriture :

sudo chown root /etc/pam_radius_auth.conf
sudo chmod go-rwx /etc/pam_radius_auth.conf

On édite ce fichier de configuration et on ajoute notre serveur RADIUS dans la section adéquate :

sudo vi /etc/pam_radius_auth.conf
# server[:port] shared_secret      timeout (s)
#127.0.0.1      secret             1
[adresse IP du serveur RADIUS] :1812     [secret/mot de passe partagé]    60

Suivant la version de votre serveur RADIUS, vous devrez peut-être mettre le port UDP 1645 à la place de UDP 1812. A noter qu’il est préférable d’augmenter le timeout à 60 secondes, notamment si vous utilisez du 2FA. Pour laisser le temps aux usagers de se connecter si leur connexion n’est pas bonne.

Autorisons maintenant l’authentification par le protocole RADIUS en SSH. Nous allons pour cela éditer le fichier suivant et ajouter la ligne qui commence par « auth… » au tout début, juste avant le ligne « @include common-auth » :

sudo vi /etc/pam.d/sshd
# Standard Un*x authentication.
auth        sufficient     /lib/security/pam_radius_auth.so
@include common-auth

Petite explication sur cette ligne :

auth = permet la vérifier l’identité de l’utilisateur lors de la connexion

sufficient = cela indique que si le test d’authentification réussi (utilisateur existant dans l’annuaire et mot de passe correct), le traitement s’arrête là.

/lib/security/pam_radius_auth.so = chemin vers la librairie utilisée, RADIUS dans notre cas

En effet, ce fichier, et un fichier « PAM » de manière générale,  comprend un séquencement d’opérations qui sont traitées successivement sur conditions (échec ou réussite). Cela représente une « pile » de règles en quelque sorte.

Pour plus de détails et d’explications claires, je vous invite à vous rendre sur ce site : http://debian-facile.org/doc:systeme:pam

A ce stade, un administrateur linux pourra s’authentifier mais il n’aura pas de privilèges. On doit donc éditer le fichier suivant et ajouter la ligne qui commence par « auth… » au tout début, juste avant le ligne « @include common-auth » :

sudo vi /etc/pam.d/sudo
# Standard Un*x authentication.
auth        sufficient     /lib/security/pam_radius_auth.so
@include common-auth

Et enfin, on doit autoriser l’administrateur à changer de compte utilisateur si besoin. Aussi, on va donc éditer le fichier suivant et cette fois on ajoute la ligne qui commence par « auth… » en fin de fichier, juste avant le ligne « @include common-auth » :

sudo vi /etc/pam.d/sudo
# The standard Unix authentication modules, used with
# NIS (man nsswitch) as well as normal /etc/passwd and
# /etc/shadow entries.
auth        sufficient     /lib/security/pam_radius_auth.so
@include common-auth

La partie configuration est terminée. Passons à la phase de test !

Tests et débogage

Si tout va bien, vous devriez pouvoir vous connecter en SSH avec votre compte Active Directory et voir apparaître le prompt :

Last login: Wed Feb 7 14:25:01 2018 from mon_pc.mon_domaine.corp
admin@mon_serveur-01:~$

On vérifie que notre compte a bien les privilèges en appelant une commande non accessible pour un utilisateur sans droit :

admin@mon_serveur-01:~$ sudo ifconfig
[sudo] password for admin:
eth0 Link encap:Ethernet HWaddr 00:50:13:37:05:34
  inet addr:10.66.0.200 Bcast:10.66.0.255 Mask:255.255.255.0
  inet6 addr: fe80::250:56ff:fe85:6ffb/64 Scope:Link
  UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  RX packets:109443470 errors:0 dropped:1 overruns:0 frame:0
  TX packets:18550308 errors:0 dropped:0 overruns:0 carrier:0
  collisions:0 txqueuelen:1000
  RX bytes:10289511895 (9.5 GiB) TX bytes:2060556027 (1.9 GiB) 

De la même manière vous devriez être en mesure de passer root et changer d’utilisateur :

admin@mon_serveur-01:~$ sudo su (votre mot de passe)
root@mon_serveur-01:/home/admin#
admin@mon_serveur-01:~$ su root (mot de passe root cette fois)
root@mon_serveur-01:/home/admin#

En cas de soucis, vous avez la possibilité d’activer le mode debug. Pour cela, il faut ajouter le mot clé « debug » comme ici dans le fichier « /etc/pam.d/sshd » (mais applicable dans tout fichier « PAM ») :

auth sufficient /lib/security/pam_radius_auth.so debug

Assurez-vous ensuite que votre serveur log correctement les messages en mode « debug » dans un fichier de logs, qui est le mode le plus bavard.

Si ce n’est pas le cas, ajoutez ce fichier dans le répertoire rsyslog, service installé par défaut normalement (remplaçant de syslog, sinon installez-le avec « sudo apt-get install rsyslog« ) :

sudo vi /etc/rsyslog.d/80-debug.conf

Puis ajoutez ceci dedans :

$template debug-mode,"/var/log/%hostname%-debug.log"
*.* ?debug-mode

Cela aura pour effet de rediriger/d’écrire l’ensemble des messages du serveur dans un fichier qui aura comme nom le nom du serveur: mon_serveur-01-debug.log

Pour que le changement soit pris en compte, il faut relancer le service rsyslog :

sudo systemctl restart rsyslog.service

Ou suivant votre gestionnaire de système :

sudo service rsyslog restart

En enfin, affichez les logs à l’écran en temps réel grâce à la commande tail -f et en filtrant les messages :

tail -f /var/log/mon_serveur-01-debug.log | grep sshd

Ici j’ai rentré un utilisateur qui est inconnu sur le serveur Linux et dans l’Active Directory (j’ai retiré l’horodatage pour une meilleure lecture) :

sshd[31232]: Invalid user le_matou from 192.168.2.200
sshd[31232]: input_userauth_request: invalid user le_matou [preauth]
sshd[31232]: pam_radius_auth: Got user name le_matou
sshd[31232]: pam_radius_auth: Sending RADIUS request code 1
sshd[31232]: pam_radius_auth: Got RADIUS response code 3
sshd[31232]: pam_radius_auth: authentication failed
sshd[31232]: pam_unix(sshd:auth): check pass; user unknown
sshd[31232]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=mon_pc.mon_domaine.corp
sshd[31232]: Failed password for invalid user le_matou from 192.168.2.200 port 21962 ssh2
sshd[31232]: Connection closed by 192.168.2.200 [preauth]

On voit que le système détecte d’emblée que le compte utilisateur n’existe pas sur le serveur puis que le serveur RADIUS rejette l’utilisateur.

Un autre cas où cette fois l’utilisateur existe bien sur le serveur Linux (avec un mot de passe) mais pas dans l’Active Directory :

sshd[26457]: pam_radius_auth: Got user name le_matou
sshd[26457]: pam_radius_auth: Sending RADIUS request code 1
sshd[26457]: pam_radius_auth: Got RADIUS response code 3
sshd[26457]: pam_radius_auth: authentication failed
sshd[26457]: Accepted password for le_matou from 192.168.2.200 port 22070 ssh2
sshd[26457]: pam_unix(sshd:session): session opened for user le_matou by (uid=0)

Cela fonctionne mais grâce à l’authentification locale de PAM dans ce cas. Cela pourrait être utile en cas de défaillance ou d’inaccessibilité du ou des serveurs RADIUS configuré(s). Soit vous avez un compte utilisateur de « secours » (que vous conserveriez soigneusement dans votre KeePass 😉 ), soit vos utilisateurs utilisent un mot de passe « de secours », ce que je ne conseille pas.

Côté serveur RADIUS on verra ce type d’événement lors d’un rejet (ici une log d’un serveur NPS de Microsoft, le client utilise un PC sous Windows 10 donc pas de client NAP) :

User:
Security ID: S-1-0-0
Account Name: le_matou
Account Domain: DOMAINE
Fully Qualified Account Name: DOMAINE\le_matou
Client Machine:
 Security ID: S-1-0-0
 Account Name: -
 Fully Qualified Account Name: -
 OS-Version: -
 Called Station Identifier: -
 Calling Station Identifier: mon_serveur-01.mon_domaine.corp

NAS:
 NAS IPv4 Address: 127.0.0.1
 NAS IPv6 Address: -
 NAS Identifier: sshd
 NAS Port-Type: Virtual
 NAS Port: 8206

RADIUS Client:
 Client Friendly Name: SERVER_IN_10.66.0.0/24
 Client IP Address: 10.66.0.200

Authentication Details:
 Connection Request Policy Name: Request SERVER_IN_10.66.0.0/24
 Network Policy Name: -
 Authentication Provider: Windows
 Authentication Server: mon_serveur_RADIUS.mon-domaine.corp
 Authentication Type: PAP
 EAP Type: -
 Account Session Identifier: -
 Logging Results: Accounting information was written to the local log file.
 Reason Code: 16
 Reason: Authentication failed due to a user credentials mismatch. Either the user name provided does not map to an existing user account or the password was incorrect.

Il existe également un petit utilitaire bien pratique développé par FreeRADIUS (je crois) qui s’appelle « radtest ». Il s’installe de cette manière :

sudo apt-get install freeradius-utils

Il suffit ensuite de taper la commande suivante (pensez à vider votre historique bash ensuite avec « history -c ») :

radtest -x -4 "compte utilisateur AD" "mot de passe AD" [addresse ip/fqdn du serveur radius]:1812 0 "secret partagé (mot de passe)"

Suivant la version de votre serveur RADIUS, vous devrez peut-être mettre le port UDP 1645 à la place de UDP 1812.

Voici une trace lorsque le test fonctionne :

Sending Access-Request of id 93 to mon_serveur_RADIUS.mon-domaine.corp port 1812
 User-Name = "admin"
 User-Password = "***********"
 NAS-IP-Address = 127.0.0.1
 NAS-Port = 0
 Message-Authenticator = 0x00000000000000000000000000000000
rad_recv: Access-Accept packet from host mon_serveur_RADIUS.mon-domaine.corp port 1812, id=93, length=202
 Marque-Exec-Privilege = 3
 Marque-AVPair = "web-administrative-role=Manager"
 Filter-Id = "Marque:version=1:mgmt=su:policy=SYS_ADMIN_AAA"
 Login-Service = 50
 Service-Type = Administrative-User
 Class = 0x89d4084f00006543102000a0a047900000000789764a6f44df9d01d3993c0951af0700000000000353bd
 MS-Link-Utilization-Threshold = 50
 MS-Link-Drop-Time-Limit = 120

Cela permet notamment de voir les attributs de l’utilisateur.

Important : Une fois le débogage terminé, pensez à commenter (# en début de ligne) les 2 lignes du fichier de configuration rsyslog et relancez le service. Avec le temps, vous risquez d’avoir un TRÈS gros fichier. Sinon, utilisez le service logrotate afin d’archiver et compresser les messages.

Le mot de la fin

Voilà, c’est tout pour cet article. J’espère avoir pu aider ou éclairer quelques personnes 😉

J’ajouterai que par sécurité et redondance, il est préférable d’avoir aux moins 2 serveurs RADIUS configurés. Utile lors des maintenances, ce sera transparent pour les utilisateurs.

Comme indiqué en introduction, il s’agit d’une « simple » introduction. Nous pourrions aller plus loin en gérant le changement de mot de passe, la création automatique des répertoires à la première connexion etc…