IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Sessions "cookie-based" et vol de session "hijacking"


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2011
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2011
    Messages : 36
    Par défaut Sessions "cookie-based" et vol de session "hijacking"
    Bonjour,


    je m'intéresse épisodiquement à la programmation depuis quelques années, ce qui m'a servi à écrire divers petits utilitaires à but personnel.

    Je me suis intéressé il y a assez longtemps aux sessions (lorsqu'elles ont été incorporées à PHP), et j'ai donc créé une petite classe perso (probablement pas géniale mais bon) de sessions (sans utiliser les fonctions session de PhP).

    J'utilisais donc un identifiant de session, qu'il fallait propager via les cookies, et je conservais les données dans une table SQL dédiée aux sessions, avec un certain nombre de précautions visant à avoir une bonne sécurité.



    Il se fait que je reprend maintenant mes vieux bouts de code, et je lis la littérature sur le sujet, et je découvre avec intérêt un système de session qui dépendrait désormais essentiellement des cookies, et qui ne nécessiterait plus du tout de table SQL dédiée aux sessions.

    Si quelqu'un est curieux je peux développer un peu le sujet, mais mes problèmes sont les suivants :



    Le gros soucis théorique qui me bloque dans l'implémentation de cette méthode, c'est que je perd une protection que j'aimais bien contre l'hijacking de session.


    En résumé, si un pirate arrive à sniffer le cookie et copier son contenu, il possède une session valide.

    Auparavant, je gérais ce cas en stockant le nombre de visites effectuées pendant la session, et en l'incrémentant automatiquement dans le cookie. Ce qui fait que si un internaute surfe et se fait sniffer sa session, le pirate ne peut l'utiliser que lorsque l'internaute arrête de surfer, car sinon je détecte facilement que le nombre de visites ne correspond pas (je reçois deux fois un cookie qui déclare que l'internaute X a déjà fait 10 visites, info que je stocke aussi dans la BDD).

    Et je ne vois absolument pas comment détecter deux sessions qui se chevauchent sans utiliser une technique qui implique SQL (ce qui tue l'un des avantages des sessions qui se basent uniquement sur les cookies).

    Enfin bref, la meilleure technique que je trouve actuellement, c'est d'enregistrer les log (ce que je fais de toute façon) dans une table SQL, qui est analysée et nettoyée tous les mois (ou plus fréquemment si ya du passage), et d'inclure dans les logs le couple (user_id . timestamp de la session), et d'imposer qu'il soit unique.
    Donc si un internaute essaye d'utiliser un cookie qui a déjà été utilisé, je ne vais pas pouvoir l'inclure dans les logs (erreur SQL j'imagine), et je saurai qu'il y a éventuellement tentative d'hijacking.


    => Une erreur SQL sur une insertion dans une table pour cause de non-unicité d'un des champs est une solution élégante ou non puisqu'elle dépend d'une erreur ?

    => Un internaute qui "clique trop vite" ne va-t-il pas générer cette erreur ?
    Si je permet deux clicks dans un intervalle très court (pour gérer ce comportement), c'est laisser une fenêtre ouverte à un hijackeur qui sait "cliquer" en même temps plus ou moins que sa victime (et je sais pas si c'est possible, ou si je suis parano ^^).






    Une autre méthode que j'utilisais aussi, c'est enregistrer l'user-agent de l'internaute, car il n'est pas censé changer. Mais quelqu'un capable de sniffer un cookie est à mon avis complètement capable de copier l'user-agent ...
    Donc utiliser l'user-agent comme élément de sécurité n'a d'intérêt que contre les voleurs de cookies qui ne savent pas se procurer l'user-agent de leur victime (ça existe?).


    Merci de m'éclairer, et désolé si je suis un peu brouillon dans mes explications.

  2. #2
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Par défaut
    Salut,

    le hijacking est un vrai problème, mais j'ai pas l'impression que tes méthodes permettent de t'en protéger.

    Incrémenter ton champs PHPSSID (id de l'utilisateur) est inutile si on peut le prédire. La seule méthode que je vois est d'utiliser des nombres et des caractères suffisament grand que tu vas passer dans une fonction de hachage. Ces nombres doivent évidement être générés aleatoirement.

    Si tu d'utilises une valeurs en clair, je pense qu'il faut quelques minutes pour trouver ton incrément (si le hacker peut créer une sessions sur ton site c'est beaucoup moins long avec des outils appropriés).

    Enfin bref, la meilleure technique que je trouve actuellement, c'est d'enregistrer les log (ce que je fais de toute façon) dans une table SQL, qui est analysée et nettoyée tous les mois (ou plus fréquemment si ya du passage), et d'inclure dans les logs le couple (user_id . timestamp de la session), et d'imposer qu'il soit unique.
    le user + timestamp sera de toute façon unique à moins que tu mettes un delta de plusieurs secondes, ce qui doit être très peinible pour l'utilisateur (impossible de refresh).

    De plus, il n'est pas difficile d'écrire un script qui calcul le temps minimum que tu imposes. Après tu peux toujours bloquer le compte en cas de tentatives de fraudes... mais la encore tu risques d'avoir des faux positifs et d'embêter tes utilisateurs.

    => Une erreur SQL sur une insertion dans une table pour cause de non-unicité d'un des champs est une solution élégante ou non puisqu'elle dépend d'une erreur ?
    Je pense qu'elle ne te protège pas du tout. Niveau code par contre rien à redire.

    => Un internaute qui "clique trop vite" ne va-t-il pas générer cette erreur ?
    En plus c'est peinible pour l'utilisateur. Car oui, il va générer cette erreur.

    Une autre méthode que j'utilisais aussi, c'est enregistrer l'user-agent de l'internaute, car il n'est pas censé changer. Mais quelqu'un capable de sniffer un cookie est à mon avis complètement capable de copier l'user-agent ...
    Donc utiliser l'user-agent comme élément de sécurité n'a d'intérêt que contre les voleurs de cookies qui ne savent pas se procurer l'user-agent de leur victime (ça existe?).
    Règle numéro 1 : Ne jamais se fier aux informations envoyé par l'utilisateur. Récupérer l'user-agent est simple comme le monde, si tu es en position d'hijacking.

    N'oublie cependant pas que ton site ne détient surement pas des secrets bancaires, ou rien qui ne justifie du hijacking. Qui demande quand même de se retrouver en situation ou l'on peut sniffer le réseau de sa cible (ce qui n'est pas du tout évident à distance).

    Et si j'ai tord sur le dernier points et que tu détiens des informations vraiment sensible -> implémente de l'https qui te fournira une sécurité nettement plus importante.

    A part de l'https, je ne vois pas de solution solide contre du hijacking...

    Coordialement Manticore

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2011
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2011
    Messages : 36
    Par défaut
    Merci.

    Je sais qu'il est difficile de se protéger contre l'hijacking, et que dire des keyloggers ...

    Je n'incrémente pas le PHPSID, mais un compteur de visites propre à la session.
    Mais bon, soit j'impose que ce compteur soit unique (ce qui risque fort de gêner les utilisateurs), soit je tolère une fenêtre de validité (ce qui diminue fortement l'intérêt et alourdit le code).
    De toute façon ce verrou de sécurité ne marche de toute façon pas si le hijackeur attend que l'internaute sorte de mon site.


    Je réagis à
    le user + timestamp sera de toute façon unique à moins que tu mettes un delta de plusieurs secondes, ce qui doit être très peinible pour l'utilisateur (impossible de refresh).
    Car même si ta réponse me satisfait, j'ai l'impression de ne pas m'être fait comprendre ^^

    Un système de session sur cookie est de la forme, si j'en crois de solides sources datant de 2008,

    user_id (ou user_name)
    +
    peremption_cookie (un timestamp)
    +
    encryption[data , cle_encryption] (l'encryption de data est optionnelle selon les désirs de confidentialité)
    +
    hash_mac[user_id + peremption_cookie + data + identifiant de session, cle_encryption]

    Avec la clé de l'encryption valant
    cle_encryption = hash_mac[user_id + peremption_cookie, cle_encryption_serveur]

    Ce qui permet, comme d'autres systèmes de sessions :
    - de continuer à authentifier un utilisateur qui s'est authentifié à un moment dans la session (donc récemment, en fonction de la durée de péremption qu'on fixe)
    - de contrôler le niveau de confidentialité de la session (on peut choisir de crypter ou non data dans le cookie)
    - de s'assurer que le cookie ne peut être inventé ou modifié (via un système de hashage qui varie pour chaque cookie, et qui dépend d'une clé de hashage coté serveur qui n'est donc pas sensible aux attaques de volume puisque ce n'est pas cette clé qu'on utilise au final (mais un hash de cette clé avec un sel variable qui dépend du timestamp et de id_user)).


    Mais il empêche difficilement hors SSL que le cookie soit copié (volé).
    L'identification de session n'est PAS phpsid, mais la clé SSL dans le cas d'une connexion sécurisée (donc protégé contre l'hijacking), et il n'y a aucune spécification dans le cas d'une connexion non sécurisée (donc vulnérable à l'hijacking).

    Une parade éventuelle, c'est d'imposer l'unicité de la clé user_id , timestamp.
    Le problème, c'est que si un utilisateur clique deux fois "trop vite", le serveur n'aura pas le temps de donner le "nouveau" cookie avant qu'il ne soit envoyé à la 2ème requete, et donc l'utilisateur enverra lui-même deux fois le même cookie, alors qu'il n'y a pas du tout de tentative d'hijacking.

    (et c'est ce que tu as confirmé je crois)




    J'utilise l'user-agent comme indice d'identification dans le hash, car si je sais que ce n'est pas une donnée fiable, au moins je sais que c'est la seule information de $_SERVER venant de l'utilisateur qui n'est pas censé changer en cours de session (contrairement à l'ip par exemple). Il est important que ce soit un élément quasi invariable, et c'est mieux lorsque c'est un élément unique et difficilement volable (comme une clé SSL), mais je n'ai rien d'autre que l'user-agent.

    Il est possible, facile et efficace d'utiliser un verrou qui observe la "tendance" de l'IP de l'utilisateur à ne pas changer (si elle ne change pas après 20 pages visitées, elle n'est pas censé changer ensuite), pour utiliser l'IP comme identifiant de session, mais ça ne marche que pour ceux qui ont une IP fixe, donc même je vais probablement intégrer ce système de "tendance" (une petit sécurité supplémentaire), il ne protègera pas tout le monde.

  4. #4
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Par défaut
    Ok je commence à mieux comprendre ce que tu fais

    Donc juste pour être sur que l'on parle de la même chose :
    1. ton compteur de visite te sert à générer un nouvel identifiant à chaque requête http.

    2. tu utilises un timestamp + user_id, tu imposes l'unicité, mais avec quel moyen ?

    user_id (ou user_name)
    +
    peremption_cookie (un timestamp)
    +
    encryption[data , cle_encryption] (l'encryption de data est optionnelle selon les désirs de confidentialité)
    +
    hash_mac[user_id + peremption_cookie + data + identifiant de session, cle_encryption]

    Avec la clé de l'encryption valant
    cle_encryption = hash_mac[user_id + peremption_cookie, cle_encryption_serveur]
    Toujours bon à savoir, merci.

    Cependant, à moins que je loupe quelques chose, ta protection, ne fais que changer plus souvent le phpssid (on va l'appeler comme ça, qui correspond à l'identifiant de session de l'utilisateur stocker dans un cookie).

    Donc à quoi te sert-elle ? Penses-tu te protéger contre quel scénario d'attaque ?


    Une parade éventuelle, c'est d'imposer l'unicité de la clé user_id , timestamp.
    Le problème, c'est que si un utilisateur clique deux fois "trop vite", le serveur n'aura pas le temps de donner le "nouveau" cookie avant qu'il ne soit envoyé à la 2ème requete, et donc l'utilisateur enverra lui-même deux fois le même cookie, alors qu'il n'y a pas du tout de tentative d'hijacking.

    (et c'est ce que tu as confirmé je crois)
    Comme je te le dis au début du texte, comment imposes-tu cette unicité ?

    Il est possible, facile et efficace d'utiliser un verrou qui observe la "tendance" de l'IP de l'utilisateur à ne pas changer (si elle ne change pas après 20 pages visitées, elle n'est pas censé changer ensuite), pour utiliser l'IP comme identifiant de session, mais ça ne marche que pour ceux qui ont une IP fixe, donc même je vais probablement intégrer ce système de "tendance" (une petit sécurité supplémentaire), il ne protègera pas tout le monde.
    Effectivement cela fonctionne, mais le problème c'est que pour faire de l'hijacking il faut en principe sniffer le réseau, donc on est souvent dans le même réseau que la cible. Comme la plupart des réseaux utilisent des translations NAT on se retrouve avec la même adresse IP que la cible donc ta protection saute.


    Encore un dernier point que se passe-t-il pour ton user si, son browser plante alors qu'il devait recevoir le dernier cookie ? Combien de temps sera t-il banni si il n'a pas reçu le bon cookie ? Suffit-il pour lui de se reconnecter ?

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2011
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2011
    Messages : 36
    Par défaut
    1. Le compteur de visite servait à assurer la continuité et l'unicité d'une session. Mais il est entaché du problème des doubles click. Il ne sert pas spécifiquement à générer un nouvel identifiant à chaque requête HTTP (je n'en vois pas l'intérêt), mais agit comme une protection contre deux utilisateurs utilisant en même temps la même session (c'est la réponse à ta question sur pourquoi imposer l'unicité : un cookie ne PEUT PAS avoir été utilisé deux fois, donc un cookie volé et utilisé par le voleur et la victime avertit d'un problème). C'est peut-être assez similaire au fait de générer un nouvel identifiant de session (session_regenerate_id ?) en pratique (les objectifs). Mais ça me semble moins lourd pour le même effet (générer des nouvelles sessions à chaque page c'est lourd).

    2. L'unicité ne s'impose que s'il y a moyen de comparer, donc d'avoir stocké qq part ces valeurs. Si je stocke cela dans ma base SQL, je réduis une partie de l'intérêt des session basées sur les cookies. Bref, si une requête INSERT (user_id+timestamp , infos...) dans une table sql_logs échoue parce que j'impose l'unicité du champs user_id+timestamp, je peux récupérer l'erreur et reset la session (je ne ban pas).


    Cependant, à moins que je loupe quelques chose, ta protection, ne fais que changer plus souvent le phpssid (on va l'appeler comme ça, qui correspond à l'identifiant de session de l'utilisateur stocker dans un cookie).
    Basiquement, et je vais peut-être répondre à d'autres questions que tu as posées à la suite, c'est un système qui anéantit un peu le système de sessions. Au lieu d'être un système de session avec un "identifiant", c'est un système qui "donne" à l'utilisateur un certain nombre d'infos sur sa session de façon "cryptée (il y a un hash de vérification de l'intégrité des données du cookie), et c'est ce hash qui garantit si les données du cookie sont valables ou non. Ce n'est pas l'existence ou non d'un phpsessid dans une table SQL qui répertorie les sessions actives.
    Le garant de la session, ce n'est pas l'identifiant, mais le hash de vérification qui garantit que le cookie a bel et bien encrypté par nous même.





    Effectivement cela fonctionne, mais le problème c'est que pour faire de l'hijacking il faut en principe sniffer le réseau, donc on est souvent dans le même réseau que la cible. Comme la plupart des réseaux utilisent des translations NAT on se retrouve avec la même adresse IP que la cible donc ta protection saute.
    Si ce que tu dis est vrai, je peux supposer que le système n'est tout simplement pas sécurisable contre le vol de cookie tant que je n'utilise pas de système comme le SSL. Cela me va.

    J'ai une question peut-être pointue :
    J'ai prévu ce cas (il me semblait probable), et je me suis dit que le cookie suffirait pour la plupart des actions pas spécialement "graves" de mon site, et que j'imposerais la réidentification (avec un formulaire) pour les actions à sécuriser.
    Mais j'ai l'impression que voler un cookie et intercepter des données $_POST, c'est un peu la même chose ... (tout est dans l'en-tête de la requête ?).



    Encore un dernier point que se passe-t-il pour ton user si, son browser plante alors qu'il devait recevoir le dernier cookie ? Combien de temps sera t-il banni si il n'a pas reçu le bon cookie ? Suffit-il pour lui de se reconnecter ?
    Je ne ban pas, je nettoie la session, donc il faut se reconnecter, oui (si j'impose le système d'unicité, ce dont je suis de moins en moins sûr).
    Si je n'utilise pas le système d'unicité, et que j'assume que la session n'est pas protégée contre l'hijacking (si je veux une session plus sûre je dois utiliser SSL ou autre), le plantage du browser ne sera pas grave pour la session : le cookie sera toujours valide (sauf s'il devient périmé).

    Je te fais remarquer que les échanges de cookie se font au tout début (avant la réception du code HTML), donc c'est quand même rare ce cas.

  6. #6
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Par défaut
    1. Le compteur de visite servait à assurer la continuité et l'unicité d'une session. Mais il est entaché du problème des doubles click. Il ne sert pas spécifiquement à générer un nouvel identifiant à chaque requête HTTP (je n'en vois pas l'intérêt), mais agit comme une protection contre deux utilisateurs utilisant en même temps la même session (c'est la réponse à ta question sur pourquoi imposer l'unicité : un cookie ne PEUT PAS avoir été utilisé deux fois, donc un cookie volé et utilisé par le voleur et la victime avertit d'un problème). C'est peut-être assez similaire au fait de générer un nouvel identifiant de session (session_regenerate_id ?) en pratique (les objectifs). Mais ça me semble moins lourd pour le même effet (générer des nouvelles sessions à chaque page c'est lourd).
    Donc ton cookie ne peut-être utilisé qu'une seule fois ok. Une fois utilisé je suppose que l'utilisateur en reçoit un nouveau ? C'est juste ?

    sa session de façon "cryptée (il y a un hash de vérification de l'intégrité des données du cookie)
    Attention à ne pas confondre crypter et hacher c'est pas du tout la même chose.

    J'ai une question peut-être pointue :
    J'ai prévu ce cas (il me semblait probable), et je me suis dit que le cookie suffirait pour la plupart des actions pas spécialement "graves" de mon site, et que j'imposerais la réidentification (avec un formulaire) pour les actions à sécuriser.
    Mais j'ai l'impression que voler un cookie et intercepter des données $_POST, c'est un peu la même chose ... (tout est dans l'en-tête de la requête ?).
    Absoluement les cookies sont insérées dans l'en-tête alors que les post sont dans le "corps", tout est en principe accessible avec les mêmes outils, je te conseils d'essayer quelques add-ons de firefox pour voir comme cela se présente par exemple : tamperdata, qui te permet d'intercepter les requêtes http

    Je te fais remarquer que les échanges de cookie se font au tout début (avant la réception du code HTML), donc c'est quand même rare ce cas.
    Ton cookie est envoyé avec chaque requête http, et oui c'est rare mais je pensais que tu faisais un ban.

    Si ce que tu dis est vrai, je peux supposer que le système n'est tout simplement pas sécurisable contre le vol de cookie tant que je n'utilise pas de système comme le SSL. Cela me va.
    En tout cas à ma connaissance, il n'existe pas de système de sessions fiable n'utilisant pas de cryptographie.

Discussions similaires

  1. [PHP 5.0] Quotes, cookies, et sessions
    Par bob633 dans le forum Langage
    Réponses: 22
    Dernier message: 30/03/2012, 00h19
  2. [MySQL] Sessions dans base MYSQL (suite au tuto "Sessions et Cookies en PHP")
    Par telliouze dans le forum PHP & Base de données
    Réponses: 11
    Dernier message: 14/08/2008, 17h08
  3. [Cookies] Test de vol de session
    Par freesurfer dans le forum Langage
    Réponses: 12
    Dernier message: 20/10/2006, 14h55
  4. [Cookies] Login membre, protection vol de session
    Par july dans le forum Langage
    Réponses: 18
    Dernier message: 06/06/2006, 12h02
  5. [Cookies] C'est quoi un vol de session ?
    Par psychoBob dans le forum Langage
    Réponses: 45
    Dernier message: 28/05/2006, 23h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo