web-dev-qa-db-fra.com

Choix d'un algorithme d'ID de session pour une relation client-serveur

Je développe une application qui a une relation client-serveur et j'ai du mal à décider de l'algorithme par lequel l'identifiant de session est déterminé. Mon objectif est d'empêcher les imposteurs d'acquérir des données privées d'autres utilisateurs.


J'envisage deux options:

Option 1: Générez une chaîne hexadécimale aléatoire de 32 caractères, stockez-la dans une base de données et transmettez-la du serveur au client lors de la connexion réussie du client. Le client stocke ensuite cet identifiant et l'utilise dans toute demande future au serveur, qui le recouperait avec l'identifiant stocké.

Option 2: Créez un hachage à partir d'une combinaison de l'heure de début de la session et du nom d'utilisateur de connexion du client et/ou du mot de passe haché et utilisez-le pour toutes les futures demandes au serveur. Le hachage de session serait stocké dans une base de données à la première demande et recoupé pour toute demande future du client.

Autres informations: Plusieurs clients peuvent être connectés simultanément à partir de la même IP, et deux clients ne doivent pas avoir le même identifiant de session.


Question: Laquelle de ces options est une meilleure approche, en ce qui concerne mes préoccupations (ci-dessous) à propos de chacune?

Ma préoccupation concernant la première option est que l'identifiant est complètement aléatoire et pourrait donc être reproduit par hasard (bien que ce soit un 1 dans un 3,4 * 1038 chance), et utilisé pour "voler" les données privées d'un utilisateur (qui devrait également utiliser le client à l'époque).

Ma préoccupation concernant la deuxième option est qu'elle présente un défaut de sécurité, à savoir que si le mot de passe haché d'un utilisateur est intercepté d'une manière ou d'une autre, le hachage de la session entière pourrait être dupé et les données privées de l'utilisateur pourraient être volées.

Merci pour toutes vos contributions.

23
FThompson

Le concept de base d'un identifiant de session est qu'il s'agit d'un nom secret de courte durée pour la session, une relation dynamique qui est sous le contrôle du serveur (c'est-à-dire sous le contrôle de votre code) . C'est à vous de décider quand les sessions commencent et s'arrêtent. Les deux caractéristiques de sécurité d'un algorithme de génération d'identifiant de session réussi sont:

  1. Deux sessions distinctes ne doivent pas avoir le même identifiant, avec une probabilité écrasante.
  2. Il ne devrait pas être possible sur le plan informatique de "frapper" un identifiant de session lors de l’essai d’identifiants aléatoires, avec une probabilité non négligeable.

Ces deux propriétés sont obtenues avec un ID de session aléatoire d'au moins, disons, 16 octets (32 caractères avec une représentation hexadécimale), à ​​condition que le générateur soit un PRNG cryptographiquement fort (/dev/urandom Sur Systèmes de type Unix, CryptGenRandom() sur Windows/Win32, RNGCryptoServiceProvider sur .NET ...). Puisque vous stockez également l'ID de session dans un serveur de base de données, vous pourriez vérifier les doublons, et votre base de données le fera probablement pour vous (vous voudrez que cet ID soit une clé d'index) , mais c'est encore du temps perdu car la probabilité est très faible. Considérez que chaque fois que vous sortez de votre maison, vous pariez sur l'idée que vous ne serez pas frappé par la foudre. Être tué par la foudre a une probabilité d'environ 3 * 10-dix par jour ( vraiment ). C'est un risque mortel, votre propre vie, pour être précis. Et pourtant, vous rejetez ce risque, sans jamais y penser. Quel sens a-t-il alors à s'inquiéter des collisions d'ID de session qui sont des millions de fois moins probables et ne tueraient personne si elles se produisaient?

Il ne sert à rien de lancer une fonction de hachage supplémentaire dans la chose. Un caractère aléatoire correctement appliqué vous donnera déjà tout le caractère unique dont vous avez besoin. Une complexité accrue ne peut entraîner que des faiblesses supplémentaires.

Les fonctions cryptographiques sont pertinentes dans un scénario où non seulement vous voulez avoir une session, mais vous voulez également éviter tout coût de stockage sur serveur; disons, vous n'avez pas de base de données sur le serveur. Ce type de déchargement d'état nécessite un MAC et éventuellement un cryptage (voir cette réponse pour plus de détails).

28
Thomas Pornin

Les ID de session doivent être aléatoires et uniques. Si un attaquant peut deviner un ID de session légitime, il peut se faire passer pour cet utilisateur.

L'option 1 est votre meilleur pari, tant que vous utilisez un CSPRNG approprié, et non quelque chose comme Rand() d'une bibliothèque standard. Utiliser quelque chose comme l'option 2 n'est pas aussi sûr, car les noms d'utilisateur et les heures sont facilement devinés ou forcés par la force.

Jetez un œil au fonctionnement de code générateur de l'ID de session PHP , et vous verrez qu'une fonction de hachage est utilisée pour combiner l'adresse IP du client, l'heure actuelle (secondes et microsecondes) et certaines valeurs du générateur de congruence linéaire PHP (LGC) RNG comme base de référence. Si une source aléatoire spécifique au système d'exploitation est disponible, une entropie supplémentaire est mélangée à l'ID de cette fonction. Cela donne une marge de sécurité raisonnable si aucune source d'entropie forte n'est disponible, mais fournit une sécurité forte si elle l'est.

6
Polynomial

Les identifiants de session doivent être signés, vous n'avez donc pas à vous soucier des gens qui essaient de deviner l'ID de session.

Vérifiez également les collisions pour vous assurer que vous n'avez pas déjà donné cet identifiant.