Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

CoqBlog

.NET is good :-)
{ Blog de Gaël Covain }

Actualités

La fonctionnalité de récupération de compte par question(s) secrète(s) rend le compte vulnérable

Via les news Microsoft Research, je suis tombé sur un article abordant le sujet des fonctionnalités de récupération d'accès à un compte utilisateur basées sur une question secrète : 'Secret' Questions Leave Accounts Vulnerable

 

Question secrète ?

Pour rappel, cette fonctionnalité (automatique) de récupération de compte basée sur une (ou plusieurs) question(s) "secrète(s)" consiste à vous demander à l'inscription de définir un (des) couple(s) question/réponse censé permettre de vérifier que c'est bien vous qui voulez récupérer le compte dont vous avez perdu le mot de passe et pas une tierce personne.

 

Cela pose un problème ?

Le problème avec la question secrète est la faiblesse qui découle du créneau sur lequel se positionne cette fonctionnalité : nous sommes censés utiliser comme réponse quelque chose que nous retiendrons facilement, quelque chose que nous reviendra immédiatement en mémoire à la vue de la question.

En tant qu'utilisateur lambda (non paranoïaque), nous allons donc sans doute utiliser quelque chose de personnel.
La réponse sera simple, car nous n'allons pas utiliser la fonctionnalité tous les 2 jours, donc nous risquerions d'oublier la forme de la réponse si elle est trop compliquée.
Pire : certaines implémentations de la fonctionnalité ne nous laisserons même pas poser la question de notre choix mais nous forcerons à en choisir une dans une liste qui sera suivant les cas plus ou moins consternante de simplicité, et massivement orientée vie personnelle :

  • Quel est le nom de jeune fille de notre mère ?
  • Quel est/était le nom de notre premier animal de compagnie ?
  • Quel est le prénom/date de naissance de notre premier enfant ?
  • Quel était notre premier employeur ?
  • ...

Secret quoi...
Dans le cas du nom de jeune fille de la mère, il n'y a jamais que le cercle familial au sens large qui soit au courant de ce genre de choses.
Dans le cas du prénom ou de la date de naissance du premier enfant, on ne peut rajouter au cercle familial que l'intégralité des personnes ayant accès au bureau sur lequel trône la photo des enfants ainsi que celles à qui nous avons annoncée la bonne nouvelle le jour J.
Dans le cas du nom du premier animal de compagnie, ça sera peut être plus restreint côté cercle familial, par contre si c'est le premier il y a des chances que nous ayons été jeunes à cette époque, dotés d'une énorme inspiration pour les noms d'animaux...
Le premier employeur se trouve sans doute dans notre CV.

En plus, nous sommes depuis quelques temps en pleine explosion du phénomène d'adhésion à des réseaux sociaux : il ne s'agit plus d'un simple outil professionnel mais d'un outil grand public.
Du coup avoir accès (ou des pistes pour deviner) à ce genre d'informations personnelles d'un utilisateur normal n'est pas forcément très compliqué, même sans faire partie de ses relations proches.

 

Alternatives ?

Dans le cadre d'une entreprise ou d'un système de faible ampleur, ce type de fonctionnalité automatique peut être remplacé par l'intervention d'un être humain et la mise en place de moyens de vérification d'identité de la personne ayant oublié ses paramètres de connexion.
En cas d'impossibilité d'interaction physique, un envoi postal (la messagerie mobile étant en fin de compte de plus en plus connectée, je ne pense pas que l'on puisse toujours considérer l'envoi d'un SMS comme suffisamment sécurisé) est envisageable si le déblocage de l'accès au système n'est pas nécessaire très rapidement. Ce n'est pas parfait mais déjà plus compliqué pour un assaillant.

Dans le cadre d'un système massif et grand public, ça devient largement plus compliqué ou trop coûteux.

C'est là que semble se positionner le système décrit dans l'article : des tierces personnes physiques connues d'une des parties (en l'occurrence nous et non pas l'entreprise) reçoivent des bribes d'informations dont nous devons récupérer plusieurs exemplaires pour pouvoir effectuer le déblocage, ce qui devrait remplir la fonction de vérification d'identité.
Encore faut-il que ces personnes soient un minimum informées, conscientes de leur rôle, l'accepte et le remplisse avec un minimum de sérieux afin de ne pas non plus donner l'information à n'importe qui : ils sont censés s'assurer que c'est bien nous qui la demandons.
Il faut aussi que le délai de récupération du compte ne soit pas critique, car en faisant intervenir plusieurs êtres humains on s'expose forcément à des délais beaucoup plus grands.

 

Je n'ai pas encore eu le temps de lire le document "It's no secret, Measuring the security and reliability of authentication via ‘secret’ questions" que j'ai fini par trouver sur la page dédiée à la conférence Security and Human Behaviour 2009 (11 juin / Session 2 Fraud / Stuart Schechter, Microsoft), mais il devrait être intéressant. Quand au second document cité dans l'article, je ne sais pas où il se trouve (ni même s'il est disponible en fait).

Bref, sujet à creuser sans doute, je n'ai pas eu le temps d'approfondir plus que cela pour l'instant mais l'information m'a semblé bonne à transmettre :-)

Nouvelle version de l'outil VMMap (Sysinternals) : affichage d'informations liées au CLR .NET

On ne s'en sert pas tous les jours de celui là, mais autant savoir qu'il affichage maintenant des informations liées à l'utilisation mémoire par le CLR, ça peut servir :

VMMap 2.0 : vue d'un processus Visual Studio 2008

Crash systématique d'Internet Explorer (IE8 en l'occurence) à l'ouverture d'un site

Je me suis dernièrement retrouvé avec un poste sur lequel IE8 crashait (dans urlmon) systématiquement à l'ouverture du site impots.gouv.fr (ça tombe bien en cette période de déclaration :p, mais en fin de compte ce n'est pas directement lié à ce site).

Lancer IE sans addins, sans DEP, etc n'a strictement rien changé mais après avoir creuser quelques pistes, il a été déterminé que ce crash n'intervenait que sur un seul compte utilisateur.

Le log Application contenait l'entrée suivante :

Application défaillante iexplore.exe, version 8.0.6001.18702, module défaillant urlmon.dll, version 8.0.6001.18702, adresse de défaillance 0x0003e819.

Dans le cas présent, la reproduction du problème avec un debugger attaché et une analyse rapide m'a permit d'obtenir une piste assez rapidement (pas besoin d'un bon niveau d'utilisation de cdb, windbg & co : assurez vous juste de bien charger les symboles publics et utilisez !analyze pour obtenir entre autres la stack) :

STACK_TEXT: 
020bca34 1a41fc23 020bcac8 020bd090 001b3750 urlmon!CSecurityManager::CheckMappings+0x1cc
020bca54 1a41fe15 020bcac8 020bd090 04332120 urlmon!CSecurityManager::CheckHKCUMappings+0x1d
020bca70 1a412d6d 020bcac8 020bd090 00000000 urlmon!CSecurityManager::CheckSiteAndDomainMappings+0x52
020bca90 1a41307d 020bcac8 020bd090 00000000 urlmon!CSecurityManager::_MapComponentsToZone+0xe7
020bcf94 1a412f7a 037f9540 020bd090 00000000 urlmon!CSecurityManager::_MapUrlToZoneDirect+0xa0
020bcfd8 1a412b3f 037f9540 020bd090 ffffffff urlmon!CSecurityManager::MapUrlToZoneEx2Internal+0x120
020bd008 1a4140ee 037f9540 020bd090 00000000 urlmon!CSecurityManager::GetZoneFromUri+0x9a
020bd03c 1a4565b0 037f9540 037f9540 020bd090 urlmon!CSecurityManager::MapUrlToZoneEx2+0xf2
020bd088 1a41790e ffffffff 037f9540 00000000 urlmon!ShouldUseEmulateIE7ModeForIntranet+0x61
020bd0d8 63597c2e 04332120 037f9540 00000000 urlmon!MapUriToBrowserEmulationState+0x12a
020bd0fc 635b1dd5 020bd118 00000000 020bd230 mshtml!CMarkup::GetEmulationState+0xd8
...

Voir des appels MapUrlToZone, GetZone etc nous fait aller directement dans la boite de dialogue de configuration des sites de confiances, pour y trouver ceci :

Internet Explorer : boite de dialogue "Sites de confiance" 

Normalement ce type de configuration n'est pas possible via le GUI (refus d'entrée en double) mais je suppose que dans le cas présent il s'agit d'un problème lors de la migration d'IE7 à IE8.
Les entrées du registre (regjump HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains) qui correspondent à cette configuration sont bel et bien "différentes", un truc a peut être changé dans l'interprétation entre 2 versions :

Vue du registre

Bref, en cas de crash dans urlmon et plus particulièrement dans CSecurityManager::CheckMappings, vérifiez les sites de confiance (dans IE, pas en modifiant directement le registre), leur paramétrage existant peut en être la cause.

Donc, aucun lien direct avec le site impots.gouv.fr qui n'est en rien responsable du problème, mais je pense plutôt que c'est un problème de migration.

 

PS : Pour la petite histoire, la présence de cette entrée dans les sites de confiances doit dater de mes tentatives de compréhension d'un échec sur les premières versions du site quand l'utilisateur était normal (non administrateur de la machine...) : la signature de la déclaration échouait sans identifier explicitement le problème.
En fin de compte il s'agissait simplement d'un problème de droits sur le système de fichiers (merci FileMon et/ou Process Monitor) : de mémoire, il y avait tentative d'écriture dans un répertoire temp situé sous le répertoire d'installation de Java (oui, un répertoire commun à tous les utilisateurs...), ce qui forcément échouait avec des profils utilisateurs standards.
Comme quoi lors de tentatives de résolution d'incident, il faut toujours noter ce que l'ont fait pour faire le ménage derrière, une fois le problème réel identifié !

Fichiers PDB : "Ce que tout développeur doit savoir"

Juste un relai d'un post de John Robbins (en anglais donc) à propos de ces fameux fichiers PDB, des Symbol Server et Source Server (si vous avez lu son fameux livre Debugging .NET 2.0 Applications, vous avez déjà un peu conscience du sujet).
Même si ce genre d'information ne sert pas forcément tous les jours, il est toujours bon de l'avoir lu à un moment afin d'avoir le réflexe "j'ai déjà lu un truc à ce sujet !" et approfondir à ce moment là.

John Robbins : PDB Files: What Every Developer Must Know

Are You Certifiable ?

Je ne me souviens plus trop de où j'en ai entendu parler, mais si vous voulez vous amuser à tester vos connaissances sur les technologies Microsoft en anglais, vous pouvez aller ici : Are You Certifiable?

PS : Vous pourrez même être représenté(e) par ce bon vieux trombone... :p

A propos des mots de passe stockés en clair & co

Cet article n'a pas pour but de présenter les meilleures solutions de stockage de mots de passe, que je ne maitrise pas forcément non plus, mais seulement d'avancer des idées/arguments montrant que celle consistant à les stocker en clair (lisible) n'est vraiment pas la bonne.

Dans le cas d'un système autonome, il n'y a à ma connaissance aucune raison valable de le faire. Nous n'avons absolument pas besoin de pouvoir lire ce mot de passe, la seule personne devant en connaître la forme lisible est son propriétaire.
La seule chose qui nous importe est de savoir si le mot de passe que nous fourni l'utilisateur est le même que celui qu'il a défini à l'origine : nous pouvons donc nous contenter de faire notre comparaison sur les empreintes de mots de passe.

Dans le cas d'interconnexion avec d'autres systèmes, on pourrait considérer comme raison valable le fait que notre système doit utiliser ces mêmes informations pour effectuer une authentification sur un autre, mais là je dirais qu'il serait peut être temps de voir pour déléguer cette procédure à un système spécialisé, comme c'est le cas par exemple sur un domaine.
Toutefois si ce n'est pas envisageable et que nous devons transmettre le login/mot de passe de l'utilisateur dans leur forme originelle, nous devons utiliser une forme de stockage cryptée pour limiter au maximum le périmètre dans lequel cette information est lisible.
Et dans ce cas, il serait aussi bon de réfléchir à la réelle nécessité de stocker cette information de façon à pouvoir la retransmettre : ne serait-il pas envisageable de stocker le hash et en cas d'authentification réussie transmettre non pas l'information stockée mais celle saisie ?
Si les transferts doivent être différés, l'information peut être conservée en mémoire volatile, toujours de manière cryptée afin de ne pas avoir de fuite dans des dumps mémoire, durant le transfert vers un cache distribué, etc

Je me placerais pour le restant de l'article dans le contexte d'un système autonome, et prendrais le hash comme alternative au stockage en clair en laissant de côté le cryptage.
Nous aborderons aussi quelques éléments plus ou moins liés à cette gestion de mot de passe.

 

 

Quels sont les différentes formes de stockage que nous pouvons utiliser ?

Les différentes formes de stockage envisageables pour un mot de passe sont :

  • en clair :
    l'information est directement lisible sous sa forme originelle
  • sous forme cryptée :
    la forme originelle de l'information peut être récupérée, mais pour cela il faut en posséder la clé
  • sous forme d'un hash : la forme originelle de l'information est perdue, on ne fait qu'en conserver une empreinte

C'est là la principale chose à retenir à propos du hash : c'est une empreinte de la donnée, pas la donnée.

 

 

Mais quel est le problème avec les mots de passe stockés en clair ?

Dit simplement : le vol d'identité est plus simple que si nous stockons un hash.
Sans tenir compte d'éventuelles failles de sécurité permettant de contourner le système d'authentification, on peut relever plusieurs faits.

L'attaquant n'a pas besoin du même niveau d'accès dans les deux cas
Pour se faire passer pour un utilisateur, en utilisant le système cible de manière tout à fait normale, les accès au stockage des données requis sont :

  • mot de passe stocké en clair : accès en lecture suffisant.
    Il suffit de lire le mot de passe pour pouvoir le saisir en entrée du système cible.
  • mot de passe stocké sous forme de hash (non réversible) : accès en écriture nécessaire.
    En partant du principe que l'attaquant connait la méthode de hash utilisée (ne surtout pas partir du principe qu'il ne la devinera pas), il devra pouvoir procéder à l'écrasement du hash avec un nouveau correspondant au mot de passe désiré.

L'attaquant à normalement plus de chances d'obtenir un accès en lecture seule à l'information qu'un accès en écriture, du moins je l'espère.
L'accès en lecture seule peut notamment être indirect, via des backups de base de données qui seraient moins bien protégés que le système principal, le contenu de scripts, des dumps mémoire, etc
Et sans avoir l'accès direct au stockage des backups, il peut aussi y avoir accès via le moyen de transport de ces derniers s'il n'est pas sécurisé.
S'il dispose d'un accès en lecture aux hashs, il devra encore mettre en oeuvre des traitements pour déterminer quelle chaine de caractères donne ce hash. Ceci peut être couteux en temps, et avec une bonne politique de changement de mot de passe il trouvera peut être la version en clair trop tard pour l'exploiter.

Et si l'attaquant faisait partie de notre service informatique ?
En quoi les personnes ayant, par leur fonction, accès à nos bases de données sont plus digne de confiance qu'une personne externe ?
Ne vont t'il jamais quitter notre entreprise ? Sont-ils seulement directement nos employés ?

Cela nous amène à un autre fait.

La détection du vol d'identité est moins évidente dans un cas que dans l'autre
Les chances que l'utilisateur dont l'identité a été volée s'aperçoive du problème sont moins élevées dans le cas du stockage en clair :

  • mot de passe stocké en clair : si l'attaquant ne laisse pas de trace de ses actions, l'utilisateur ne s'en apercevra peut être jamais
    Dans le meilleur des cas il change son mot de passe régulièrement, mais si l'attaquant a toujours accès en lecture au stockage, cette politique de changement ne fera que le ralentir sans l'arrêter.
  • mot de passe stocké sous forme de hash (non réversible) : suivant la fréquence d'utilisation du service par l'utilisateur ce peut être rapide, vu qu'il n'arrivera plus à s'authentifier avec son mot de passe habituel.
    Il y a de grandes chances qu'il finisse par râler, le tout étant que les équipes de support ne fassent pas un simple changement de mot de passe forcé sans creuser/tracer.

 

 

Inconvénients du stockage du mot de passe sous forme de hash par rapport au stockage en clair ?

Un "inconvénient" de ce mode de stockage est que nous perdons toute possibilité de renvoi de son mot de passe originel à l'utilisateur.
S'il déclare l'avoir perdu, nous sommes obligés de lui en fournir un nouveau que nous générons. 
Nous assortirons cette génération d'une gestion de péremption et nous obligerons l'utilisateur à changer de mot de passe au premier accès : nous l'aurons probablement transmis par mail ou un autre moyen potentiellement non sécurisé.

Avantage de cet inconvénient : nous avons de fait perdue toute possibilité de comportement dangereux du type rappel régulier de son mot de passe à l'utilisateur, système que vous avez probablement déjà observé pour des comptes du genre abonnement à une newsletter par exemple : envoi régulier du mot de passe avec la newsletter.

 

 

Comportement dangereux : incorporation du mot de passe en mail de confirmation

Même si nous stockons des hashs, il reste une chance pour ce comportement dangereux d'incorporation en clair dans une communication : insertion du mot de passe dans le mail de confirmation de création de compte. 
Nous avons encore une "chance" de le faire si jamais notre procédure d'envoi de mail de confirmation est directement liée au processus de création de compte utilisateur.
C'est mal.

Pourquoi donner à l'utilisateur l'information qu'il connait car il vient de la saisir 2 fois ?
A quoi bon changer de mot de passe si le simple fait de le faire oblige l'utilisateur à le refaire (boucle infinie...) car il a été dévoilé ?

Voulons-nous vraiment obliger l'utilisateur à considérer notre système comme à risque et à nous fournir un mot de passe simple car il n'a pas envie d'en retenir un qu'il sait en danger ?

Au pire si l'utilisateur oublie entre temps, que ce soit parce qu'il est parti longtemps avant de traiter le mail ou juste par manque de célérité de notre système d'envoi, ça lui donnera une bonne occasion d'utiliser notre fonctionnalité de récupération (qui pour rappel génère avec délai de péremption et oblige à changer de mot de passe au premier accès).

 

 

La règle "Utiliser un mot de passe par système" et la réalité...

Cette bonne pratique part d'un bon sentiment, mais dans les faits a, à mon avis, peu de chances d'être respectée.

L'utilisateur lambda :

  • ne sais pas qu'elle existe
  • sais qu'elle existe mais n'en a rien à faire
  • n'a pas conscience que son mot de passe peut être connu de quelqu'un d'autre
  • a déjà suffisamment de mal à en retenir un compliqué, alors il le met partout

L'utilisateur avancé ayant connaissance de cette bonne pratique a quand à lui trop de différents comptes utilisateur sur différents système pour retenir une telle masse de mots de passe.

On peut à mon avis avoir dans ce cas affaire à deux écoles :

  • celle consistant à stocker les mots de passe uniques de manière sécurisée par un mot de passe global y donnant accès.
  • différents mots de passe sont utilisés plusieurs fois selon l'importance des systèmes et le niveau de "sacrifiabilité" du mot de passe (si nous avons envoyé son mot de passe en clair à ce type d'utilisateur, je vous laisse deviner de quel type de mot de passe nous allons écoper...).

Ceci nous amène à l'importance du concept de "salt" lors de l'obtention du hash de mot de passe de l'utilisateur.

 

 

A propos de l'utilisation d'un "salt" lors de l'obtention du hash à stocker

Le salt est une information UNIQUE PAR UTILISATEUR que nous pouvons stocker en clair (à la rigueur cryptée, le tout étant de pouvoir en obtenir sa forme originelle), elle doit justement être lisible.
Le salt n'a pas besoin d'être humainement lisible : nous pouvons utiliser un générateur du type RNGCryptoServiceProvider pour le déterminer.
Cette valeur n'intervient que durant une phase : l'obtention du hash, qu'il s'agisse de celle à l'enregistrement en base ou de celle au moment de la vérification d'identité de l'utilisateur.
Son rôle est tout simplement de compléter le mot de passe fournit par l'utilisateur afin de nous assurer que le hash obtenu pour un même mot de passe sera différent.

Le problème avec le hash sans salt
Pour illustrer, prenons le cas de Jean et Paul.
Ils ne se connaissent pas, mais ont tous les deux les mêmes goûts en terme de mot de passe : "toto#titi!tata". 
Nous utilisons un hash SHA512 sans salt, nous obtenons en sortie (Base64) :

Jean :
7KWJOnnYabt9pmwzP/qRAiPAplLlG/vZ37G7NlRh+J8rrE+7jcgF0rGQcXPeMiuQEOXZlaRqeIo+h15aJEwWEw==
Paul :
7KWJOnnYabt9pmwzP/qRAiPAplLlG/vZ37G7NlRh+J8rrE+7jcgF0rGQcXPeMiuQEOXZlaRqeIo+h15aJEwWEw==

Ils sont bien entendu identiques, c'est là tout l'intérêt du hash : à jeu de données identique, hash identique, sinon impossible d'authentifier l'utilisateur.
Vous devez maintenant avoir compris l'intérêt du hash.

Si jamais nous avons plusieurs utilisateurs possédant le même mot de passe, l'attaquant peu le deviner grâce aux hashs : il ne sait pas encore ce qu'est le mot de passe réel, mais sait maintenant que s'il parvient à déterminer le mot de passe correspondant à ce hash, il aura accès à plusieurs comptes.
En se concentrant sur les comptes possédant des hash identiques, il augmente ses chances de réussite car si Jean change son mot de passe entre temps, peut être que Paul ne le fera pas.

Mais il y a pire : il y a de fortes chances que quelqu'un d'autre utilise le même algorithme de hash que nous, au sein de notre SI comme ailleurs.
Si nos utilisateurs ont aussi un compte là bas (ou tout simplement que d'autres utilisateurs ont le même mot de passe) et que l'attaquant à déjà compromis cet autre système, il a déjà accès à plusieurs de nos comptes utilisateur.

Sans aller jusqu'à ce "manque de chance", il y a d'autres menaces : il existe de grosses bases de données (connues sous le nom de "Rainbow tables") contenant des valeurs de hashs calculés à partir de mot de passe potentiels. Elles permettent ainsi de faire rapidement le parallèle entre un hash et le mot de passe correspondant.

Donc, utilisons un salt
Le principe est simple : nous allons tout simplement générer une valeur unique (j'insiste bien : unique, un salt commun à tous les utilisateurs serait bien entendu aussi efficace que pas de salt) que nous ajouterons au mot de passe saisi par l'utilisateur avant d'obtenir le hash.

En prenant les salts suivants (vous n'êtes bien sûr pas obligé de passer par un salt sous forme de chaîne de caractères) :
Jean : "Jpf0ZrIOSX2ZebuI52nfow=="
Paul : "kcbIrxcdNC7pQMCkR+pazQ=="

Pour Jean, nous demandons le hash de "toto#titi!tataJpf0ZrIOSX2ZebuI52nfow==" :
70bQc07fYCDVyduPajGQ5piprIROrBEw7oY8tP/hczwqtYSTJFBi5jsqEywShb7+dhb5xujkn9rejeMWWj0hZQ==
Pour Paul, nous demandons le hash de "toto#titi!tatakcbIrxcdNC7pQMCkR+pazQ==" :
uW/oOqh0R/JPBloWsMASmYAmHwVsZo+VuNRN4FXuJFPwACZ/BHH/wvrrkdDBgLAO+D3HvdnLkDcZ9M5j39WsBg==

Pour un même mot de passe, les 2 hashs sont distincts : nos utilisateurs peuvent maintenant avoir des mots de passe identiques sans que cela soit devinable dans la liste des hash stockés.
Comme nous stockons le salt de manière lisible, nous pouvons renouveler l'opération au moment de la tentative d'authentification de l'utilisateur : si le mot de passe saisi est bon, le hash sera identique à celui stocké.

Nous avons aussi réduit les chances de réussite de l'attaquant lors de l'utilisation d'une Rainbow table : il faudrait démultiplier le volume de la liste de référence pour avoir les combinaisons de mot de passe avec salt, et vu que notre salt est quelque chose totalement aléatoire...

L'utilisation d'un algorithme de hash produisant une quantité de données importante peut aussi être bénéfique dans le sens que ce type de table de correspondance devra stocker une énorme quantité de données, alors que de notre côté un doublement de volumétrie sur les comptes utilisateurs n'est peut être pas très important.
Il en va de même avec le temps nécessaire au calcul du hash (temps naturel : ralentir artificiellement le code de calcul ne sert à rien car l'attaquant n'utilisera pas notre code mais une version optimisée) : si nous utilisons un algorithme gourmand en temps, nous ajouterons un peu de temps sur nos opérations (probablement insignifiant au regard du reste de nos traitements), mais énormément de temps sur celles de l'attaquant en cas de brute force. Au pire, par mesure de prudence, prévoir tout de même une limitation du nombre de tentatives de logon par laps de temps.

 

 

Une fonctionnalité dangereuse : la "phrase secrète"

S'il y a bien une fonctionnalité que je déteste c'est celle là, du moins dans sa forme automatique.
On nous demande de définir une question et la réponse à cette question afin de pouvoir procéder à la récupération de notre mot de passe.

A mes yeux le seul intérêt réel de cette fonctionnalité est du côté de l'attaquant : ça peut lui faire gagner du temps.

Déjà, cette fonctionnalité ne peut fonctionner qu'avec un mode de stockage permettant de récupérer le mot de passe sous sa forme lisible : en clair ou crypté donc, nous pouvons oublier le hash du coup.
Ensuite, on le récupère pour en faire quoi ?
L'envoyer à l'utilisateur par mail ? Voir remarques plus haut.
L'afficher à l'utilisateur au travers d'une connexion sécurisée ? Affiché... à l'écran... et si quelqu'un d'autre regarde dans le dos de l'utilisateur ?
Une chose est sûre : si nous donnons son mot de passe à l'utilisateur, il ne risque pas de la changer après l'avoir récupéré... Et même dans le cas contraire, autant passer quand même par une génération de mot de passe temporaire.

Soyons réalistes : je doute que l'utilisateur lambda pense toujours à spécifier une question et une réponse compliquées.
Quand à l'utilisateur avancé je pense qu'il risque fortement de procéder un peu comme moi quand on m'oblige à spécifier ces éléments (...) : question "Hu ?" et réponse que même moi je serais incapable de donner.
Intéressant comme système, surtout quand certains d'entre eux ne nous laissent même pas la question libre mais nous fournissent à la place une liste de question d'une simplicité plus ou moins consternante du genre :

  • Prénom de la grand mère / du grand père
  • Nom du premier animal de compagnie
  • Prénom du premier enfant
  • ...

Nous partons donc du principe que l'attaquant n'est en aucun cas un proche plus ou moins direct de l'utilisateur ?
Et même sans cela : n'oublions pas qu'à notre époque les réseaux sociaux sur internet sont à la portée de n'importe qui, du coup obtenir des informations sur la vie de l'utilisateur n'est pas bien compliqué si ce dernier n'est pas un minimum prudent et si l'attaquant sais ce qu'il cherche.

Petit bémol :
Si la récupération du mot de passe réel est nécessaire, par exemple pour des raisons de perte de données en cas d'écrasement du mot de passe (cryptage dont la clé serait le mot de passe, ...), il faut alors que la procédure de récupération ne soit pas automatique : nous devons faire intervenir dans le processus un être humain à même de vérifier l'identité du demandeur, et obliger ce dernier à changer de mot de passe après récupération.

 

 

Conclusion

Je pense qu'on peut dire que le stockage en clair est à proscrire totalement.

Le choix de stocker un hash et non une forme lisible (en clair ou cryptée) n'est pas seulement une histoire de limitation des risques de vol d'identité, il y a aussi une notion de respect de l'utilisateur : le mot de passe est quelque chose que vous devez considérer comme faisant partie de la sphère très privée que seul lui doit connaitre (sauf choix volontaire de sa part).

 

Merci à Vincent pour la relecture et les compléments !

Code Canvas : visualisation spatiale de code

Kael Rowan a publiée une vidéo basée sur une ancienne version (novembre 2008) d'un prototype de visualisation de code :

Ca peut être intéressant comme jouet.
Si vous voulez vous tenir au courant des nouvelles concernant ce projet, je pense que Kael Rowan en parlera sur son blog.

Kael Rowan : Code Canvas

Des cmdlets BITS (Background Intelligent Transfer Service) dans PowerShell V2

Je viens de le voir dans un post sur le blog du team PowerShell, et un autre sur le blog WMI : PowerShell V2 contiendra des cmdlets de contrôle de BITS (Background Intelligent Transfer Service), service très pratique pour le transfert en tâche de fond (Windows Update s'en sert) mais qui n'était pour l'instant pas forcément simple d'accès.
Des GUIs tels que celui de Matevz Gacnik existaient, et pour de l'ajout de masse il existait bitsadmin, mais avec des cmdlets PowerShell, ça devrait être plus sympa.
Ces cmdlets semblent déjà présentes dans la CTP3, mais je n'en ai pas sous la main pour tester.

- Windows PowerShell Blog : Transferring (Large) Files Using BITs
- Windows Management Infrastructure Blog : Introducing BITS PowerShell Cmdlets!

Network Monitor : parser TDS (Tabular Data Stream de SQL Server) disponible

Voilà une nouvelle qui pourrait intéresser ceux qui aiment creuser profond : un parser Network Monitor pour le protocole TDS de SQL Server est disponible dans la version 3.3.1551 (et supérieures donc) des parsers distribués sur CodePlex : Network Monitor Open Source Parsers

Avant c'était juste un stub, maintenant c'est un parser plus complet.

Avant, avec le stub :

Affichage d'une capture, avant activation du parser TDS complet

Maintenant, avec le parser complet :

Affichage d'une capture, après activation du parser TDS complet 

Bref, le genre de chose qui ne sert pas forcément tous les jours pour l'utilisateur lambda, mais qui peut s'avérer pratique à savoir le jour où...

Pour avoir accès au parser complet, après installation, n'oubliez pas d'aller vérifier dans les options que la catégorie Windows est bien en mode Full et non pas Stubs :

Option de parser de Network Monitor

Si vous devez modifier ce paramètre, déclenchez ensuite le rechargement des parsers.
Amusez vous bien.

TechDays 2009 : les vidéos des sessions sont disponibles

Pour ceux qui n'ont pas pû se rendre aux TechDays cette année, et même les autres, je viens de voir que les vidéos des TechDays 2009 sont maintenant disponibles.

Vous pouvez les télécharger pour visionnage hors ligne, mais toujours en 3 parties par session.

Webcasts des Microsoft Techdays 2009 : le rendez-vous des professionnels de l'informatique en video

Tech·Days Developer 2009 : 24H de TechDays virtuels

Le 1er avril 2009 se déroulera une conférence virtuelle de 24H (mondiale), qui devrait proposer plus de 90 sessions, principalement en anglais comme vous vous en doutez.

Virtual TechDays 2009 - TechDays Defy All Challenges

Avis aux motivés, les inscriptions sont ouvertes !
Plus de détails ici : Tech·Days Developer 2009 – Defy All Challenges 24-Hour virtual event

PS : je me demande combien de personnes croiront à une blague.

Une énumération (enum en C#) énumère, mais ne donne pas de garantie

S'il y a un aspect des énumérations qui est méconnu (et j'ai moi même fait ce type de mauvaise supposition par le passé), c'est bien le fait que l'utilisation d'un enum pour une propriété, un paramètre (etc) ne garanti PAS l'obtention d'une valeur valide de cette énumération.

Vous pouvez voir cette information en autres au travers de guidelines à propos de la définition d'énumération et de gestion de leur évolution, comme c'est le cas dans ce post de Krzysztof Cwalina, et dans le livre Framework Design Guidelines dont la seconde édition est sortie récemment.
Ces guidelines abordent divers sujets comme la nécessité de traiter de manière particulière la valeur 0, mais dans ce post nous allons nous pencher un peu plus sur cet aspect de non garantie de validité qu'il faut prendre en compte lors du développement d'API utilisant des énumérations, surtout si elle est publique.

 

 

Une énumération énumère, mais ne donne pas de garantie

Je pense que cette petite phrase peut aider à mémoriser ce caractère : "Une énumération énumère, mais ne donne pas de garantie"

En effet, le code suivant est tout à fait valide (tout du moins d'un point de vue compilation et exécution, mais côté logique ça peut coincer) :

class Program
{
  /// <summary>
  /// Liste des valeurs possibles.
  /// </summary>
  public enum ValeursPossibles : int
  {
    Un = 1,
    Deux = 2,
    Trois = 3
  }

  static void Main(string[] args)
  {
    // Normal
    DoSomething(ValeursPossibles.Un);
    DoSomething(ValeursPossibles.Deux);
    DoSomething(ValeursPossibles.Trois);

    // Déjà beaucoup moins normal
    DoSomething((ValeursPossibles)(-1));
    DoSomething((ValeursPossibles)(Int32.MinValue));
    DoSomething((ValeursPossibles)(Int32.MaxValue));

    // L'absence de l'attribut Flags n'exclu pas les opérations de ce type
    DoSomething(ValeursPossibles.Un | ValeursPossibles.Deux );
    DoSomething(ValeursPossibles.Un | (ValeursPossibles)256);
  }

  public static void DoSomething(ValeursPossibles valeur)
  {
    Console.WriteLine("DoSomething : {0} ({0:D})", valeur);
  }
}

Ce qui donne la sortie :

DoSomething : Un (1)
DoSomething : Deux (2)
DoSomething : Trois (3)
DoSomething : -1 (-1)
DoSomething : -2147483648 (-2147483648)
DoSomething : 2147483647 (2147483647)
DoSomething : Trois (3)
DoSomething : 257 (257)

L'utilisation d'une énumération ne vous libère pas de la validation des valeurs attendues.
Il faut voir l'énumération comme une simplification lors de la saisie/lecture du code et un moyen de réduire les erreurs involontaires par présentation d'une liste de valeurs possibles facilement identifiables, tant par les développeurs que par leurs outils (contrairement à des solutions du type constantes).

Elle n'empêchera en rien un utilisateur malintentionné de tenter de faire des dégâts.

 

 

Comment valider ?

L'utilisation de Enum.IsDefined pour vérifier simplement la liste des valeurs définies par l'énumération est déconseillée par certaines guidelines, comme justement celles citées plus haut.
Cette méthode est déconseillée tant pour un éventuel problème de coût à l'exécution que pour le fait qu'elle ne permet pas de gérer certains aspects de cette validation, notamment celles liées à l'évolution possible de l'enum sans pour autant que l'ensemble du code l'utilisant évolue lui aussi.

A mon avis en validant les entrées, il faut se poser ce type de questions :

  • est-ce que je dois autoriser n'importe quelle valeur définie dans l'énumération, y compris les ajouts futurs ?
  • est-ce que je dois autoriser n'importe quelle valeur définie dans l'énumération, mais pas les ajouts futurs ?
  • au moment d'écrire le code, une valeur de l'énumération est invalide dans mon cas : est ce que je dois autoriser n'importe quel ajout futur ?

Ce type de question va orienter votre choix de méthode de vérification, qui peut, je pense, être imagé de la manière suivante :

Diagramme illustrant le choix d'une méthode de vérification

"Nous maitrisons, personne chez nous ne passera de valeur invalide !"
Et si un jour ça venait à être exposé au travers d'un service web ou d'un service WCF ?
Avec une valeur invalide, les proxies générés devraient échouer dans leur tentative d'envoi, par contre un message bâti à la main pourrait passer (dans le cas d'un service web la simple page de test permet d'envoyer une valeur invalide).
Dans tous les cas, une validation uniquement côté client ne peut être considérée comme suffisante.

Une simple vérification par plage peut prendre cette forme :

public static void DoSomethingSafe(ValeursPossibles valeur)
{
  // Validation du paramètre valeur
  if (valeur < ValeursPossibles.Un || valeur > ValeursPossibles.Trois)
  {
    throw new InvalidEnumArgumentException(
      "valeur", 
      (Int32)valeur, 
      typeof(ValeursPossibles)
      );
  }

  Console.WriteLine("DoSomething : {0} ({0:D})", valeur);
}

 

 

Et si je levais une exception en cas de valeur invalide ?

Vous l'avez sans doute vu dans l'exemple ci-dessus, si vous souhaitez lever une exception en cas de spécification de valeur invalide à votre API, au lieu d'utiliser une simple ArgumentException vous pouvez opter pour un type d'exception plus spécifique : InvalidEnumArgumentException

Le type InvalidEnumArgumentException est défini dans l'assembly System.dll (contrairement à ArgumentException défini directement dans mscorlib.dll), sous l'espace de nom System.ComponentModel.

WinForms au design time : Coding4Fun par Mitsu

Les développeurs WinForms ont probablement tous un jour découvert ce côté du design time, celui rendant nécessaire la fameuse propriété DesignMode.

Regarder (et testez) donc ce que Mitsu en fait, ça devrait vous rappeler quelques souvenirs : [Coding4Fun]: understanding WinForms designmode

Marrant :p

.NET 4.0 : du nouveau du côté de la gestion de certaines exceptions

La version 4 du CLR devrait apporter un changement assez important à prendre en compte, notamment en cas d'exécution d'un existant sous cette nouvelle version, au niveau de la gestion de certaines exceptions considérées comme critiques.
Critiques dans le sens où elles indiquent que ce qui a provoqué leur levée a de grandes chances de laisser le processus dans un état inconnu, avec tous les risques de corruption des données que cela comporte si l'exécution se poursuit comme si de rien n'était.

Ce changement pourrait apporter une modification de comportement assez forte pour des applications reposant sur le "fameux" code de ce type :

// NE PAS UTILISER CECI
try
{
  // ...
}
catch (Exception ex)
{
}

Le problème avec ce genre de code est qu'il étouffe n'importe quel type d'exception, même ceux qu'il ne sait pas réellement gérer.
Hors le CLR fourni les exceptions issues du SEH, comme par exemple celle signalant une violation d'accès, de la même manière que toutes les autres : elles sont donc elles aussi étouffables par le code précédemment cité.

Et c'est justement à ce niveau qu'il va y avoir du changement : pour la nouvelle version du CLR, certaines de ces exceptions qui ont été jugées susceptibles de corrompre l'état ne seront plus étouffées par ce type de code car ne seront plus gérables sauf si la méthode contenant les blocs try/catch est décorée de l'attribut System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions.

Andrew Pardoe en parle dans son article MSDN Magazine de février CLR Inside Out: Handling Corrupted State Exceptions (basé sur une version préliminaire de .NET 4.0 et de VS2010 donc), que je vous invite donc à consulter pour de plus amples informations.
Vous y trouverez aussi les informations concernant les paramètres à appliquer en fichier de configuration pour permettre aux existants (pour ceux le nécessitant réellement bien sûr) de fonctionner avec le comportement précédent.

Mais où trouver les informations de limites de support concernant les produits Microsoft ?

De temps en temps j'ai l'impression que la disponibilité publique de ces d'information n'est pas forcément connue de tous, alors qu'il pourrait être décisif de connaitre les dates de fin de support d'un produit comme, par exemple, le .NET Framework 1.1 pour des planifications de migration ou même pour des démarrages de nouveaux projets.
Un petit rappel ne peut donc pas faire de mal !

Ces informations sont disponibles à l'adresse suivante : Politique de Support Microsoft / Microsoft Support Lifecycle (la langue dépendra probablement de vos paramètres existant sur le site du support, bien que certaines pages devraient être uniquement en anglais)

Après une présentation, vous trouverez en bas de pages des liens vers les différentes manières de trouver le informations concernant le produit qui vous intéresse :

Bonnes recherches.

Humour : le problème avec les données cryptées...

Un comic xkcd qui m'a bien amusé :

xkcd - A Webcomic - Security

Ca m'a refait penser aux risques physiques potentiellement liés à la biométrie.

Comment obtenir un comportement similaire entre les commandes "cd" sous PowerShell et cmd.exe

Et c'est parti pour un post principalement destiné à ceux qui aiment le comportement de la commande cd sous PowerShell (enfin, l'alias de la cmdlet Set-Location donc) et qui se font du coup avoir par celui de la commande cd (chdir) de l'interpréteur cmd.exe (ce qui peut s'avérer relativement génant suivant la commande qu'on tape ensuite).

En effet si le répertoire courant est "C:\MonDir" et que vous tapez la commande "cd D:\Src", le résultat n'est pas le même dans les 2 cas :

  • Sous PowerShell, vous vous retrouvez dans le répertoire "D:\Src"
  • Sous cmd.exe, vous restez dans "C:\MonDir" (mais le répertoire courant pour le lecteur D est bel et bien passé à "Src")

Pour obtenir le même comportement sous cmd.exe que sous PowerShell, il suffit de taper 3 caractères en plus, c'est à dire ajouter le switch "/d" :

cd /d D:\Src

Vous me direz, c'est marqué dans la documentation, mais bon il y a des fois où on ne voit pas ce que l'on a sous le nez...

Vous rejetez WPF pour la seule raison que c'est trop orienté "multimédia" ?

Si vous n'avez vu que des démonstrations orientées multimédia et 3D, vous avez peut être un à priori négatif sur l'utilisation de Windows Presentation Foundation pour vos interfaces, qu'il serait peut être temps de réévaluer.

Parmi la liste des choses que je devais lire depuis un bout de temps il y avait l'article 10 bonnes raisons de choisir WPF d'Olivier Dahan, et j'ai justement pris le temps de le lire cette semaine : plutôt intéressant comme lecture, j'ai bien aimé.

Ca peut vous donner une nouvelle vue sur cette technologie, ne vous laissez pas décourager par le nombre de pages et même dans ce cas, lisez au moins l'introduction.

Dot.Blog | 10 bonnes raisons de choisir WPF

Posted: samedi 17 janvier 2009 12:39 par coq | 6 commentaire(s)
Classé sous : ,
Blocker Toolkit pour Internet Explorer 8 disponible

Pour ceux qui ne peuvent se permettre de voir IE8 déployé dès sa mise à disposition sur Windows Update / Microsoft Update, le blocker toolkit permettant de bloquer cette mise à jour est disponible sur le centre de téléchargement : Toolkit to Disable Automatic Delivery of Internet Explorer 8

Pour plus d'informations je vous invite à lire le post en français sur le blog TechNet de l'équipe support Windows française.

Le mirroring RAID n’est PAS une solution de sauvegarde

Ce post m'a fait repenser à cette idée dangereuse qu'une mise en miroir via une technologie RAID est amplement suffisante comme moyen de sauvegarde (backup).

Heu, non.
Je suis loin de maitriser les différents aspects de ces technologies mais s'il y a bien une chose à retenir c'est qu'il ne s'agit pas d'une alternative à une politique de sauvegarde correcte. *
Ces technologies sont là pour apporter une solution de tolérance de panne matérielle et/ou d'amélioration des performances et/ou d'augmentation de capacité.

Où est le problème avec le fait de se contenter d'un mirroring entre x disques comme seul moyen de "sauvegarde" ?

  • les x disques rendent l'âme (destruction de la machine, ...)
    vous avez tout perdu
  • un bug logiciel entraine la corruption de vos fichiers vitaux pour l'entreprise
    vous avez potentiellement tout perdu
  • une erreur de manipulation entraine la suppression de ces mêmes fichiers
    vous avez tout perdu

Le mirroring n'est pas une solution de sauvegarde : les corruptions/pertes de données sont répliquées aussi.

 

Je pense que pour bien prendre conscience du problème la question à se poser est :
En cas de sinistre, vous préférez perdre une journée (suivant fréquence de sauvegarde) de travail ou mettre la clé sous la porte ?

Je ne maitrise pas non plus les différentes solutions de sauvegarde, mais parlez en à la personne qui vous agace car elle refuse de faire concorder les privilèges sur le SI avec le niveau hiérarchique des personnes dans l'entreprise : elle doit probablement maitriser le sujet ;-)

 

* : il y a peut être, parmi les x versions plus ou moins standards, hardware ou software, une solution qui fourni des fonctionnalités de sauvegarde mais de manière générale je considère que ce n'est pas le cas

Plus de Messages Page suivante »


Les 10 derniers blogs postés

- [Perso] Découvertes estivales : Linux (Part I) par Le blog de FremyCompany le il y a 48 minutes

- [Refactoring] ReSharper pour Visual Studio 2010 (Preview) par Thomas Jaskula le il y a 15 heures et 24 minutes

- [Refactoring] Analyser vos exceptions avec ReSharper Exceptional par Thomas Jaskula le il y a 16 heures et 38 minutes

- SharePoint 2007 : patterns & practices SharePoint Guidance par Philippe Sentenac [MVP SharePoint] le 07-03-2009, 09:56

- [Visual Studio 2010] Les tests cases c’est bien, mais je vais devoir tout réécrire ? par Etienne Margraff le 07-03-2009, 09:00

- MVP[Gribouillon].AddYear par The Grib's Lair [Sébastien PICAMELOT - MVP SharePoint] le 07-03-2009, 08:45

- Clinique INSIA - Projet de fin d’Etudes (Silverlight 3 MVVM et OutOfBrowser, WCF, TFS) - Part 1 par David REI le 07-02-2009, 23:38

- C’est la crise ? Bah pourquoi cramer du budget pub alors ? par Nix's Blog le 07-02-2009, 15:31

- Soyons MVP ! par TheSaib .NET blog le 07-02-2009, 12:15

- SharePoint : Gestion des Erreurs 6398, 7076 et 6482 par Blog Technique de Romelard Fabrice le 07-02-2009, 11:53