web-dev-qa-db-fra.com

Pourquoi n'est-il pas sûr de stocker l'ID de session dans un cookie directement?

J'apprends middleware de session .

Vous avez pour fournir un secret ou le middleware se plaint:

app.use(session({
  secret: "abc",
  resave: false,
  saveUninitialized: false,
  store: new MongoStore({
    mongooseConnection: mongoose.connection
  })
}));

J'ai fait quelques recherches et l'ID de session réel est

eKeYlF1DR6AtVkeFZK9vEIHSZT8e0jqZ

Mais selon le cookie, l'ID de session est

s%3AeKeYlF1DR6AtVkeFZK9vEIHSZT8e0jqZ.on5ifVE079C4ctKNdkNiJSh8NkQMckjd5fn%2FsxIQWCk

Je suis confus. Pourquoi n'est-il pas sûr de stocker l'ID de session directement dans le cookie? Puis-je ne pas stocker l'ID de session directement?

Il semble que le secret soit une clé privée et que l'ID de session soit crypté?

Si je comprends bien, si un attaquant peut atteindre ce cookie, peut-être via XSS ou l'ingénierie sociale, l'attaquant peut toujours détourner la session. Je ne sais pas à quoi sert le secret.

40
Angular noob

L'auteur de cette bibliothèque JS semble avoir fait une hypothèse commune, mais erronée, bien que basée sur juste assez de connaissances pour se tromper.

Vous ne pouvez pas simplement saupoudrer de la poussière de fée magik crypto et espérer obtenir plus de sécurité, comme des pépites de chocolat.

Ce qui manque à l'auteur, c'est qu'une fois que vous avez signé l'ID de session et que vous l'avez placé dans le cookie - l'ID de session signé IS l'ID de session. C'est littéralement le identifiant avec lequel les utilisateurs finaux indiqueront au serveur quelle session est la leur. Peu importe que le serveur souhaite effectuer un traitement interne pour associer l'identifiant de session réel à la représentation interne de la mémoire de la session.

Pour être clair, si l'ID de session signé est volé - de quelque manière que ce soit via XSS, l'ingénierie sociale ou autre chose - l'attaquant pourra simplement utiliser cet ID de session signé pour détourner la session de l'utilisateur, malgré la représentation interne.


Cela dit, il y a un avantage nominal à signer la valeur du cookie avant de l'envoyer au navigateur: la détection de falsification. Autrement dit, lors de la réception du cookie de l'utilisateur, l'application Web peut vérifier que le cookie n'a pas été falsifié avant en l'utilisant pour rechercher la mémoire de session, notamment en validant la signature. Cela peut éventuellement empêcher certaines attaques avancées/actives sur la gestion de session, en évitant une recherche de session sur un identifiant de session qui n'a jamais été valide.

Cependant, cet avantage supposé est douteux, car l'id de session est généralement juste un id, utilisé pour rechercher les variables de session. De plus, la plupart attaques ciblant l'ID de session ne seraient pas arrêtées par cela - détournement de session, fixation de session, don de session, session de circonscription, etc.

Quoi qu'il en soit, si vous voulez vraiment vérifier que le cookie de session n'a pas été falsifié avant de l'utiliser, il existe des moyens plus simples qu'une signature numérique ...

54
AviD

Une réponse plus complète de http://hueniverse.com/2015/07/08/on-securing-web-session-ids/

Avertissement: comme tout conseil de sécurité de quelqu'un qui ne connaît pas les spécificités de votre propre système, ceci est uniquement à des fins éducatives. La sécurité est un domaine complexe et très spécifique et si vous êtes préoccupé par la sécurité de votre système, vous devez engager un expert qui peut examiner votre système avec une analyse des menaces et fournir les conseils appropriés.

Force brute

Les attaques par force brute sont celles dans lesquelles l'attaquant tente d'accéder au système en faisant des demandes répétées en utilisant des informations d'identification différentes (jusqu'à ce que l'une fonctionne). L'exemple le plus courant est celui d'un attaquant qui tente de deviner un mot de passe utilisateur. C'est pourquoi les mots de passe doivent être longs et éviter d'utiliser des mots du dictionnaire pour les rendre plus difficiles à deviner. Des systèmes correctement conçus gardent une trace des demandes d'authentification échouées et aggravent le problème lorsqu'il apparaît qu'une attaque est en cours.

Les mots de passe ne sont pas les seules informations d'identification utilisées dans l'authentification Web. L'implémentation la plus courante comprend une page de connexion qui, une fois l'authentification réussie, définit un cookie de session sur le client. Le cookie de session agit comme un jeton porteur - celui qui apparaît avec le jeton est considéré comme l'utilisateur authentifié. La configuration d'un cookie de session supprime la nécessité de saisir votre nom d'utilisateur et votre mot de passe sur chaque page. Cependant, ce cookie de session agit désormais comme la seule clé d'authentification et toute personne qui accède à cette clé aura accès au système. Les cookies ne sont, après tout, qu'une simple chaîne de caractères.

Une attaque de devination d'ID de session est un type d'attaque par force brute. Au lieu d'essayer de deviner le mot de passe, l'attaquant essaie de deviner l'ID de session et de forger le cookie d'authentification. L'attaquant génère des identifiants de session et essaie de faire des requêtes à l'aide de ces identifiants, dans l'espoir qu'ils correspondent aux sessions actives réelles. Par exemple, si les identifiants de session d'une application Web sont générés en séquence, un attaquant peut rechercher leur propre identifiant de session et en fonction de ces demandes de contrefaçon en utilisant des valeurs d'ID de session proches. Pour se protéger contre cette attaque, nous devons rendre les identifiants de session difficiles à deviner. Notez que je dis "impraticable", pas "impossible".

Manque de réalisme

La première étape consiste à s'assurer que les identifiants de session sont suffisamment longs et non séquentiels. Tout comme les mots de passe, plus l'ID de session est long, plus il est difficile d'en trouver un valide en devinant. Il est également essentiel que les identifiants de session ne soient pas générés à l'aide d'un algorithme prévisible tel qu'un compteur, car si une telle logique existe, l'attaquant ne devine plus mais génère des identifiants de session. L'utilisation d'un générateur de nombres aléatoires cryptographiquement sécurisé pour produire des identifiants de session suffisamment longs est la meilleure pratique courante. Qu'est-ce qui est "suffisamment long"? Eh bien, cela dépend de la nature de votre système. La taille doit se traduire par un effort peu pratique pour deviner un identifiant de session valide.

Une autre façon d'empêcher un attaquant de deviner les identifiants de session consiste à intégrer l'intégrité dans le jeton en ajoutant un hachage ou une signature au cookie de session. Pour ce faire, le middleware de session Express calcule un hachage sur la combinaison de l'ID de session et d'un secret. Étant donné que le calcul du hachage nécessite la possession du secret, un attaquant ne sera pas en mesure de générer des identifiants de session valides sans deviner le secret (ou simplement essayer de deviner le hachage). Tout comme les identifiants de session aléatoires forts, la taille de hachage doit correspondre aux exigences de sécurité de l'application spécifique qu'elle est censée protéger. En effet, à la fin, le cookie de session n'est encore qu'une chaîne de caractères et est ouvert aux attaques de devinettes.

Les identifiants de session doivent être suffisamment longs et difficiles à deviner. Il existe plusieurs façons d'y parvenir. Les techniques d'aléatoire et de hachage ci-dessus sont les deux méthodes les plus courantes mais pas les seules.

Couches

Si nous générons des identifiants de session aléatoires solides, avons-nous toujours besoin du hachage? Absolument!

Le principal principe de sécurité est la superposition. Ceci est également connu comme ne mettant pas tous vos œufs dans le même panier. Si vous comptez sur une seule source de sécurité, vous vous retrouvez sans aucune sécurité si cette seule source échoue. Par exemple, que faire si quelqu'un trouve un bug dans votre générateur de nombres aléatoires? Et s'ils trouvent un moyen de pirater cette partie de votre système et de la remplacer? Il existe d'innombrables attaques connues exploitant exactement cela - la génération de nombres aléatoires qui s'avère finalement moins aléatoire.

La combinaison d'un identifiant de session aléatoire fort avec un hachage pour l'intégrité protégera contre les failles dans le générateur de nombres aléatoires. Il protégera également contre les erreurs de développeur telles que l'utilisation de la mauvaise fonction de générateur de nombres aléatoires (par exemple, la méthode pas si aléatoire que chaque système propose en plus de la méthode forte). Nous écrivons tous du mauvais code, quelle que soit la qualité de notre processus ou notre expérience. Cela fait partie du génie logiciel. C'est pourquoi il est si important de superposer votre sécurité. Un fossé ne suffit pas, vous voulez aussi un mur derrière et probablement des gardes derrière le mur.

Si vous pensez que l'utilisation de la mauvaise fonction aléatoire ou d'un bogue profond dans OpenSSL sont les deux seuls problèmes ici, considérez la pratique courante du code de correction de singe en JavaScript et dans d'autres langages dynamiques. Si quelqu'un, n'importe où dans un déploiement d'application entier, s'oppose aux installations aléatoires globales (pour les tests, la journalisation, etc.) et les casse (ou si cela fait partie d'une injection de code malveillante), les identifiants de session reposant uniquement sur l'aléatoire ne sont plus sécurisés.

Alarmes

Une différence importante entre deviner les mots de passe et deviner les identifiants de session est le fait que les mots de passe sont associés à un compte (par exemple, nom d'utilisateur). La paire compte-mot de passe facilite le suivi des attaques par force brute, car elle fournit un moyen relativement simple de suivre les tentatives infructueuses. Cependant, en ce qui concerne les identifiants de session, ce n'est pas aussi simple car les sessions expirent et n'incluent pas de contexte de compte. Cela signifie qu'un identifiant de session non valide pourrait provenir d'une session expirée ou d'un attaquant, mais sans données supplémentaires (par exemple, une adresse IP), il serait difficile de faire la différence dans un système à grande échelle.

En incluant un composant d'intégrité dans l'ID de session (via un hachage ou une signature), le serveur peut immédiatement faire la différence entre une session expirée, un ID de session non alloué et une session non valide. Même si vous enregistrez simplement des tentatives d'authentification non valides (et vous devriez), vous souhaiterez enregistrer une session expirée différemment d'une session non valide. Outre la valeur de sécurité de connaître la différence, il fournira également des informations utiles sur le comportement de vos utilisateurs.

Hygiène

Les informations d'identification doivent expirer et, par conséquent, les identifiants de session doivent avoir une durée de vie limitée (où la durée est en grande partie une valeur spécifique au système). Bien que les cookies soient soumis à une politique d'expiration, il n'y a aucun moyen de s'assurer qu'ils sont effectivement respectés. Un attaquant peut définir l'expiration du cookie sur n'importe quelle valeur sans que le serveur puisse la détecter. Une meilleure pratique courante consiste à inclure un horodatage dans chaque information d'identification émise, ce qui peut être aussi simple que d'ajouter un suffixe d'horodatage à l'ID de session généré de manière aléatoire. Cependant, afin de pouvoir compter sur cet horodatage, nous devons être en mesure de vérifier qu'il n'a pas été tempéré et que la façon de le faire est avec un hachage ou une signature.

L'ajout d'un horodatage à l'ID de session permet au serveur de gérer rapidement les sessions expirées sans avoir à effectuer une recherche de base de données coûteuse. Bien que cela puisse sembler sans rapport avec la sécurité, il s'agit en fait d'un élément essentiel du maintien d'une application sécurisée.

Une attaque par déni de service (ou DoS) est une attaque dans laquelle l'attaquant fait des demandes répétées dans le seul but de consommer trop de ressources sur le serveur et de le fermer ou de le rendre inaccessible aux autres. Si chaque authentification de demande nécessite une recherche de base de données complète au niveau de l'application, un attaquant peut utiliser des identifiants de session falsifiés pour lancer facilement une attaque DoS. En incluant un composant d'intégrité dans le cookie, le serveur peut immédiatement identifier les informations d'identification falsifiées ou expirées sans aucun coût de recherche d'arrière-plan.

Antidémarreur

Parfois, les choses tournent mal. Et quand ils vont très mal, vous devez avoir un moyen d'invalider immédiatement des classes entières de sessions. Étant donné que la génération d'un hachage ou d'une signature nécessite un secret ou une clé côté serveur, le remplacement du secret entraînera l'échec de la validation de tous les ID de session. En utilisant différents secrets pour différents types d'ID de session, des classes entières de sessions peuvent être séparées et gérées. Sans un tel mécanisme, l'application elle-même doit prendre une décision calculée sur l'état de chaque session ou effectuer des mises à jour de masse de la base de données.

De plus, dans les grands systèmes distribués avec réplication de base de données sur différents emplacements géographiques, la invalidation d'un enregistrement de session dans un emplacement peut prendre des secondes, voire des minutes, pour se répliquer. Cela signifie que la session reste active jusqu'à ce que le système complet soit de nouveau synchronisé. Par rapport à un identifiant de session auto-descriptif et auto-validant, les avantages sont évidents.

Usage général

Une caractéristique importante du middleware de session Express est sa prise en charge des ID de session générés par l'utilisateur. Cela permet au développeur de déployer le middleware dans un environnement existant où les identifiants de session sont générés par une entité existante qui pourrait résider sur une plateforme complètement différente. Sans ajouter un hachage aux identifiants de session fournis par l'utilisateur, la charge de la construction d'un système sécurisé passe de l'expert (l'auteur du module) à l'utilisateur (qui est probablement un novice en matière de sécurité). L'application d'un hachage est une bien meilleure approche que de forcer un générateur d'ID de session interne.

Crocodiles

Ajouter un hachage à un identifiant de session aléatoire fort n'est pas tout ce que vous devez faire. La question de savoir si vos douves peuvent bénéficier des crocodiles est, encore une fois, une décision spécifique au château. Sans aller trop loin dans le sujet, il existe de nombreuses autres couches que vous pouvez ajouter à votre niveau de gestion de session. Par exemple, vous pouvez utiliser deux informations d'identification de session, une longue durée de vie (dure aussi longtemps que la session) et une autre courte durée (valable pour des minutes ou des heures). Pour actualiser la courte durée de vie, vous utilisez la longue durée de vie, mais ce faisant, vous réduisez l'exposition des informations d'identification de longue durée de vie sur le réseau (en particulier lorsque vous n'utilisez pas TLS).

Une autre pratique courante consiste à avoir un cookie contenant des informations générales sur l'utilisateur (par exemple, prénom, éléments récemment consultés, etc.) à côté de la session, puis à inclure quelque chose de ce cookie dans le hachage pour créer une liaison entre l'état actif de l'utilisateur et l'authentification. C'est une façon de ramener le "nom d'utilisateur" dans le flux de travail.

Pour aller encore plus loin, le hachage peut être remplacé par des signatures et le contenu des cookies peut être crypté (puis haché ou signé par-dessus). La verbosité de la sécurité doit correspondre à la menace.

19
Eran Hammer

Eran Hammer, l'un des responsables du module de gestion de session yar pour NodeJS, a dit ceci à ce sujet:

Avertissement: comme tout conseil de sécurité de quelqu'un qui ne connaît pas les spécificités de votre propre système, ceci est uniquement à des fins éducatives. La sécurité est un domaine complexe et très spécifique et si vous êtes préoccupé par la sécurité de votre système, vous devez engager un expert qui peut examiner votre système tout au long de son analyse des menaces et fournir les conseils appropriés.

[...] La signature d'un jeton porteur pour l'intégrité interne et la validation est une pratique de sécurité courante. Bien que je ne considère pas ce que la session express fait comme suffisant, c'est certainement le strict minimum requis.

Vous ne voulez pas que les gens puissent deviner une session afin d'avoir accès au compte de quelqu'un d'autre. [...] Empêcher de deviner un identifiant de session en incluant [sic] un composant cryptographique [sic] est la bonne façon pour y parvenir. C'est la norme de l'industrie.

Les cookies de session sont des jetons au porteur, ce qui signifie que quiconque les possède peut avoir un accès complet en tant que propriétaire légitime. Vous voulez pouvoir faire quelques choses pour réduire les risques. S'assurer que personne d'autre que le serveur ne peut émettre des informations d'identification valides est le strict minimum et c'est ce qui se fait dans express-session.

Je ne considère pas qu'une simple signature soit une protection suffisante pour la gestion de session, c'est pourquoi ce module [yar] utilise l'encodage iron qui à la fois crypte le contenu et le signe pour la validation d'intégrité. Cela rend pratiquement impossible pour quiconque de tempérer avec l'état (ainsi que la possibilité de maintenir un certain état dans le cookie lui-même), mais plus important encore, cela vous permet de définir une expiration pour les informations d'identification.

Bien que les cookies soient livrés avec des instructions d'expiration, un attaquant n'est pas tenu d'obéir. Cela signifie que si quelqu'un vole un cookie, s'il n'y a aucun moyen de forcer ce cookie à être de courte durée, cela laissera le système exposé pendant longtemps. La synchronisation de la politique d'expiration des cookies avec la politique côté serveur est une autre couche de complexité qui ne devrait pas faire partie du profil de sécurité du système.

Il y a beaucoup d'autres vecteurs d'attaque à considérer ici. Par exemple, si chaque demande déclenche une recherche de stockage de session, il est plus facile de DOS avec des identifiants de session non valides. Si vous avez un moyen rapide de détecter qu'une demande provient d'un attaquant, vous pouvez à la fois la bloquer mais aussi prendre des mesures pour la combattre. Une signature de cookie non valide ne peut provenir que d'une source malveillante (à moins que vous n'ayez modifié leur façon de générer des cookies, auquel cas vous le savez et pouvez le gérer).

Dans le même ordre d'idées, il est essentiel de pouvoir savoir quand un identifiant de session est falsifié ou expiré pour maintenir un système sécurisé. Si vous générez simplement des identifiants aléatoires, en supposant qu'ils soient suffisamment longs et suffisamment aléatoires, vous n'avez aucun moyen de le savoir à moins de garder une trace de chaque identifiant de session jamais généré, ce qui rendrait la mise à l'échelle de votre système coûteuse et douloureuse. Et il devrait être assez évident de dire pourquoi vous voulez savoir si une mauvaise demande de cookie provient ou non d'un attaquant.

(Voir le commentaire complet)

Donc, fondamentalement, bien que le stockage direct d'un ID de session aléatoire dans un cookie ne soit pas nécessairement non sécurisé (tant que l'ID est imprévisible et suffisamment long), le cryptage et la signature des informations de session offrent un certain nombre de fonctionnalités supplémentaires (comme la possibilité de stocker l'expiration informations contenues dans le cookie lui-même et la capacité d'identifier les tentatives de falsification d'un ID de session) qui peuvent être utilisées pour améliorer la sécurité.

Pour expressjs en particulier, le mainteneur actuel aussi fournit la justification suivante :

Les utilisateurs peuvent utiliser les ID de session qu'ils souhaitent. Peut-être que quelqu'un pense qu'il devrait utiliser un numéro d'incrémentation automatique de la base de données SQL, cela n'a pas d'importance, car nous protégeons sa décision non informée en signant la valeur, en allongeant la clé.

En d'autres termes, la signature de l'ID de session protège les utilisateurs de la bibliothèque qui pourraient (incorrectement) utiliser des ID de session prévisibles ou insuffisamment longs dans leurs applications (au lieu de laisser la bibliothèque gérer la génération d'ID de session). Évidemment, cette raison n'est pas applicable si l'utilisateur utilise des ID de session choisis en toute sécurité, mais cette bibliothèque a choisi de ne pas faire cette hypothèse.

Hammer réitère ce point :

En outre, il s'agit d'un module générique supposant que sa principale exigence est un large éventail d'utilisateurs. Il doit absolument supposer que certaines personnes l'utiliseront mal (par exemple les identifiants d'incrémentation) et s'adapter à cela. C'est également une pratique courante lors de la création de modules pour un large public.

14
Ajedi32