[spip-dev] piratage de session

En relisant
<http://cvsweb.tuxfamily.org/cvs/spip_doc/auth.txt?rev=1.1&cvsroot=spipcvs>
je m'aperçois qu'il y a un piratage possible si on peut chopper un cookie
d'admin. "Ca ne dure que 48 heures" -- tiens, c'est pas implémenté encore
les 48 heures -- ça ne marche pas si je me passe en douce comme admin.

Méthode : je m'inscris comme rédacteur, je propose un article/forum avec un
  jajascript onLoad=... et j'attrape le cookie d'un autre, que je m'empresse
  d'utiliser, si c'est un admin, pour ME passer admin. Là je dé/valide des
  articles, je modère les forums, etc.

Bon, ce hack est pas évident à implémenter, mais le risque existe. Et le coup
des 48 heures ne résoud pas le pb...

Avec le cookie de session, on est plus fragile qu'avec un mot de passe :

1) le cookie peut être piqué par jajascript

2) lorsqu'on pose le cookie, c'est via l'URL
   spip_cookie.php3?cookie=A1234343 qui reste dans l'historique du
   navigateur... donc même si on quitte/relance le navigateur... sympa dans
   les cybercafés, si tu oublies de te déloguer... celui qui passe après toi
   peut tomber sur ton accès admin même sans faire exprès !

Des idées (simples...) ? Je mettrais bien l'IP dans le fichier de sessions,
histoire de limiter les dégâts en cas de (1). Pour (2) je ne vois pas.

-- Fil

Et si tu appellais tout simplement les fcts utilisées ds spip_cookie ??? => Tu passe par tes includes, … ect.

Mais de toute manière, je ne vois pas où est le pb … Moi j’utilise des cookie, mais dès que je ferme le navigateur, mes identifications sont mortes …

Emilien

Mais de toute manière, je ne vois pas où est le pb ... Moi j'utilise des
cookie, mais dès que je ferme le navigateur, mes identifications sont
mortes ...

En détails :

Disons que je propose dans les forums de ton site un petit blah blah qui
contient un tag du genre <a href=".."
onMouseOver="javascript:...url...spip_session">toto</a>

intrigué par le lien que tu as vu dans mon message, tu passes la souris
dessus, et ton navigateur envoit une requête sur mon serveur, à l'adresse
http://url/… valeur(spip_session)

A cet endroit j'ai un script qui m'envoit un mail, je me connecte tout de
suite sur ton ecrire/ avec ton cookie : comme tu ne t'es pas délogué, le
cookie de session est valide. Je suis admin, j'ai tout juste le temps de me
créer en douce un autre compte admin. J'attends ensuite que tu te délogues
(on me demande alors de m''identifier : je sais que tu n'es plus là) et je
suis admin tout seul sur le site, donc indétecté (pas indétectable, mais
indétecté).

On doit pouvoir casser ce hack en surveillant de près 'spip_session' dans la
fonction interdire_scripts, mais c'est pas très beau ni facile.

-- Fil

Autre chose : la durée de vie des sessions.

* ajoutons dans inc_sessions_cache.php3 la date de création de chaque session

* expirons les "vieilles" sessions (48 h ?) pour alléger ce fichier

est-ce qu'on faire mieux que ça ?

-- Fil

@ Emilien ARNAUD <creatixea@creanet.creatixea.eu.org> :

Hum... et si à un numéro de session on attribuait l'IP ???
Et pis une tite vérification :slight_smile: Et le tour est joué.
En somme le seul numéro de session n'est pas valide tout seul, il faut
qu'il soit associé à la bonne IP.
Evidemment, dans un cyber café, il peuvnt avoir la mm IP ... mdr ! Mais
bon, faut pas pousser le bouchon trop loin non plus :slight_smile:

En matière de sécurité de spip il faut pousser le bouchon le plus loin
possible - et voir si ça mord. L'IP, c'est une idée, un md5(IP + X_FORWARDED
+ caractéristiques du brouteur) serait mieux encore (pour éviter les
problèmes d'IP partagée). Ces solutions sont toutes hackables par quelqu'un
de déterminé -- même si l'IP + FORWARDED ça devient un peu dur à émuler.

Quant au problème du cybercafé, c'est juste l'URL appelant spip_cookie qui
me gêne. Il faudrait, lorsqu'on crée le cookie, le mettre dans
inc_sessions_cache.php3, associé à un code jetable qu'on passe dans l'URL.

-- Fil

C'est ce que j'avais déjà fait à l'époque des premiers essais avec cookie. Facile et immédiat. C'était un trou de sécurité classique de phpNuke.

ARNO*

Hello,

toute cette discussion sur la sécurité et le piratage m'intéresse au
plus haut point, mais j'ai du mal à suivre vos échanges ... :wink:

je m'aperçois qu'il y a un piratage possible si on peut chopper un
cookie d'admin.

En effet.

Avec le cookie de session, on est plus fragile qu'avec un mot de
passe :
1) le cookie peut être piqué par jajascript
2) lorsqu'on pose le cookie, c'est via l'URL

Des idées (simples...) ? Je mettrais bien l'IP dans le fichier de
sessions, histoire de limiter les dégâts en cas de (1).

Voir la fonction très complète de Marc Meurrens :
http://www.cgsa.net/php/identifierShow.php

Pour (2) je ne vois pas.

Pourquoi passer par une URL pour poser un cookie ???

-Nicolas

Autre chose : la durée de vie des sessions.

* ajoutons dans inc_sessions_cache.php3 la date de création de
  chaque session

Il faudrait plutôt la date de dernière modif, c'est à dire la date à
laquelle l'utilisateur a chargé une page pour la dernière fois.

* expirons les "vieilles" sessions (48 h ?) pour alléger ce fichier

Les vieilles sessions sont alors celles qui n'ont pas été modifiées
depuis 1h, par exemple, ça devrait suffire.

-Nicolas

Voir la fonction très complète de Marc Meurrens :
http://www.cgsa.net/php/identifierShow.php

C'est too much, car on veut juste un truc unique. J'en suis là :

    // un truc le plus unique possible mais constant brouteur + numero ip
    function md5_brouteur() {
        return md5 (getenv('REMOTE_ADDR') . getenv('HTTP_USER_AGENT') . getenv('HTTP_X_FORWARDED_FOR'));
    }

ça suffit pas ?

Pourquoi passer par une URL pour poser un cookie ???

C'est pour le cas où tu veux poser le cookie depuis ecrire/ - mais à la
réflexion c'est inutilisé, je vais virer ce cas-là : on n'a qu'à poser le
cookie via spip_cookie.

Derniers (?) commits bientôt.

-- Fil

> * ajoutons dans inc_sessions_cache.php3 la date de création de
> chaque session

Il faudrait plutôt la date de dernière modif, c'est à dire la date à
laquelle l'utilisateur a chargé une page pour la dernière fois.

Le problème, c'est que je ne veux pas réécrire le fichier cache des sessions
à chaque passage dans ecrire/ !! D'autant que c'est en tête de traitements,
pas en queue...

-- Fil

Il faudrait plutôt la date de dernière modif, c'est à dire la date
à laquelle l'utilisateur a chargé une page pour la dernière fois

Le problème, c'est que je ne veux pas réécrire le fichier cache des
sessions à chaque passage dans ecrire/ !!

Ouh la, il faut passer dans 'ecrire/' pour s'identifier ???

De toute façon, il faut mieux avoir un fichier par session, ça permet
d'utiliser la date de modif du fichier, et on peut l'utiliser comme
"vraie" session, avec d'éventuelles données utilisteur.

-Nicolas

@ Nicolas Hoizey <nhoizey@phpheaven.net> :

>> Il faudrait plutôt la date de dernière modif, c'est à dire la date
>> à laquelle l'utilisateur a chargé une page pour la dernière fois
>
> Le problème, c'est que je ne veux pas réécrire le fichier cache des
> sessions à chaque passage dans ecrire/ !!

Ouh la, il faut passer dans 'ecrire/' pour s'identifier ???

Non. Tu veux dire qu'il faut récrire le fichier de session (au singulier) à
chaque passage sur n'importe quelle page ( inc-public, ou ecrire/ ) ???

De toute façon, il faut mieux avoir un fichier par session, ça permet
d'utiliser la date de modif du fichier, et on peut l'utiliser comme
"vraie" session, avec d'éventuelles données utilisteur.

Ah, c'était bien ça ! Pfff.... Il faudra recommencer, alors... Réécrire la
fonction ajoute_session(), en gros, et éventuellement
verifie_cookie_session()

-- Fil

Voir la fonction très complète de Marc Meurrens :
http://www.cgsa.net/php/identifierShow.php

C'est too much, car on veut juste un truc unique. J'en suis là :

// un truc le plus unique possible mais constant brouteur + numero ip
function md5_brouteur() {
    return md5 (getenv('REMOTE_ADDR') . getenv('HTTP_USER_AGENT') . getenv('HTTP_X_FORWARDED_FOR'));
}

ça suffit pas ?

Non, ça ne suffit pas forcément, cf
http://groups.google.com/groups?selm=8cn5j1%24ljf%241%40mach.vub.ac.be&output=gplain

Ce travail de Marc Meurrens a fait suite à de longues discussions sur
fciwap et de nombreux tests.

Pourquoi passer par une URL pour poser un cookie ???

C'est pour le cas où tu veux poser le cookie depuis ecrire/

Et alors ??? Je ne comprend pas du tout où est le problème, à vrai
dire, je dois être mal réveillé ... :wink:

mais à la réflexion c'est inutilisé, je vais virer ce cas-là : on
n'a qu'à poser le cookie via spip_cookie.

OK.

Derniers (?) commits bientôt.

Attention, précise que c'est pour ce point précis, sinon tout le monde
va croire que la 1.4 est pour tout de suite !!! :slight_smile:

-Nicolas

> return md5 (getenv('REMOTE_ADDR') . getenv('HTTP_USER_AGENT') . getenv('HTTP_X_FORWARDED_FOR'));
> ça suffit pas ?
Non, ça ne suffit pas forcément, cf
http://groups.google.com/groups?selm=8cn5j1%24ljf%241%40mach.vub.ac.be&output=gplain

Tu n'as pas compris : je me fous de savoir quel est le vrai IP du client. Je
veux juste un truc difficile à "spoofer" émuler (donc contenant, quelque
part, l'ip) et relativement stable pour un même client.

-- Fil

Ouh la, il faut passer dans 'ecrire/' pour s'identifier ???

Non. Tu veux dire qu'il faut récrire le fichier de session (au
singulier) à chaque passage sur n'importe quelle page ( inc-public,
ou ecrire/ ) ???

Oui, on modifie le fichier de session de l'utilisateur à chaque
chargement de page, c'est le mécanisme standard des sessions.

De toute façon, il faut mieux avoir un fichier par session, ça
permet d'utiliser la date de modif du fichier, et on peut
l'utiliser comme "vraie" session, avec d'éventuelles données
utilisteur.

Ah, c'était bien ça ! Pfff.... Il faudra recommencer, alors...
Réécrire la fonction ajoute_session(), en gros, et éventuellement
verifie_cookie_session()

On peut modifier ma lib dbSession qui gère de manière transparente le
fait d'être sous PHP3 ou PHP4, mais en lui faisant utiliser des
fichiers plutôt que la base. Elle sera encore plus simple. Je peux le
faire d'ici cet après-midi, si vous voulez tester ...

-Nicolas

Non, ça ne suffit pas forcément, cf
http://groups.google.com/groups?selm=8cn5j1%24ljf%241%40mach.vub.ac.be&output=gplain

Tu n'as pas compris : je me fous de savoir quel est le vrai IP du
client. Je veux juste un truc difficile à "spoofer" émuler (donc
contenant, quelque part, l'ip) et relativement stable pour un même
client.

Donc si tu veux éviter le problème des proxy, auquel seront confrontés
beaucoup d'utilisateurs, il faut utiliser la fonction de Marc, je
pense.

-Nicolas

> Ah, c'était bien ça ! Pfff.... Il faudra recommencer, alors...
> Réécrire la fonction ajoute_session(), en gros, et éventuellement
> verifie_cookie_session()

On peut modifier ma lib dbSession qui gère de manière transparente le
fait d'être sous PHP3 ou PHP4, mais en lui faisant utiliser des
fichiers plutôt que la base. Elle sera encore plus simple. Je peux le
faire d'ici cet après-midi, si vous voulez tester ...

La fonction qui stocke les sessions fait 20 lignes, hein ! Ne nous refile
pas une librairie de 300ko!

-- Fil

Donc si tu veux éviter le problème des proxy, auquel seront confrontés
beaucoup d'utilisateurs, il faut utiliser la fonction de Marc, je
pense.

Euh, c'est toi l'informaticien... mais je ne crois pas qu'on ait besoin de
faire un appel dns pour générer ce qu'il nous faut : il suffit d'aller
chercher tous les getenv() pertinents, de les mettre bout à bout, et de
hasher. C'est ce que je fais, sur 3 variables. On peut en ajouter.

-- Fil

On peut modifier ma lib dbSession [...]

La fonction qui stocke les sessions fait 20 lignes, hein ! Ne nous
refile pas une librairie de 300ko!

Pas d'inquiétude !!! :stuck_out_tongue:

Je fais ça pour cet après-midi ...

-Nicolas

Donc si tu veux éviter le problème des proxy, auquel seront
confrontés beaucoup d'utilisateurs, il faut utiliser la fonction de
Marc, je pense.

Euh, c'est toi l'informaticien...

Ouah, l'insulte !!! :smiley:

je ne crois pas qu'on ait besoin de faire un appel dns pour générer
ce qu'il nous faut : il suffit d'aller chercher tous les getenv()
pertinents, de les mettre bout à bout, et de hasher.

En effet, je suis allé un peu trop vite sans regarder le source de sa
dernière version ... :wink:

C'est ce que je fais, sur 3 variables. On peut en ajouter.

Voilà sa liste :

$HTTP_VIA
$HTTP_X_COMING_FROM
$HTTP_X_FORWARDED_FOR
$HTTP_X_FORWARDED
$HTTP_COMING_FROM
$HTTP_FORWARDED_FOR
$HTTP_FORWARDED
$REMOTE_ADDR

-Nicolas