Archive

Archive for the ‘Security’ Category

Premier pas avec mod_security

June 19th, 2011 No comments

Un client m’a demandé récemment si je pouvais jeter un œil à mod_security pour ses besoins de protections d’URL (WAF, en anglais Web Application Firewall, plus d’infos sur l’article Wikipedia). En quelques mots, mod_security est un module Apache – comme son nom l’indique – qui apporte donc une fonctionnalité de filtre relativement avancé, mais avec l’avantage d’être opensource et donc gratuit. De plus, il vient avec un ensemble de règles déjà établies qui sont le fruit du travail du groupe OWASP, qui se définit comme un 501c3 not-for-profit worldwide charitable organization focused on improving the security of application software.

L’objectif de ma première approche de mod_security est relativement simple puisqu’il consiste à logger toutes les tentatives d’authentification avec un nom d’utilisateur qui contient des caractères hormis [a-zA-Z0-9]. Voici un récapitulatif de l’architecture (simple) mise en œuvre :

  • Distribution : CentOS
  • un apache (où sera installé le module mod_security) en frontal devant un Tomcat, en utilisant le mod_proxy (en HTTP)
  • un Tomcat avec une application de test nommée Xebia Travel développée par Xebia
  • L’authentification des utilisateurs sur l’application Xebia Travel s’effectue via un POST au travers d’un formulaire, avec les variables j_username et j_password

Une fois installé mod_security (depuis le dépôt EPEL), et quelques petites heures de recherche, voici le résultat que j’ai obtenu :


SecAuditLog /var/log/httpd/ecommerce-audit.log
SecDebugLog /var/log/httpd/ecommerce-security.log
SecDebugLogLevel 3
SecAuditEngine relevantonly

SecRequestBodyAccess On

SecRule ARGS:j_username "!@rx ^([A-Za-z0-9]+)$" auditlog,id:10000

Quelques explications :

  • Les directives SecAuditLog, SecDebug, SecDebugLogLevel et SecAuditEngine sont relativement explicites. Elles permettent en effet de configurer les différents fichiers de logs et d’audit, ainsi que leur verbosité
  • La directive SecRequestBodyAccess est très importante, puisqu’elle permet de dire à mod_security d’analyser non pas seulement les en-têtes des requêtes mais également le corps. Pourquoi est-ce important ? Parce qu’avec les formulaires de type POST, les variables sont passées non pas en en-tête, mais bien dans le corps du message. Sans cette directive, il est donc impossible d’analyser les arguments des formulaires de type POST
  • et enfin, la directive la plus importante à savoir SecRule qui est exécutée à chaque fois qu’une requête est effectuée avec l’argument j_username (POST ou GET), et je vérifie au travers d’une expression rationnelle (regex) qu’elle contient d’autres caractères que [A-Za-z0-9], auquel cas je lui définie l’action auditlog, en lui demendant d’identifier cette règle avec l’id 10000, ce qui s’avère pratique pour l’analyse du fichier d’audit.
  • Bien entendu, ce billet ne montre qu’un centième des utilisations possible de mod_security, mais si cela peut aider à commencer, sur ce, à bientôt !

EJBCA Créer un certificat administrateur en ligne de commande

May 4th, 2011 No comments

De retour chez un client après quelques années d’absences, je me retrouve avec un certificat d’administrateur expiré sur la PKI de test. Voici la procédure de création d’un nouveau certificat, le tout en ligne de commande, forcément :

./bin/ejbca.sh ra adduser bbonfils00 foo123 "cn=Bruno Bonfils,UID=bbonfils,O=Customer,C=FR" NULL AdminCA1 bruno@opencsi.com 1 P12 ENDUSER EE_PKI_ADMINISTRATOR
./bin/ejbca.sh ra setclearpwd bbonfils00 foo123
./bin/ejbca.sh batch

Bien entendu il faut que le certificat corresponde au profil. Si besoin, vous devez pouvoir utiliser le profil EMPTY en ne spécifiant uniquement le CN. Il faut maintenant obtenir le numéro de série du certificat.

./bin/ejbca.sh ra getusercert bbonfils00

Copier / coller le certificat dans un certificat, puis extraire le numéro de série à l’aide de la commande OpenSSL :

openssl x509 -in /tmp/bbonfils0.pem -noout -serial
serial=4AEDB10E68DC69B6

Et finalement, identifier un groupe d’administrateur, puis rajouter l’administrateur dans ce groupe :

./bin/ejbca.sh admins listgroups
Using JBoss JNDI provider...
PKI CA Administrators (1 admin)
Super Administrator Group (2 admins)
./bin/ejbca.sh admins addadmin "Super Administrator Group" "AdminCA" "WITHSERIALNUMBER" EQUALCASEINS 4AEDB10E68DC69B6

Categories: PKI Tags:

Le futur de la sécurité Web, ce n’est pas le https

April 4th, 2011 2 comments

Suite aux problèmes récents de divers fournisseurs officiels de certificats, notamment Comodo, on peut croiser ici et diverses propositions de changement (assez radicaux) quant à la gestion des certificats. Certains parlent d’un Web of Trust (pour faire simple et court, c’est l’utilisateur qui choisi au cas par cas à qui il fait confiance), d’autres encore pensent à sortir du modèle actuel des fournisseurs officiels, en utilisant notamment le DNS pour fournir l’information sur le certificat attendu, ce qui permettrait au navigateur de savoir si le certificat reçu est celui attendu.

Cependant, toutes ces propositions ne sont là que pour corriger le modèle actuel des fournisseurs de certificats, aucune proposition (du moins parmi celle que j’ai lues) ne remet en question le modèle du HTTPs, à savoir de la protection de transport. Pour moi, le vrai problème ne se situe plus à la protection du transport, mais à la protection du contenu. Qu’est ce que je veux dire par là ? Prenons un cas simple, une page d’authentification. Il va de soit que l’identifiant et surtout le mot de passe doit être transmis de manière sécurisé.

Aujourd’hui nous utilisons de plus en plus de sites internets, issus de différents éditeurs, et surtout de plus en plus de portails. Comme je l’avais imaginé il y a déjà plus de 2 ans, de mon avis l’avenir réside dans le fait de sécuriser le contenu, et non plus le contenant. Prenons l’exemple d’un utilisateur qui va sur un site que l’on appellera BLOG, cette personne veut publier un commentaire, mais ne dispose pas d’un compte sur la plateforme BLOG. Peu importe, nous sommes au XXI ème siècle, il est possible de s’identifier via Facebook ! Oui mais… suivant comment est implémentée cette authentification, rien ne garanti que le mot de passe circule de manière chiffrée sur la plateforme BLOG. Cependant, l’authentification est un cas à part, il existe déjà des mécanismes pour éviter ce genre de problème, notamment la fédération d’identité, qui permet à un fournisseur de service (tel qu’un blog wordpress comme celui que vous lisez actuellement) d’être indépendant du fournisseur d’identité (là où on tape son identifiant et son mot de passe).

Le principe est relativement simple, plutôt que de chiffrer le tuyau d’une communication sensible, on chiffre le contenu de la communication, qui peut donc transiter de manière sûre via des canaux non sûrs. Bien entendu, cela ne change en rien la problématique de délivrance des certificats. Mais je pense que plutôt que d’essayer de corriger le problème en bout de chaîne, essayons de corriger la source. Par exemple, la plupart de nos chers voisins belges disposent d’une carte d’identité électronique, qui contient un certificat. Ce dernier, au travers d’un lecteur de carte (avec des drivers qui fonctionnent aussi bien sous Windows que sous Linux, en passant par Mac OS X), peuvent utiliser leur certificat, notamment pour déposer des dossiers légaux de manière purement électronique. En aucun cas je ne suis en train de dire que tous les certificats serveurs doivent être délivrés par l’État ou assimilé (encore que, quand on voit cet article on peut se demander de la pertinence d’une telle solution). Mais l’utilisation massive par les utilisateurs d’un certificat permettrait – je le pense – une meilleure compréhension, et surtout cela imposerait aux éditeurs de logiciels de prendre du temps pour réfléchir à l’ergonomie associée. Car, et je terminerais la dessus, le problème de sécurité des certificats actuels, est surtout lié aux éditeurs des navigateurs.

En effet, bien que l’on puisse reprocher l’aspect monétaire, le modèle actuel pêche surtout par l’absence de renouvellement régulier des certificats racines, certains sont en 1024 bits, d’autres utilisent du MD4 (non, il n’y a pas de typo, je parle bien de MD4 et non MD5, qui de toute manière est tout aussi faible dans le cas de certificats). De plus, bien qu’il existe des mécanismes de vérification des certificats (tel que l’utilisation de CRL, et surtout de l’OCSP) ces mécanismes ne sont pas activés par défaut sur les navigateurs et/ou systèmes d’exploitations. Pour conclure, plutôt que d’essayer de trouver un nouveau modèle, il faudrait utiliser les technologies qui nous sont d’ores et déjà proposées.

Categories: Security Tags:

LSC Use Case: synchronize telephoneNumber from Sun LDAP to Active Directory

July 21st, 2010 1 comment

At work, we are using two directories. The first one, a damn old Sun Directory 5.2, used by the mail system and VOIP. The second directory is an Active Directory used by … everything which run on Windows. At the moment, we don’t have some Identity Provisionning products, so users are created by hand in both directories. I want to make this synchronization automatic, however since it’s a complex and dangerous thing, I want to start by synchronize few attributes. The first one is the telephoneNumber, available in the Sun Directory with format “21xxx” (the internal phone number), while the one store in active directory is the public one (014070xxx), so I need to transform the attribute before sending it in AD.

Some friends of mine start the LSC Project(LDAP Synchronization Connector) few years ago, a tool to synchronize directories! Here the configuration file I used for my use case:

Define the source


src.java.naming.provider.url = ldap://sun_hostname:389/dc=rtl,dc=fr
src.java.naming.security.authentication = none
src.java.naming.security.principal =
src.java.naming.security.credentials =
src.java.naming.referral = ignore
src.java.naming.ldap.derefAliases = never
src.java.naming.factory.initial = com.sun.jndi.ldap.LdapCtxFactory
src.java.naming.ldap.version = 3

Define the target


dst.java.naming.provider.url = ldap://ad_hostname:389/dc=activedirectory,dc=domain
dst.java.naming.security.authentication = simple
dst.java.naming.security.principal = userwithenoughperms@activedirectory.domain
dst.java.naming.security.credentials = secret
dst.java.naming.referral = ignore
dst.java.naming.ldap.derefAliases = never
dst.java.naming.factory.initial = com.sun.jndi.ldap.LdapCtxFactory
dst.java.naming.ldap.version = 3

Define the task to manage telephoneNumber attribute


lsc.tasks = FirstTask
lsc.tasks.FirstTask.srcService = org.lsc.jndi.SimpleJndiSrcService
lsc.tasks.FirstTask.srcService.baseDn = ou=People
lsc.tasks.FirstTask.srcService.filterAll = (inetUserStatus=ACTIVE)
lsc.tasks.FirstTask.srcService.pivotAttrs = mail
lsc.tasks.FirstTask.srcService.filterId = (mail={mail})
lsc.tasks.FirstTask.srcService.attrs = mail telephoneNumber
lsc.tasks.FirstTask.srcService.requestNameForList = getAllPeoplePivots
lsc.tasks.FirstTask.srcService.requestNameForObject = getOnePerson
lsc.tasks.FirstTask.dstService = org.lsc.jndi.SimpleJndiDstService
lsc.tasks.FirstTask.dstService.baseDn = ou=Pole radio,dc=activedirectory,dc=domain
lsc.tasks.FirstTask.dstService.filterAll = (&(sn=*)(objectClass=inetOrgPerson))
lsc.tasks.FirstTask.dstService.pivotAttrs = mail
lsc.tasks.FirstTask.dstService.filterId = (mail={mail})
lsc.tasks.FirstTask.dstService.attrs = telephoneNumber
lsc.tasks.FirstTask.bean = org.lsc.beans.SimpleBean
lsc.tasks.FirstTask.dn = ""
lsc.syncoptions.FirstTask = org.lsc.beans.syncoptions.PropertiesBasedSyncOptions
lsc.syncoptions.FirstTask.default.action = K
lsc.syncoptions.FirstTask.default.delimiter = $
lsc.syncoptions.FirstTask.telephoneNumber.action = F
lsc.syncoptions.FirstTask.telephoneNumber.force_value = StringUtils.replaceFromMap(srcBean.getAttributeValueById("telephoneNumber"), "telephone.csv")

I think most of properties are self-meaning, however here some explanations about few of thems

  • default.action = K, meaning the attribute is not overriden if the value is ok
  • telephoneNumber.action = F, force the attribute to be updated
  • lsc.syncoptions.FirstTask.telephoneNumber.force_value= StringUtils.replaceFromMap(srcBean.getAttributeValueById(“telephoneNumber”), “telephone.csv”) is the code to compute the new value of the telephoneNumber attribute. In that case, I use a CSV files where I specify two fields: the pattern, and the value to replace if the pattern is found. (i.e. “^21,014070”)

Output in dryrun mode


% ./bin/lsc -n -f etc -s FirstTask
juil. 21 16:24:43 - WARN - Starting sync for FirstTask
juil. 21 16:24:43 - INFO - Connecting to LDAP server ldap://sun_hostname:389/dc=rtl,dc=fr anonymously
juil. 21 16:24:44 - INFO - Connecting to LDAP server ldap://ad_hostname:389/dc=activedirectory,dc=domain as admin@activedirectory.domain
juil. 21 16:24:44 - WARN - The method getAttributeValueById() is deprecated and will be removed in a future version of LSC. Please use getAttributeFirstValueById() instead.
juil. 21 16:24:44 - DEBUG - Update condition false. Should have modified object CN=BONFILS Bruno,OU=Users,DC=activedirectory,DC=DOMAIN
dn:: CN=BONFILS Bruno,OU=Users,DC=activedirectory,DC=DOMAIN
changetype: modify
replace: telephoneNumber
telephoneNumber: 0140704049

juil. 21 16:24:44 - INFO - All entries: 1, to modify entries: 0, modified entries: 0, errors: 0

Categories: IAM Tags:

OpenSSO strict cookie value

February 22nd, 2010 1 comment

At my work, we’re currently working on a new J2EE platform to host our webapp applications, based on Tomcat 6 (6.0.24 to be precise). After deployed few fully public webapps without any issue, we start to deploy some other webapps with an authenticated part. The authentication is based on OpenSSO, using REST APIs. The cookie is created to OpenSSO, then set (client side) by one of our own webapplication. This cookie is validate using isValidToken REST API on every application the user goes. However, we’re not able to get authentication working on the preproduction environment, while it working perfectly on the dev environment. After some investigations with the developpers, we notice the OpenSSO’s cookie value was truncated.

After reading this post on the tomcat’s user mailing list, we start to configure tomcat. Few hours after, I was thinking about change the tomcat configuration is only a workaround, without fixing the original problem. Thanks to the OpenSSO’s IRC channel, someone (Allan Foster) pointed me to com.iplanet.am.cookie.c66Encode configuration variable. You can enable it in the console, Configuration, servers and sites, click on default paramaters, and then advanced tab. Set the value to true, and voila! Everything is now working good!

Categories: IAM, SSO Tags:

OpenSSO, OpenID and Yubikey, the perfect personal SSO: cheap, and secure

August 3rd, 2009 1 comment

As a new owner of an yubikey, I was looking the best way to integrate it with the web application I already use. While there is already an available OpenID provider which support Yubikey authentication, I prefer to manage my own system, using OpenSSO for sure 🙂
Yubikey
First, let me introduce the yubikey. This USB key act as an OTP (One Time Password) device, each time you press the button, the key compute a new password. This pasword must be verify, in the case of Yubikey, this is done by query a Webservices on a yubico (the company) server. Yubikey offers a lot of advantages than others classical OTP devices, including:

  • The yubikey is see as an USB keyboard (class HID), no driver required!
  • No battery, more longlife than anothers devices
  • Very cheap, around 20 euros (ordered by 10, from France), transport and taxes included

So, why choose OpenSSO? For few years know, OpenSSO provides an extension to act as an OpenID provider, and an authentication class is available for the Yubikey.

OpenSSO OpenID Yubikey

References:

Categories: IAM, Security, Sysadmin Tags: , ,

How to convert a PKCS#12 to JKS

July 2nd, 2009 6 comments

Most of system administrators use OpenSSL (which is not a good idea, but it’s an another story) to manage their PKI. While OpenSSL is good to create/convert X509 certificates from PEM/DER to PKCS#12 (and vice versa, for sure) it doesn’t understand the JKS (Java KeyStore) format. JKS are used in Java world, for example Glassfish application server, OpenDS and so more. In this post, I’ll explain how to convert a PKCS#12 to a JKS using portecle. portecle is a small, but very useful application (written in Java) to manipulate keystores.

  1. Download portecle, extract it, and lauch it using java -jar portecle.jar (note that Java 6 seems required for version 1.4.x)
  2. Open your PKCS#12 file, provide the password
  3. Click on Tools/Change KeyStore Type/JKS menu
  4. If you don’t want to use the default password (which is password), click on the menu keystore password
  5. Save it, that’s all folks!

You can know list the contents of your JKS using keytool:


% keytool -list -v -keystore yourkeystore.jks

Categories: Security, Sysadmin Tags:

Soirée CloudCamp à Paris le 11 Juin

May 19th, 2009 2 comments

Comme tout le monde, vous entendez parler du cloud computing, mais vous ne savez pas forcément ce qui se cache derrière ce terme ? Vous connaissez déjà, mais vous voulez en savoir plus ? Bref, dans tous les cas, si ce sujet vous intéresse, je vous invite à participer à la soirée organiser par cloudcamp. Cette soirée aura lieu le 11 Juin, à partir de 18h30. Pour ma part, je dois y intervenir pour parler de la sécurité.

Je me permet de rappeler, pour mes fidèles lecteurs, que Solaris/OpenSolaris est très proche du concept de cloud computing notamment grâce aux containers (zones + resource shapping), et OpenStorage.

Categories: Security, Sysadmin Tags:

IAM track at LSM

May 4th, 2009 No comments

As a member of the LSM staff, I organize a track about IAM. The schedule is almost closed, including:

  • Pat Patterson, from OpenSSO, the famous Access Manager (SSO) of Identity Federation tool from Sun (english)
  • Ludovic Poitou, from OpenDS, the future Sun’s Directory Server (english or french)
  • Clément Oudot, from LemonLDAP::NG, an opensource Web SSO (english or french
  • Tomas Gustavsson, from EJBCA, the most famous opensource PKI product (english)
  • Jonathan Clarke, from LSC, a tool to synchronize directory from JDBC or LDAP (english or french)
  • Myself, introducing about IAM, especially the provisionning (french)

This day is planned for July, the 10th, at Nantes. Check LSM website to register in a near future (registration are not opened yet). For OpenDS, LemonLDAP::NG and LSC talks, the language will be choosen according the audience.

Categories: IAM, PKI, Social, SSO, Sysadmin Tags:

Petite surprise en LDAP: last successful bind

April 28th, 2009 2 comments

Un rapide poste qui je l’espère fera suite à d’autres pour exposer une petite surprise que j’ai eu avec LDAP (enfin de manière plus précises avec les serveurs). Lors d’un projet pour mon nouvel employeur, on me demanda d’installer un OpenSSO pour authentifier des utilisateurs et obtenir leurs attributs LDAP. Bon, jusqu’ici rien d’anormal. Néanmoins, dans les attributs utilisateurs, il est demandé un attribut fournissant la date de la dernière connexion d’un utilisateur (en pratique la date d’un dernier bind opéré avec succès). Sur le moment, je n’ai pas percuté. Ce n’est qu’au moment de revenir sur mon poste, et par acquis de conscience, que j’ai commencé à me renseigner.

Et quelle ne fut pas ma surprise lorsque je me suis rendu que :

  • OpenSSO ne le permet pas de base. Après une rapide rechercher, il semblerait qu’une manière simple (c’est tout relatif) est d’écrire une classe (Java) qui sera exécutée après une authentification utilisateur.
  • Active Directory semble fournir cette fonctionnalité de base (via l’attribut lastlogon)
  • Sun Directory Directory Server Entreprise Edition (DSEE pour faire court) ne semble à priori pas le supporter dans toutes ses versions (>= 6.2 de mémoire, à prendre avec grande précaution) (tests en court)
  • OpenDS le supporte (tests en court)
  • Sun iPlanet 5.x ne le supporte tout simplement pas
  • Je n’ai pas regardé pour les autres serveurs, si jamais vous avez des retours dessus, je suis preneur.

Évidemment, je vous laisse deviner quel serveur j’utilise. Donc, je me suis retrouvé à écrire un plugin (en C) pour iPlanet, j’avoue que cela est assez intéressant (enfin il y a bien pire comme tâche :). Je vais mettre à disposition le code de ce plugin d’ici quelques jours, même si je doute qu’en Avril 2009 cela intéresse encore beaucoup de gens !

Pour information, pour obtenir cette fonctionnalité avec DSEE et OpenDS, il faut utiliser les password policies, et n’activer que la partie concernée. Cela va mettre à jour le champ ds-pwp-last-login-time (au moins vrai pour OpenDS).

Néannmoins, j’avoue que je suis assez surpris que cela ne soit pas de base, partout, dans tous les serveurs LDAP. Certes, cela demande un minimum de performances supplémentaires. En effet, cela provoque une écriture (opération considérée comme lente sur un annuaire LDAP) à chaque opération d’authentification réussie (mais on pourrait imaginer de vouloir l’équivalent pour un last failure). Mais au point de vue gestion d’identité, c’est quand même une information qui peut être très intéressante. Au hasard, sur un portail public, d’obtenir rapidement, et simplement, la liste des utilisateurs qui ne se sont pas connectés depuis une année.

Categories: IAM, Security, Sysadmin Tags: ,