Escaping the Apple ecosystem: part 2

In part 1, I've written about the BoM of my project and the associated to-do list.
First item on this list was: build the box. That did not go as smoothly as expected. The motherboard was not fully operational: after few minutes of run time (between 5 and 30), it would trigger a CPU overheat alarm, even when the CPU was idle and cool. Supermicro's Support made me tried a new BIOS, with no effect, so I've finally send the board for exchange. The new board arrived but I've had to delay the rebuilt for few weeks.
Now the PC is up and running. The new motherboard seems to work great, but I've not tested IPMI yet. IPMI was the very first feature I've used on the first board, and there is a slight probability that the CPU overheat problem comes from a probe malfunction related to the BMC. Let's keep that for later.

I've chosen to run this box on VMware ESXi 5.5, because it's quite common (more than the latest 6.x), because it sports features I need like passthrough, and because most VMware based multi-sit PC projects like mine are using ESXi 5.x.

ESXi is quite easy to install, I won't give details. Main hdd in the box is installed with ESXi, which is configured thanks to a USB keyboard and a display plugged in the VGA port of the motherboard. After basic configuration (network, user password...), I've switched to remote configuration through VSphere Client, installed on a Windows PC (really a VM running on the Mac).

General view

General view of ESX's configuration


Configuring passthrough for GPUs is pretty straightforward, because I've started with only one GPU, and because these are discrete PCI cards. On the other hand, passthrough of USB controller can be tricky: many controllers, nothing to identify them except trial & error (unless you have the blueprint for your motherboard telling what physical USB ports belong to what controller).
Go to configuration tab, then "Advanced", and finally click "edit" on the right

Go to configuration tab, then "Advanced", and finally click "edit" on the right


When you click "Edit…" a window opens that lists interesting devices you can try to passthrough.
Choose some. Then you have to reboot the ESXi and add some of these devices to a VM.
passthrough
I've created a Windows 7 pro 64bits VM, with raw device mapping pointing to an SSD. I've added every available PCI devices to this VM (USB, sound, GPU) and installed Windows plus updates.
It's important to remember that initially, most PCI devices might not work at all because of missing drivers on guest OS (here it's Windows). Hence, after installing Windows, the Radeon was detected but not used, and only Intel USB controllers where working. I've installed AMD drivers, and ASMedia drivers (courtesy of Supermicro). I've also installed VMware Tools.
After all this, the Windows VM properly uses my Dell display hocked-up on the MSI R9 270x Radeon, and I can interact with the system thanks to a real keyboard and mouse. Passing through the whole USB controller allows me to use any USB device I want. I've successfully plugged-in and used a thumbdrive, a USB gaming headset and a USB hub.
I've made some GPU/CPU benchmarks and everything looks perfect. I've tested Left 4 Dead 2 game play, and it looked great too (I'll probably have to tweak anti aliasing settings to make it perfect).

The Windows part was quite fast to setup, and is almost done now. I've started to fight with OSX and Ubuntu, but things are not easy with both of them. It looks like my 3 years old graphics card it so new that OSX does not support it until 10.11.x, and Ubuntu won't allow me to install Radeon drivers on 16.x LTS because they wait for some software to stabilize before packaging it…

To-do list:

  • fix problems with OSX and Ubuntu virtualization
  • find another MSI Radeon R9 270X GAMING 2G (of course it's no longer in stock…)
  • fully test Mac OS X 10.6.8 with Mac's graphics card instead of MSI Radeon
Related posts

Cracking passwords: testing PCFG password guess generator

Cracking passwords is a kind of e-sport, really. There's competition among amateurs and professionals "players", tools, gear. There are secrets, home-made recipes, software helpers, etc.
One of this software is PCFG password guess generator, for "Probabilistic Context-Free Grammar". I won't explain the concept of PCFG, some scientific literature exists you can read to discover all the math inside.
PCFG password guess generator comes as two main python programs: pcfg_trainer.py and pcfg_manager.py. Basic mechanism is the following:
- you feed pcfg_trainer.py with enough known passwords to generate comprehensive rules describing the grammar of known passwords, and supposedly unknown passwords too.
- you run pcfg_manager.py, using previously created grammar, to create millions of password candidates to feed into your favorite password cracker (John the Ripper, Hashcat…).

In order to measure PCFG password guess generator's efficiency I've made few tests. Here is my setup:

  • Huge password dump, 117205873 accounts with 61829207 unique Raw-SHA1 hashes;
  • John the Ripper, Bleeding Jumbo, downloaded 20160728, compiled on FreeBSD 10.x;
  • PCFG password guess generator, downloaded 20160801, launched with Python 3.x;

Here's my methodology:

Of these 61829207 hashes, about 35 millions are already cracked. I've extracted a random sample of 2 millions known passwords to feed the trainer. Then I've used pcfg_manager.py to create a 10 millions lines word list. I've also trimmed the famous Rockyou list to it's 10 millions first lines, to provide a known reference.

Finally, I've launched this shell script:

#!/bin/sh
for i in none wordlist jumbo; do
  ./john --wordlist=pcfg_crckr --rules=$i --session=pcfg_cracker-$i --pot=pcfg_cracker-$i.pot HugeDump
  ./john --wordlist=ry10m --rules=$i --session=ry10m-$i --pot=ry10m-$i.pot HugeDump
done

No forking, I'm running on one CPU core here. Each word list is tested three times, with no word mangling rules, with defaults JtR rules, and finally with Jumbo mangling rules.

Some results (number of cracked passwords):

Rules PCFG Rockyou
none 4409362 2774971
wordlist 5705502 5005889
Jumbo 21146209 22781889

That I can translate into efficiency, where efficiency is Cracked/WordlistLength as percentage:

Rules PCFG Rockyou
none 44.1% 27.7%
wordlist 57.1% 50.1%
Jumbo 211.5% 227.8%

It's quite interesting to see that the PCFG generated word list has a very good efficiency, compared to Rockyou list, when no rules are involved. That's to be expected, as PCFG password guess generator has been trained with a quite large sample of known passwords from the same dump I am attacking.
Also, the PCFG password guess generator creates candidates that are not very well suited for mangling, and only the jumbo set of rules achieves good results with this source. Rockyou on the other hand starts quite low with only 27.7% but jumps to 50.1% with common rules, and finally defeats PCFG when used with jumbo rules.

On the word list side, Rockyou is known and limited: it will never grow. But PCFG password guess generator looks like it can create an infinite list of candidates. Let see what happens when I create a list of +110 M candidates and feed them to JtR.

Rules PCFG Efficiency
none 9703571 8.8%
wordlist 10815243 9.8%

Efficiency plummets: only 9.7 M hashes cracked with a list of 110398024 candidates, and only 1.1 M more when the set of rules "wordlist" is applied. It's even less beneficial than with a list of 10 M candidates (+1.3 M with "wordlist" rules, compared to "none").

On the result side, both word list with jumbo rules yields to +21 M cracked passwords. But are those passwords identical, or different?

Rules Total unique cracked Yield
none 6013896 83.7%
wordlist 8184166 76.4%
Jumbo 26841735 61.1%
Yield = UniqueCracked / (PcfgCracked + RockyouCracked)

A high yield basically says that you should run both word lists into John. A yield of 50% means that all pwd cracked thanks to PCFG are identical to those cracked with the Rockyou list.

As a conclusion, I would say that the PCFG password guess generator is a very interesting tool, as it provides a way to generate valid candidates pretty easily. You probably still need a proper known passwords corpus to train it.
It's also very efficient with no rules at all, compared to the Rockyou list. That might make it a good tool for very slow hashes when you can't afford to try thousands of mangling rules on each candidate.

Some graphs to illustrate this post:

every john session on the same graph

every john session on the same graph

every session, zoomed on the first 2 minutes

every session, zoomed on the first 2 minutes

Rules "wordlist" on both lists of candidates

Rules "wordlist" on both lists of candidates

Rules "none", both lists of candidates

Rules "none", both lists of candidates

Related posts

Escaping the Apple ecosystem: part 1

X10SRA-F_specBack in late 2012, I've started to think about my post-Apple days. I knew already that I would not endorse the full cloud crap, and the oversimplification of OS X that follows the iOS convergence. My hardware, my OS, my data.

I'm still running a Mac Pro 2010, with Mac OS X 10.6.8, the last great OS from Apple. Unfortunately (in)security is not what it used to be, and browsers, ssl libraries, etc. are updated frequently and older OSes are no longer supported. So it was time to switch away from 10.6.8 for my online activities. Meaning, it's time to create my multi-headed workstation running various OSes with dedicated GPU.

After about a year spent looking for the right pieces of hardware, I've came up with this BOM:

Hopefully it will yield to great results with virtualization, passthrough of GPUs and USB.
For now, only one GPU, just in case it's not working accordingly. That will allow me to test every OSes I want to use with GPU passthrough. I'll buy 2 more GPUs when it's fully tested and satisfactory.

To do list:

  • Assemble the workstation
  • Install and patch VMWare (to allow the virtualization of Mac OS X on non-Apple hardware)
  • Test each VM with GPU+USB+Sound passthrough

Due to the exotic nature of some of these pieces of hardware, I've had to order them from four retailers in two countries: Amazon (France), LDLC (France), PC-Cooling (Germany) and MindFactory (Germany).

I've got only one delivery problem, for the PC case: it was delivered through GLS Group, and it took them more than a week to drive 10 km from their warehouse to my home. When it finally went through my door, the box was trashed and the PC case had one foot slightly hammered into the case. It can't stand still on its 4 feet.
Whatever you buy abroad, just make sure it won't be delivered through GLS. The driver was a pain in the ass, calling me to delay the delivery.

Related posts

Monter un serveur d’authentification multifacteur 3/3

insertedDans deux articles précédents j'ai présenté la création d'un serveur de validation YK-VAL et d'un serveur de clé YK-KSM permettant de créer une infrastructure d'authentification double facteur basée sur Yubico OTP.

Dans ce dernier article je vais détailler quelques étapes importantes pour connecter un client, toujours en FreeBSD 10.3. Dans ce contexte, le client est en fait un service authentifié (un serveur sshd par exemple).

Prérequis

À ce stade, posséder une Yubikey dont vous pourrez configurer un des slots est impératif. Il est aussi pertinent de télécharger sur votre poste le Yubikey Personalization Tool. Et il vous faut bien évidemment une machine sous FreeBSD 10.x qui servira de serveur sshd.

Générer une clé d'API

La validation d'une authentification par OTP Yubico requière que l'utilisateur fournisse un OTP reconnu, c'est à dire que sa Yubikey soit enregistrée dans le YK-KSM, et que l'OTP envoyé soit valide. Il est aussi nécessaire que la connexion entre le client (ici sshd+pam) et le serveur YK-VAL soit "authentifiée" par une clé d'API.

Dans l'idéal, chaque client individuel doit disposer de sa propre clé d'API, c'est plus sûr. Et même si cela peut occasionner des lourdeurs, cela permet de révoquer une clé d'API sans mettre par terre l'ensemble des clients.

La première étape pour ajouter un client dans l'infrastructure est donc de créer une clé d'API. Pour cela, il faut se connecter sur le serveur YK-VAL, et lancer la commande suivante :

ykval-gen-clients --urandom --notes "client de test 1"
1,VI5eTtCSAjdmp473G3rWFq+pL1k=

Cette commande vous donne en résultat une clé d'API, associée au client "1". La clé d'API et les informations connexes sont injectées dans la base de données du serveur YK-VAL.

Enregistrer une Yubikey

Chaque Yubikey compatible Yubico OTP dispose de deux slots de configuration. Le premier est réglé par défaut sur Yubico OTP, mais il est impossible d'en extraire la clé privée de chiffrement (configuration d'usine). Cette clé est enregistrée dans le YK-KSM des serveurs yubico.com, donc elle est opérationnelle si vous souhaitez l'utiliser pour vous authentifier sur des services qui s'appuient sur le cloud de yubico.com. Nous souhaitons nous appuyer sur notre propre infrastructure privative, donc cette clé n'est pas utilisable.
Si vous souhaitez conserver cette clé initiale, vous devrez créer une nouvelle clé privée sur le slot 2 de votre Yubikey (et je vous y encourage). Si vous êtes sûr de ne pas en avoir l'usage, vous pouvez simplement écraser le slot 1 de la Yubikey avec votre nouvelle clé privée. Sachez que l'écrasement d'un slot est irréversible : la clé privée fournie par Yubico sera définitivement perdue.

Ceci posé, vous pouvez connecter votre Yubikey à votre machine, et lancer le Yubikey Personalization Tool.
Dans l'interface, choisissez le premier onglet en haut à gauche "Yubico OTP", et cliquez sur "Quick".
La fenêtre ci-dessous est affichée :
- choisissez le slot 1 (écrasement de la configuration d'usine) ou le slot 2 (vierge)
- décochez la case "Hide values"
- copiez précieusement les chaînes de caractères des trois champs, ainsi que le serial number au format décimal ("Dec") qui se trouve au milieu à droite de la fenêtre.

Yubico Personalization Tool

Il s'agit ensuite d'enregistrer ces informations dans la base de données du YK-KSM. Dans le cadre de ces tests, j'ai simplement injecté la clé à la main dans MySQL :

INSERT INTO yubikeys VALUES (4263215,"vvgrneginvdf","","578fba7ca791","fd69d1ecc644f36dde9dfc742cf2e3fa","00000000","",1,1);

Les champs sont dans l'ordre d'apparence : le numéro de série "Dec" de votre clé physique, la date de création (non renseignée), la "Public Identity" de votre clé de chiffrement, la "Private Identity" de votre clé de chiffrement, et enfin la "Secret Key". Les champs suivants sont "lockcode", "creator" (vide), "active" et "hardware". Laissez-les simplement comme présenté ci-dessus.

Dès que vous avez procédé à l'insertion, vous pouvez tester que la clé est bien reconnue par le serveur YK-KSM. Générez un OTP avec votre clé en appuyant un court instant sur le bouton si vous utilisez le slot 1, ou 2-3 secondes si vous utilisez le slot 2 (placez au préalable votre curseur dans un document txt).
Ensuite tapez la commande suivante sur le serveur YK-KSM :

curl 'http://localhost/wsapi/decrypt?otp=vvgrneginvdfddffbdhgefnrdtgcrnntccchndebhdiv'

ou vvgrneginvdfddffbdhgefnrdtgcrnntccchndebhdiv est l'OTP que vient de générer votre clé.
Vous obtiendrez alors la réponse suivante :

OK counter=0001 low=8250 high=45 use=02

Vous pouvez ensuite tester que votre Yubikey passe bien la validation de bout en bout. À partir d'un terminal sur YK-VAL, lancez la commande suivante :

ykclient --url "http://127.0.0.1/wsapi/2.0/verify" --apikey VI5eTtCSAjdmp473G3rWFq+pL1k= 1 vvgrneginvdfihrudhtffnjigivctkujtfjlkiniideg --debug

L'argument --apikey doit être suivi de la clé d'API que vous avez générée plus haut. Elle est suivit d'un espace, puis du numéro d'ID du client que vous avez inséré (et donné dans la sortie de la commande ykval-gen-clients). À la suite de ce client ID, on injecte un OTP, et éventuellement l'argument --debug.

Si tout va bien, vous devez obtenir dans la sortie :

Input:
  validation URL: http://127.0.0.1/wsapi/2.0/verify
  client id: 1
  token: vvgrneginvdfihrudhtffnjigivctkujtfjlkiniideg
  api key: VI5eTtCSAjdmp473G3rWFq+pL1k=
Verification output (0): Success

Configuration du client

Pour brancher un serveur sshd sur une infrastructure d'authentification double facteur, le plus simple est en général d'utiliser un plugin PAM. Sur FreeBSD, on peut en quelques secondes installer le nécessaire :

pkg install pam_yubico

Ce plugin s'appuie sur deux choses : l'URL de votre service YK-VAL, et une liste qui associe les logins des utilisateurs avec une clé ("Public Identity").
Vous pouvez créer le fichier qui associe l'uid UNIX à la "Public Identity" très simplement :

cat "patpro:vvgrneginvdf" >> /etc/yubikey

Puis dans /etc/pam.d/sshd il faut ajouter la directive qui permettra à PAM de faire la requête vers YK-VAL. La ligne suivante doit être ajoutée :

auth      required      /usr/local/lib/security/pam_yubico.so mode=client authfile=/etc/yubikey id=1 key=VI5eTtCSAjdmp473G3rWFq+pL1k= url=http://192.168.0.100/wsapi/2.0/verify?id=%d&otp=%s

juste au dessus de la ligne :

auth      required      pam_unix.so     no_warn try_first_pass

authfile pointe vers votre fichier associant uid et clé OTP, id est la Client ID créée lors de l'ajout du client sur YK-VAL, key est la clé d'API associée à ce client. Pour finir, url est l'adresse du service de vérification sur YK-VAL. On peut tout à fait inscrire le nom du serveur YK-VAL dans l'URL à la place de son adresse IP, néanmoins en cas d'avarie du DNS il est souhaitable que l'authentification continue de fonctionner.

Dernière étape : la configuration du serveur sshd. Il s'agit assez simplement de modifier /etc/ssh/sshd_config pour s'assurer que les paramètres suivants sont actifs :

PasswordAuthentication no
ChallengeResponseAuthentication yes

Relancez ensuite sshd avec la commande service sshd restart et tentez la connexion à partir d'une machine sur laquelle votre Yubikey est connectée :

$ ssh patpro@192.168.0.104
YubiKey for `patpro': 
Password for patpro@test10.patpro.net:
Last login: Fri May  6 21:33:58 2016 from 192.168.0.2
FreeBSD 10.3-RELEASE (GENERIC) #0 r297264: Fri Mar 25 02:10:02 UTC 2016

Welcome to FreeBSD!
...

Enjoy.

Bibliographie

Pour réaliser cette infrastructure privative d'authentification double facteur et les articles qui en découlent, je me suis appuyé sur les sources suivantes :

yubikey-ksm, principes et installation.
yubikey-val, principes et installation.
Building a local Yubikey server infrastructure (sur Linux).
yubico-pam, README.
YubiKey on FreeBSD HOWTO, aspect "client" uniquement, utilisant en plus pam_per_user.

Related posts

Monter un serveur d’authentification multifacteur 2/3

Dans un article précédent, j'ai présenté les étapes nécessaires à l'installation du serveur de validation YK-VAL de Yubico sur FreeBSD 10.3. Ce serveur s'intègre dans l'infrastructure d'authentification double facteur Yubico selon le schéma ci-dessous.
proposition d'infrastructure YK-VAL YK-KSM

D'autres modèles sont possibles bien évidemment, comme celui qui consiste à mettre les services YK-VAL et YK-KSM sur la même machine.
La suite des opérations consiste à créer le serveur YK-KSM en suivant la documentation officielle de Yubico, et les informations ci-après.

Serveur de clés YK-KSM

Pour assurer la sécurité lors des manipulations de clés, ce serveur est supposé n'utiliser que des fichiers chiffrés via OpenPGP/GnuPG. Aussi, l'outil ykksm-import nécessite-t-il qu'une clé GnuPG soit utilisée pour chiffrer les clés en amont, à leur création sur le poste de l'administrateur par exemple. Il est néanmoins tout à fait possible de ne pas utiliser les commandes ykksm-gen-keys et ykksm-import pour faire fonctionner l'infrastructure d'auth double facteur. Il suffit alors de fournir les clés à la main en les injectant directement dans la table MySQL ad-hoc.

Les étapes supplémentaires liées à OpenPGP n'étant pas complexes à mettre en œuvre, je les présente tout de même.
Il s'agit donc dans un premier temps d'installer gnupg, et de créer une clé maîtresse. Cette clé est utilisée sur le poste qui servira à générer les clés Yubico (ici le serveur lui-même), et sur le serveur YK-KSM pour les déchiffrer au moment de les injecter dans la base de données.

Pour une raison qui m'échappe, le fonctionnement de pinentry-tty est assez hasardeux à l'intérieur d'une Jail, donc si vous souhaitez, comme moi initialement, faire l'installation du service YK-KSM dans une Jail, passez votre chemin, vous gagnerez du temps :)

La partie GnuPG est assez simple :

pkg install gnupg
gpg2 --full-gen-key

Et suivez l'exemple de la doc Yubico. Une fois que votre clé GnuPG est créée, vous pouvez passer à l'installation du service YK-KSM proprement dite.

pkg install git help2man p5-DBI mysql56-server p5-DBD-mysql apache24 mod_php56 php56-xml php56-curl php56-hash php56-pdo_mysql php56-mcrypt
git clone git://github.com/Yubico/yubikey-ksm.git
cd yubikey-ksm

L'utilisation de GIT n'est pas obligatoire, on peut aussi bien télécharger le master.zip à partir de github, comme je l'ai fait pour YK-VAL.
Tout comme pour ce dernier, le Makefile est inexploitable en l'état, j'ai donc eu recours à quelques bricoles pour générer l'environnement adéquat avant d'installer les fichiers à la main :

for DIR in $(awk '/prefix = / {print $3}' Makefile); do
	[ -d $DIR ] || mkdir -p $DIR
done

La commande awk '/prefix = / {print $1"="$3}' Makefile nous donne une série de variables, à laquelle j'ajoute DESTDIR, que l'on fourni ensuite à bash :

etcprefix=/etc/yubico/ksm
binprefix=/usr/bin
phpprefix=/usr/share/yubikey-ksm
docprefix=/usr/share/doc/yubikey-ksm
manprefix=/usr/share/man/man1
wwwprefix=/var/www/wsapi
DESTDIR=/

Cette fois-ci, les commandes ykksm-* utilisables dans le shell sont codées en Perl avec un shebang compatible Linux, pas FreeBSD. On peut faire un lien symbolique de /usr/local/bin/perl vers /usr/bin/perl ou on peut corriger les scripts avant de les installer :

sed -i'.old' 's,/usr/bin/perl,/usr/local/bin/perl,' ykksm-import
sed -i'.old' 's,/usr/bin/perl,/usr/local/bin/perl,' ykksm-gen-keys
sed -i'.old' 's,/usr/bin/perl,/usr/local/bin/perl,' ykksm-export
sed -i'.old' 's,/usr/bin/perl,/usr/local/bin/perl,' ykksm-checksum

Puis on lance la copie des différents éléments :

cp .htaccess ${DESTDIR}${phpprefix}/.htaccess
cp ykksm-decrypt.php ${DESTDIR}${phpprefix}/ykksm-decrypt.php
cp ykksm-utils.php ${DESTDIR}${phpprefix}/ykksm-utils.php
cp ykksm-gen-keys ${DESTDIR}${binprefix}/ykksm-gen-keys
cp ykksm-import ${DESTDIR}${binprefix}/ykksm-import
cp ykksm-export ${DESTDIR}${binprefix}/ykksm-export
cp ykksm-checksum ${DESTDIR}${binprefix}/ykksm-checksum
cp ykksm-config.php ${DESTDIR}${etcprefix}/ykksm-config.php
cp ykksm-gen-keys.1 ${DESTDIR}${manprefix}/ykksm-gen-keys.1
cp ykksm-import.1 ${DESTDIR}${manprefix}/ykksm-import.1
cp ykksm-export.1 ${DESTDIR}${manprefix}/ykksm-export.1
cp ykksm-checksum.1 ${DESTDIR}${manprefix}/ykksm-checksum.1
cp ykksm-db.sql ${DESTDIR}${docprefix}/ykksm-db.sql
cp Makefile ${DESTDIR}${docprefix}/ykksm.mk
cp doc/* ${DESTDIR}${docprefix}/

L'étape suivante est l'installation de la base de données. Suivez simplement les instructions de l'étape 3 de la doc Yubico.

J'ai traité l'étape 4 différemment de ce qui est proposé. J'ai préféré tout mettre dans le fichier .htaccess :

<IfModule mod_php5.c>
  php_value include_path ".:/etc/yubico/ksm:/usr/share/yubikey-ksm"
</IfModule>

RewriteEngine on
RewriteRule ^([^/\.\?]+)(\?.*)?$ $1.php$2 [L]

L'étape 5 se traite exactement de la même manière que pour YK-VAL. Et l'étape 6 se fait simplement en créant les liens symboliques à la main.

À l'étape 7, tout comme pour YK-VAL, on renseigne le mot de passe MySQL dans le fichier de configuration ykksm-config.php.

Ensuite, sous réserve que votre serveur web soit lancé, il ne vous reste qu'à tester que tout fonctionne. Comme indiqué dans la doc, le résultat attendu est une erreur de clé inconnue, ce qui est tout à fait normal.

Fabrication de clés et import dans la base de données

Les vraies clés seront ajoutées ultérieurement. Mais vous pouvez néanmoins tester l'ajout de clés bidons via ykksm-gen-keys et ykksm-import.

La fabrication de 5 clés se fait comme ceci (doc officielle) :

ykksm-gen-keys --urandom 1 5 | gpg -a --encrypt -r 67A59965 -s > keys.txt

où 67A59965 est l'ID de la clé GnuPG fabriquée un peu plus haut.

Ensuite l'import des clés se fait de cette manière (doc officielle) :

ykksm-import --verbose --database 'DBI:mysql:dbname=ykksm;host=localhost' --db-user ykksmimporter --db-passwd mot-de-passe-mysql < keys.txt

Dans un troisième et dernier article il sera question de la partie vraiment intéressante : comment provisionner de vraies clés, et comment brancher un Client YK (un serveur sshd par exemple) sur votre nouvelle infrastructure d'authentification double facteur.

Related posts

Redis au secours de la performance du filtrage bayésien de SpamAssassin

Compte tenu des masses titanesques d'emails qu'un serveur peut être amené à traiter quotidiennement, l'optimisation des performances pour son logiciel de filtrage antispam est primordiale. C'est encore plus vrai si vous pratiquez le before queue content filtering.

Depuis plusieurs mois, vraisemblablement suite à une mise à jour d'une librairie ou d'un composant de l'antispam, j'ai constaté sur le SMTP authentifié @work un délai de traitement anormal dans certains cas. La durée normale pour le filtrage d'un message se situe entre 0 et 1 seconde, et pour une portion non-négligeable d'entre eux, cette durée passe à 30 secondes presque tout rond :

normal :                    anormal : 

elapsed: {                  elapsed: {
 Amavis: 0.059               Amavis: 0.267
 Decoding: 0.019             Decoding: 0.026
 Receiving: 0.002            Receiving: 0.002
 Sending: 0.027              Sending: 0.229
 SpamCheck: 0.156            SpamCheck: 30.113
 Total: 0.224                Total: 30.398
 VirusCheck: 0.003           VirusCheck: 0.008
}                           } 

Une recherche en mode debug m'a rapidement orienté vers un souci avec le filtrage bayésien :

SA dbg: locker: safe_lock: created /.../bayes.lock.foobar.19635
SA dbg: locker: safe_lock: trying to get lock on /.../bayes with 0 retries
SA dbg: locker: safe_lock: trying to get lock on /.../bayes with 1 retries
SA dbg: locker: safe_lock: trying to get lock on /.../bayes with 2 retries
SA dbg: locker: safe_lock: trying to get lock on /.../bayes with 3 retries
SA dbg: locker: safe_lock: trying to get lock on /.../bayes with 4 retries
SA dbg: locker: safe_lock: trying to get lock on /.../bayes with 5 retries
SA dbg: locker: safe_lock: trying to get lock on /.../bayes with 6 retries
SA dbg: locker: safe_lock: trying to get lock on /.../bayes with 7 retries
SA dbg: locker: safe_lock: trying to get lock on /.../bayes with 8 retries
SA dbg: locker: safe_lock: trying to get lock on /.../bayes with 9 retries

Ces 10 tentatives de prise de verrou ont souvent lieu 3 fois de suite, et chaque série dure 10 secondes : mon délai de 30 secondes est trouvé.
Le problème se trouvant du côté des fonctions d'accès à la base de données bayésienne, j'ai deux options : le résoudre ou le contourner. Le résoudre impliquerait probablement plusieurs journées d'analyse très fine et surtout de nombreux tests intrusifs sur une machine de production : pas envisageable.

J'ai donc pris le parti remplacer le stockage bayésien basique (Berkeley DB) par un stockage "haute performance" basé sur une base de données Redis.

Le changement est très simple à implémenter et totalement réversible. Le serveur Redis étant déjà installé sur la machine pour recueillir les logs détaillés d'Amavisd-new, il y a très peu de modifications à apporter pour y stocker les "seen" et les "token" de SpamAssassin.

Le support de Redis est inclus nativement dans Spamassassin depuis la version 3.4.0. Il suffit donc de placer les bons réglages et de recharger amavisd-new :

Dans le fichier /usr/local/etc/mail/spamassassin/local.cf on ajoute les lignes suivantes :

	bayes_store_module  Mail::SpamAssassin::BayesStore::Redis
	bayes_sql_dsn       server=127.0.0.1:6379;password=foo;database=3
	bayes_token_ttl 21d
	bayes_seen_ttl   8d

Et on recharge amavisd-new avec la commande sudo amavisd reload.

Il faut ensuite utiliser sa-learn pour faire apprendre à la nouvelle base vierge 200 messages de spam et 200 messages de ham, sans quoi la base bayésienne ne sera pas utilisée lors de l'analyse antispam.

Le gain de performance est immédiat : comme il s'agit d'une base de données NoSQL en mémoire, il n'y a pas de contrainte de verrou sur des fichiers, et la très forte concurrence des requêtes n'est plus un souci.

Entre la semaine 17 et la semaine 18 on constate la disparition quasi-totale des longs temps d'analyse, notamment dans la zone des 30 secondes (attention à l'échelle log) :

nbr_msg_pr_duree_antispam

Les trois bosses se situent respectivement autour de 10, 20 et 30 secondes. On remarque aussi que les performances de cette semaine 18 (avec Redis) sont meilleures que celles d'une semaine précédant l'arrivée du problème (bosse à 10 secondes) :

nbr_msg_pr_duree_antispam2

Une autre représentation des mêmes données montre de manière spectaculaire l'amélioration des temps d'analyse :

repartition_msg_pr_duree_pcent

Cette modification relativement simple améliore clairement le ressenti des utilisateurs du serveur SMTP (ie. qui ne passent pas par une interface "webmail"). Leur client de messagerie ne les fera plus attendre 30 secondes par envoi lors des périodes de forte affluence, et le filtrage en Before Queue est préservé. Le meilleur des deux mondes !

Related posts

Monter un serveur d’authentification multifacteur 1/3

YubiKey-4-EdgeLe simple mot de passe est de plus en plus souvent pointé du doigt comme ne présentant plus les garanties requises pour l'authentification. L'alliance FIDO montre d'ailleurs l'exemple en assurant le développement et la promotion d'une infrastructure grand public d'authentification double facteur.

Quels outils pour l'authentification double facteur ?

Il est néanmoins des cas (nombreux) où FIDO et son U2F ne fonctionneront pas pour vous : pour toutes les authentifications qui ne passent pas par un navigateur web.

Pour tout le reste, et en particulier ce qui passe par PAM sur les UNIX et Linux, il existe quelques outils. Google Authenticator fonctionne bien, mais il nécessite que vous utilisiez un client type Google Authenticator, en général sur téléphone malin. Pour quelqu'un qui va s'authentifier rarement, disons 1 à 5 fois par semaine, c'est supportable : initier la connexion, sortir et déverrouiller son téléphone, lancer l'application, recopier le code temporaire (OTP), fermer l'application.
Sur un an je m'authentifie en ssh ou dans sudo environ 4000 fois. C'est à dire en moyenne plus de 11 fois par jour, pour des semaines de 7 jours.
En réalité je travaille toujours un peu moins le week end. Il en résulte qu'une journée de travail peut voir des pics autour de 60 authentifications.
Utiliser une authentification double facteur basée sur une appli mobile ou tout autre appareil affichant un code à recopier serait un échec dans un tel contexte.

C'est là que la Yubikey entre en jeu. Cette petite clé USB programmable est vue comme un clavier par votre ordinateur, et sur pression du doigt elle va taper pour vous l'OTP nécessaire à l'auth double facteur.
Par défaut elle s'appuie sur des serveurs externes pour valider votre OTP. Le jour où pour une raison X ou Y votre réseau n'accède plus à ces serveurs, vous ne pourrez donc plus vous authentifier (il existe malgré tout des contournements). C'est particulièrement problématique si vous tentez justement de reprendre la main sur votre firewall qui a décidé de bloquer l'accès à internet.
Heureusement, Yubico met à disposition de la communauté les outils nécessaires à la création d'un serveur de validation et d'un serveur de stockage des clés, permettant ainsi aux plus exigeants d'entre-nous de monter leur propre infrastructure d'authentification double facteur interne.

Ces outils sont bruts de fonderie, un peu mal dégrossis, et les instructions pour leur mise en place sont parfois approximatives. Le sujet devient encore plus épineux quand on tente de faire l'installation sur FreeBSD. Voici donc quelques instructions basées sur les notes prises lors de mes errances.

Monter des serveurs d'authentification Yubico sur FreeBSD

L'infrastructure d'authentification double facteur Yubico est composée de deux services : le service de validation (YK-VAL), c'est à dire celui auquel votre OTP va être envoyé par PAM, et qui donnera la réponse à PAM, et le service de stockage des clés (YK-KSM) sur lequel les clés des utilisateurs sont enregistrées.
Pour des raisons évidentes, il est recommandé de sécuriser au maximum ces deux services. L'idéal est donc de les installer sur deux machines différentes, et d'appliquer de la sécurité en profondeur dessus : firewall en entrée et sortie, si possible un réseau privé entre les deux serveurs, HTTPS partout, etc.

proposition d'infrastructure YK-VAL YK-KSM

Prérequis : pour aller au bout du process, il vous faudra acheter au moins une clé Yubikey, n'importe laquelle supportant "Yubico OTP".

Pour les besoins de cette maquette, j'ai créé 3 machines virtuelles FreeBSD 10.3. Une d'entre elle sera le serveur de validation ykval.patpro.net, une autre sera le serveur de clé yksm.patpro.net, et la dernière sera un serveur sshd sur lequel je souhaite activer l'authentification double facteur.

Serveur de validation YK-VAL

Sur une installation relativement vierge de FreeBSD 10.3, j'installe les composants suivants :

pkg install apache24 mod_php56 php56-xml php56-curl php56-hash bash sudo mysql57-server php56-pdo_mysql ykclient

Attention, pour une raison que je n'ai plus en tête, l'installation du serveur YK-KSM n'est pas compatible avec mysql57-server. Si vous installez YK-VAL et YK-KSM sur la même machine, choisissez mysql56-server !

Je récupère aussi les sources du serveur de validation Yubico :

fetch https://github.com/Yubico/yubikey-val/archive/master.zip
unzip master.zip

Et je tente de suivre les instructions présentées sur la documentation officielle Yubico. Je vous encourage à lire cette documentation en parallèle avec ce blog, car je ne reprends pas ici l'intégralité des explications.

Premier souci, le Makefile n'est pas fonctionnel sur FreeBSD, et j'ai du faire l'installation manuellement. J'ai tenté de scripter les choses un tout petit peu en créant automatiquement les répertoires manquants :

for DIR in $(awk '/prefix = / {print $3}' Makefile); do
	[ -d $DIR ] || mkdir -p $DIR
done

Puis en créant une série de variables qu'il faut injecter dans bash :

awk '/prefix = / {print $1"="$3}' Makefile
etcprefix=/etc/yubico/val
sbinprefix=/usr/sbin
phpprefix=/usr/share/yubikey-val
docprefix=/usr/share/doc/yubikey-val
manprefix=/usr/share/man/man1
muninprefix=/usr/share/munin/plugins
wwwprefix=/var/www/wsapi

Ensuite on peut copier les fichiers vers leur destination :

cp ykval-verify.php ${phpprefix}/ykval-verify.php
cp ykval-common.php ${phpprefix}/ykval-common.php
cp ykval-synclib.php ${phpprefix}/ykval-synclib.php
cp ykval-sync.php ${phpprefix}/ykval-sync.php
cp ykval-resync.php ${phpprefix}/ykval-resync.php
cp ykval-db.php ${phpprefix}/ykval-db.php
cp ykval-db-pdo.php ${phpprefix}/ykval-db-pdo.php
cp ykval-db-oci.php ${phpprefix}/ykval-db-oci.php
cp ykval-log.php ${phpprefix}/ykval-log.php
cp ykval-queue ${sbinprefix}/ykval-queue
cp ykval-synchronize ${sbinprefix}/ykval-synchronize
cp ykval-export ${sbinprefix}/ykval-export
cp ykval-import ${sbinprefix}/ykval-import
cp ykval-gen-clients ${sbinprefix}/ykval-gen-clients
cp ykval-export-clients ${sbinprefix}/ykval-export-clients
cp ykval-import-clients ${sbinprefix}/ykval-import-clients
cp ykval-checksum-clients ${sbinprefix}/ykval-checksum-clients
cp ykval-checksum-deactivated ${sbinprefix}/ykval-checksum-deactivated
cp ykval-nagios-queuelength.php ${sbinprefix}/ykval-nagios-queuelength
cp ykval-queue.1 ${manprefix}/ykval-queue.1
cp ykval-synchronize.1 ${manprefix}/ykval-synchronize.1
cp ykval-import.1 ${manprefix}/ykval-import.1
cp ykval-export.1 ${manprefix}/ykval-export.1
cp ykval-gen-clients.1 ${manprefix}/ykval-gen-clients.1
cp ykval-import-clients.1 ${manprefix}/ykval-import-clients.1
cp ykval-export-clients.1 ${manprefix}/ykval-export-clients.1
cp ykval-checksum-clients.1 ${manprefix}/ykval-checksum-clients.1
cp ykval-checksum-deactivated.1 ${manprefix}/ykval-checksum-deactivated.1
cp ykval-munin-ksmlatency.php ${muninprefix}/ykval_ksmlatency
cp ykval-munin-vallatency.php ${muninprefix}/ykval_vallatency
cp ykval-munin-queuelength.php ${muninprefix}/ykval_queuelength
cp ykval-munin-responses.pl ${muninprefix}/ykval_responses
cp ykval-munin-ksmresponses.pl ${muninprefix}/ykval_ksmresponses
cp ykval-munin-yubikeystats.php ${muninprefix}/ykval_yubikeystats
cp ykval-db.sql ${docprefix}/ykval-db.sql
cp ykval-db.oracle.sql ${docprefix}/ykval-db.oracle.sql

À ce stade on a installé différents scripts php dont le shebang est réglé sur un chemin "linux". On pourrait modifier tous les shebangs, mais il est plus simple de créer un lien symbolique de php au bon endroit :

ln -s /usr/local/bin/php /usr/bin/

Ensuite on s'attaque à la configuration de la base de données. J'ai opté pour MySQL, avec lequel je suis plus à l'aise.
Les étapes de la documentation officielle fonctionnent assez bien, mais les droits alloués à l'utilisateur ykval_verifier sont insuffisants. Il faut en effet lui donner les droits d'ajouter des clients dans la table ykval.clients. J'ai donc remplacé la ligne :

GRANT SELECT(id, secret, active) ON ykval.clients TO 'ykval_verifier'@'localhost';

par :

GRANT SELECT,INSERT,UPDATE ON ykval.clients TO 'ykval_verifier'@'localhost';

L'étape 4 de la doc. se résume à ces trois commandes :

mkdir /var/www/wsapi/2.0
ln -sf /usr/share/yubikey-val/ykval-verify.php /var/www/wsapi/2.0/verify.php
ln -sf /usr/share/yubikey-val/ykval-sync.php /var/www/wsapi/2.0/sync.php

L'étape 5 consiste à créer l'endroit où seront stockées les préférences de l'application, et à s'assurer qu'elles seront lisibles par Apache.

mkdir /etc/default
vi /etc/default/ykval-queue
ajouter la ligne : DAEMON_ARGS="/etc/yubico/val:/usr/share/yubikey-val"
vi /var/www/wsapi/2.0/.htaccess
ajouter les lignes suivantes : 
	RewriteEngine on
	RewriteRule ^([^/\.\?]+)(\?.*)?$ $1.php$2 [L]
	<IfModule mod_php5.c>
	  php_value include_path ".:/etc/yubico/val:/usr/share/yubikey-val"
	</IfModule>
cd /var/www/wsapi
ln -s 2.0/.htaccess /var/www/wsapi/.htaccess

À l'étape 6, il faut récupérer l'exemple de fichier de configuration ykval-config.php fourni avec le code de l'application, et le copier au bon endroit :

cp ykval-config.php /etc/yubico/val/

On édite ce fichier pour renseigner le mot de passe MySQL.

L'étape 7 permet de configurer Apache. Les instructions présentées sont valides pour apache 2.2, mais en version 2.4 il y a quelques modifications à faire. Notamment, autoriser l'accès se fait par la formule Require all granted. Il faut aussi activer le mod_rewrite qui n'est pas actif par défaut sur FreeBSD.

C'est l'occasion de configurer proprement le virtual host, d'activer SSL, etc.

Pour configurer syslogd lors de l'étape 8, il suffit d'ajouter la ligne suivante à /etc/syslog.conf :

local0.*              /var/log/ykval.log

et de faire un touch /var/log/ykval.log && service syslogd restart.

La rotation automatique pourra être gérée dans /etc/newsyslog.conf.

J'ai sauté l'étape 9, car je n'ai pas souhaité mettre en place de synchronisation entre différents YK-VAL pour cette maquette. C'est néanmoins une étape à valider si vous souhaitez mettre en place une infrastructure utilisable en production (ie. redondante).

À ce stade vous pourrez passer à l'étape 11. Cette dernière donnera sans doute lieu à de nombreux petits ajustements : config Apache, droits de fichiers, etc. Pas de panique, les logs fournissent normalement pas mal de pistes (notamment /var/log/ykval.log), et vous ne seriez pas ici si vous n'étiez pas capable de vous en sortir.

curl 'http://ykval.patpro.net/wsapi/2.0/verify?id=1&nonce=asdmalksdmlkasmdlkasmdlakmsdaasklmdlak&otp=dteffujehknhfjbrjnlnldnhcujvddbikngjrtgh'
h=CqcOcOH1yokoXcDimKDnElyP+f8=
t=2016-02-18T17:47:56Z0853
status=NO_SUCH_CLIENT

Lire la suite : la création du serveur YK-KSM.

Related posts

Un shell taillé pour le roaming, la 3G et les cages d’ascenseur

Les fans de la ligne de commande, ou ceux qui sont obligés de s'en servir, le savent : garder un shell distant ouvert et réactif peut parfois être très compliqué, voire impossible. Vous lancez une manip un peu longue mais après quelques temps vous devez changer de réseau. Vous devez intervenir d'urgence via une connexion mobile de très mauvaise qualité. Vous êtes coincé dans un ascenseur avec quelques kbps de bande passante sur un WIFI intermittent. Autant de raisons qui vous feront aimer mosh.

passer-sur-mosh
Mosh pour Mobile Shell, est un outil client et serveur qui supporte le roaming, et qui fonctionne particulièrement bien sur les connexions de mauvaise qualité.
L'architecture de mosh est bien pensée : elle ne nécessite pas d'intervention lourde sur vos serveurs pour en permettre l'utilisation et elle s'appuie sur un serveur ssh existant pour gérer l'initialisation de la connexion, dont la phase d'authentification.

Vous devez simplement installer mosh sur votre poste et sur votre serveur. À partir de là, la connexion fonctionne selon ce principe :
- vous lancez mosh en pointant sur votre login@serveur
- mosh ouvre une connexion ssh login@serveur ce qui permet de procéder à votre authentification
- dès que vous êtes authentifié, mosh lance mosh-server sur le serveur, sous votre UID
- mosh ferme la connexion ssh, et passe la main au mosh-client
- mosh-client se connecte en UDP sur votre mosh-server distant.

Bien sûr, les paquets UDP sont chiffrés, garantissant la sécurité de la connexion. Mosh dispose aussi d'une fonction local-echo très utile sur les liens à forte latence : vous voyez ce que vous tapez immédiatement, contrairement à ce qu'il se passe sur une connexion ssh, où votre entrée devra arriver sur le serveur, être traitée, être renvoyée à votre terminal puis enfin affichée. Cela ajoute un agrément très appréciable sur les lignes très lente ou de mauvaise qualité.

Aussi, l'utilisation de l'UDP, un protocole non-connecté, autorise une implémentation simple de l'itinérance. Plus de problème quand votre portable change de réseau Wifi, passe de l'ethernet à la 4G, etc. Votre connexion avec le serveur reste ouverte, et utilisable dès que le réseau est disponible.

J'encourage vivement les curieux à approfondir les aspects techniques, c'est intéressant et innovant.
Attention cependant, mosh ne supporte pas les utilisations non-intéractives de ssh : scp, les tunnels, X-Forwarding… C'est vraiment fait - actuellement - pour remplacer la bonne vieille session interactive.

Les binaires sont disponibles pour de nombreuses plateformes, même pour Mac OS X 10.5... vous n'avez plus aucune excuse.

Related posts