J'essaie de mieux comprendre la fixation et le détournement de session PHP et comment éviter ces problèmes. J'ai lu les deux articles suivants sur le site Web de Chris Shiflett:
Cependant, je ne suis pas sûr de bien comprendre les choses.
Pour éviter la fixation de session, il suffit d'appeler session_regenerate_id (true); après avoir réussi à connecter quelqu'un? Je pense avoir bien compris.
Il parle également d'utiliser des jetons transmis dans les URL via $ _GET pour empêcher le piratage de session. Comment cela se ferait-il exactement? Je suppose que lorsque quelqu'un se connecte, vous générez son jeton et le stockez dans une variable de session, puis sur chaque page, vous compareriez cette variable de session avec la valeur de la variable $ _GET?
Ce jeton ne devrait-il être changé qu'une seule fois par session ou à chaque chargement de page?
Est-ce également un bon moyen d'empêcher le piratage sans avoir à transmettre une valeur dans les URL? ce serait beaucoup plus facile.
Réponses:
Ok, il y a deux problèmes distincts mais liés, et chacun est traité différemment.
Fixation de session
C'est là qu'un attaquant définit explicitement l'identifiant de session d'une session pour un utilisateur. En général, en PHP, cela se fait en leur donnant une URL comme
http://www.example.com/index...?session_name=sessionid
. Une fois que l'attaquant donne l'URL au client, l'attaque est identique à une attaque de détournement de session.Il existe plusieurs façons d'éviter la fixation de session (faites-les toutes):
Définissez
session.use_trans_sid = 0
dans votrephp.ini
fichier. Cela indiquera à PHP de ne pas inclure l'identifiant dans l'URL et de ne pas lire l'URL pour les identifiants.Définissez
session.use_only_cookies = 1
dans votrephp.ini
fichier. Cela indiquera à PHP de ne jamais utiliser d'URL avec des identifiants de session.Régénérez l'ID de session chaque fois que l'état de la session change. Cela signifie l'un des éléments suivants:
Détournement de session
C'est là qu'un attaquant récupère un identifiant de session et est capable d'envoyer des requêtes comme s'il s'agissait de cet utilisateur. Cela signifie que puisque l'attaquant possède l'identifiant, il est pratiquement impossible de les distinguer de l'utilisateur valide en ce qui concerne le serveur.
Vous ne pouvez pas empêcher directement le détournement de session. Vous pouvez cependant prendre des mesures pour le rendre très difficile et plus difficile à utiliser.
Utilisez un identifiant de hachage de session fort:
session.hash_function
dansphp.ini
. Si PHP <5.3, définissez-le sursession.hash_function = 1
pour SHA1. Si PHP> = 5.3, définissez-le sursession.hash_function = sha256
ousession.hash_function = sha512
.Envoyez un hash fort:
session.hash_bits_per_character
dansphp.ini
. Réglez ceci sursession.hash_bits_per_character = 5
. Bien que cela ne rende pas plus difficile la fissuration, cela fait une différence lorsque l'attaquant tente de deviner l'identifiant de session. L'ID sera plus court, mais utilisera plus de caractères.Définissez une entropie supplémentaire avec
session.entropy_file
etsession.entropy_length
dans votrephp.ini
fichier. Définissez le premier sursession.entropy_file = /dev/urandom
et le second sur le nombre d'octets qui seront lus à partir du fichier d'entropie, par exemplesession.entropy_length = 256
.Modifiez le nom de la session du PHPSESSID par défaut. Ceci est accompli en appelant
session_name()
avec votre propre nom d'identifiant comme premier paramètre avant l'appelsession_start
.Si vous êtes vraiment paranoïaque, vous pouvez également faire pivoter le nom de la session, mais sachez que toutes les sessions seront automatiquement invalidées si vous le modifiez (par exemple, si vous le rendez dépendant de l'heure). Mais en fonction de votre cas d'utilisation, cela peut être une option ...
Faites souvent pivoter votre identifiant de session. Je ne ferais pas cela à chaque demande (sauf si vous avez vraiment besoin de ce niveau de sécurité), mais à un intervalle aléatoire. Vous voulez changer cela souvent car si un attaquant détourne une session, vous ne voulez pas qu'il puisse l'utiliser trop longtemps.
Incluez l' agent utilisateur de
$_SERVER['HTTP_USER_AGENT']
dans la session. En gros, lorsque la session démarre, stockez-la dans quelque chose comme$_SESSION['user_agent']
. Ensuite, à chaque demande suivante, vérifiez qu'elle correspond. Notez que cela peut être truqué, donc ce n'est pas fiable à 100%, mais c'est mieux que pas.Incluez l' adresse IP de
$_SERVER['REMOTE_ADDR']
l' utilisateur dans la session. En gros, lorsque la session démarre, stockez-la dans quelque chose comme$_SESSION['remote_ip']
. Cela peut être problématique de la part de certains FAI qui utilisent plusieurs adresses IP pour leurs utilisateurs (comme AOL le faisait auparavant). Mais si vous l'utilisez, ce sera beaucoup plus sûr. Le seul moyen pour un attaquant de simuler l'adresse IP est de compromettre le réseau à un moment donné entre l'utilisateur réel et vous. Et s'ils compromettent le réseau, ils peuvent faire bien pire qu'un détournement (comme les attaques MITM, etc.).Incluez un jeton dans la session et du côté des navigateurs que vous incrémentez et comparez souvent. Fondamentalement, pour chaque demande, faites
$_SESSION['counter']++
du côté serveur. Faites également quelque chose dans JS du côté des navigateurs pour faire de même (en utilisant un stockage local). Ensuite, lorsque vous envoyez une requête, prenez simplement un nonce d'un jeton et vérifiez que le nonce est le même sur le serveur. En faisant cela, vous devriez être en mesure de détecter une session détournée car l'attaquant n'aura pas le compteur exact, ou s'il le fait, vous aurez 2 systèmes transmettant le même nombre et pourrez dire qu'un est falsifié. Cela ne fonctionnera pas pour toutes les applications, mais c'est un moyen de lutter contre le problème.Une note sur les deux
La différence entre la fixation de session et le détournement concerne uniquement la manière dont l'identifiant de session est compromis. Lors de la fixation, l'identifiant est mis à une valeur que l'attaquant connaît à l'avance. Dans Hijacking, il est soit deviné, soit volé à l'utilisateur. Sinon, les effets des deux sont les mêmes une fois que l'identifiant est compromis.
Régénération d'identifiant de session
Chaque fois que vous régénérez l'identifiant de session en utilisant
session_regenerate_id
l'ancienne session doit être supprimé. Cela se produit de manière transparente avec le gestionnaire de session principal. Cependant, certains gestionnaires de session personnalisés qui utilisentsession_set_save_handler()
ne le font pas et sont susceptibles d'attaquer d'anciens identificateurs de session. Assurez-vous que si vous utilisez un gestionnaire de session personnalisé, que vous gardez une trace de l'identifiant que vous ouvrez, et si ce n'est pas le même que vous enregistrez que vous supprimez (ou modifiez) explicitement l'identifiant de l'ancien.En utilisant le gestionnaire de session par défaut, vous pouvez simplement appeler
session_regenerate_id(true)
. Cela supprimera les anciennes informations de session pour vous. L'ancien ID n'est plus valide et entraînera la création d'une nouvelle session si l'attaquant (ou n'importe qui d'autre d'ailleurs) essaie de l'utiliser. Soyez prudent avec les gestionnaires de session personnalisés ...Détruire une session
Si vous allez détruire une session (lors de la déconnexion par exemple), assurez-vous de la détruire complètement. Cela inclut la désactivation du cookie. Utilisation
session_destroy
:la source
session_regenerate_id
n'invalide pas la session qui est toujours associée à l'ancien ID; seulement si le paramètre delete_old_session est défini sur true, la session sera détruite. Mais que se passe-t-il si un attaquant a lancé cette régénération d'identifiant?session.entropy_file = /dev/urandom
. La génération d'entropie interne de PHP s'est avérée extrêmement faible et le pool d'entropie fourni par / dev / random ou / dev / uranom est le meilleur que vous puissiez obtenir sur un serveur Web sans rng matériel.session.cookie_httponly
etsession.cookie_secure
. Le premier aide à contrecarrer xss (mais ce n'est pas parfait). Le 2e est le meilleur moyen d'arrêter OWASP A9 ...Les deux attaques de session ont le même objectif: accéder à une session légitime d'un autre utilisateur. Mais les vecteurs d'attaque sont différents:
Dans une attaque de fixation de session , l'attaquant a déjà accès à une session valide et tente de forcer la victime à utiliser cette session particulière.
Dans une attaque de piratage de session , l'attaquant tente d'obtenir l'ID de la session d'une victime pour utiliser sa session.
Dans les deux attaques, l'ID de session correspond aux données sensibles sur lesquelles ces attaques se concentrent. C'est donc l'ID de session qui doit être protégé à la fois pour un accès en lecture (Session Hijacking) et un accès en écriture (Session Fixation).
La règle générale de protection des données sensibles à l'aide de HTTPS s'applique également dans ce cas. De plus, vous devez effectuer les opérations suivantes:
Pour éviter les attaques de fixation de session , assurez-vous que:
true
) et ne le faites pour HTTPS que si possible (définissez session.cookie_secure surtrue
); vous pouvez faire les deux avecsession_set_cookie_params
.Pour empêcher les attaques de piratage de session , assurez-vous que:
true
)Pour éviter les deux attaques de session, assurez-vous que:
session_regenerate_id(true)
après une tentative d'authentification (true
uniquement en cas de succès) ou un changement de privilèges et détruire l'ancienne session. (Assurez-vous de stocker toutes les modifications d'$_SESSION
utilisationsession_write_close
avant de régénérer l'ID si vous souhaitez conserver la session associée à l'ancien ID; sinon, seule la session avec le nouvel ID sera affectée par ces modifications.)la source
Les jetons que vous mentionnez sont un nombre "nonce" utilisé une fois. Ils ne doivent pas nécessairement être utilisés une seule fois, mais plus ils sont utilisés longtemps, plus les chances que le nonce puisse être capturé et utilisé pour détourner la session sont élevées.
Un autre inconvénient des nonces est qu'il est très difficile de créer un système qui les utilise et autorise plusieurs fenêtres parallèles sur le même formulaire. Par exemple, l'utilisateur ouvre deux fenêtres sur un forum et commence à travailler sur deux messages:
Si vous n'avez aucun moyen de suivre plusieurs fenêtres, vous n'aurez stocké qu'un seul nonce - celui de la fenêtre B / Q. Lorsque l'utilisateur soumet ensuite son message à partir de la fenêtre A et passe en nonce «P», le système rejettera le message comme
P != Q
.la source
Je n'ai pas lu l'article de Shiflett, mais je pense que vous avez mal compris quelque chose.
Par défaut, PHP transmet le jeton de session dans l'URL chaque fois que le client n'accepte pas les cookies. Sinon, dans le cas le plus courant, le jeton de session est stocké sous forme de cookie.
Cela signifie que si vous mettez un jeton de session dans l'URL, PHP le reconnaîtra et essaiera de l'utiliser par la suite. La fixation de session se produit lorsque quelqu'un crée une session, puis incite un autre utilisateur à partager la même session en ouvrant une URL qui contient le jeton de session. Si l'utilisateur s'authentifie d'une manière ou d'une autre, l'utilisateur malveillant connaît alors le jeton de session d'un utilisateur authentifié, qui peut avoir des privilèges différents.
Comme je suis sûr que Shiflett l'explique, la chose habituelle à faire est de régénérer un jeton différent chaque fois que les privilèges d'un utilisateur changent.
la source
Oui, vous pouvez empêcher la fixation de session en régénérant l'identifiant de session une fois lors de la connexion. De cette façon, si l'attaquant ne connaîtra pas la valeur du cookie de la session nouvellement authentifiée. Une autre approche qui arrête totalement le problème est définie
session.use_only_cookies=True
dans votre configuration d'exécution. Un attaquant ne peut pas définir la valeur d'un cookie dans le contexte d'un autre domaine. La fixation de session repose sur l'envoi de la valeur du cookie en tant que GET ou POST.la source