Vérification systématique du type de session dans SessionNamespace#5933
Conversation
475a053 to
f1de717
Compare
|
Je t'ai ajouté à ma PR #5931 |
EwenKorr
left a comment
There was a problem hiding this comment.
C'est élégant et plus générique en effet.
dejafait
left a comment
There was a problem hiding this comment.
LGTM et j'apprends plein de trucs sur notre mécanisme de session, merci 😊
| view. | ||
| """ | ||
| try: | ||
| session_kind = self._session[self.session_kind_key] |
There was a problem hiding this comment.
Un peu naïvement j'aurais plutôt mis ça en dessous de self._session[self.name] afin que tout soit contenu au même endroit mais ça veux dire devoir ajouter un niveau entre self._session[self.name] et data si on ne veux pas polluer 🤔.
There was a problem hiding this comment.
La transition m’a fait un peu peur, parce qu’il faudrait réécrire les sessions en cours. Et l’accès direct via request.session["name"] serait cassé (bien qu’il ne soit pas encouragé). J’ai trouvé que stocker les données à côté permettait de répondre au problème de manière moins invasive.
| session_kind = None | ||
| if session_kind is not None and session_kind != self.expected_session_kind: | ||
| logger.warning(f"Loading a {session_kind} while expecting a {self.expected_session_kind}.") | ||
| raise Http404 |
There was a problem hiding this comment.
Pas sûr que Http404 soit la bonne exception, le type ne devrais pas être différent donc si on est dans ce cas alors c'est qu'il y a un loup et donc on veux un truc qui casse bien fort et pas être silencieux.
There was a problem hiding this comment.
Http404 ne devrait se produire que si la session est corrompue (elle a un session_kind qui n’est pas l’attendu).
On peut mettre un erreur plus costaud pour Sentry.
Http404 n’est pas une super exception, mais permet de mutualiser le comportement actuel plutôt que de demander à chaque utilisateur de SessionNamespace de garder chaque lecture avec try: ... except SessionCorrupted: raise Http404.
There was a problem hiding this comment.
Pour moi on ne veux pas spécialement attraper l'erreur mais la laisser passer, pour moi on est dans la même logique que le token CSRF ou autre joyeuseté de ce type donc retourner une 404 me semble bizarre pour ce genre de truc.
There was a problem hiding this comment.
Dans un monde parfait, oui. C’est aux vues de décider quoi faire en cas d’erreur, et pas à un utilitaire de gestion de session.
Le problème est que l’erreur peut sortir à n’importe quel appel, parce que le SessionNamespace est initialisé paresseusement. Si SessionNamespace accédait immédiatement à la session, on pourrait ne garder que dans __init__() et demander aux appelant de gérer ce cas. Vu la multitude de méthode de l’API de SessionNamespace, une demander à l’appelant de garder chaque appel me semble se faire des nœuds au cerveau.
J’ai déjà pensé plein de fois à passer SessionNamespace en accès immédiat, mais c’est long et pénible, et les gains me semblent minimes.
Si on veut, on peut aussi définir une:
class SessionNamespaceCorrupted(Http404):
passÇa permet aux vues « bonnes élèves » de gérer proprement le cas, et d’éviter la 500 sur les autres.
8ed8f7b to
da2657c
Compare
| if session_kind is not None and session_kind != self.expected_session_kind: | ||
| logger.warning(f"Loading a {session_kind} while expecting a {self.expected_session_kind}.") | ||
| raise Http404 | ||
| self.kind_verified = True |
There was a problem hiding this comment.
On marquera les sessions actives qui ne vérifiaient pas session_kind comme verified. C’est juste pour une semaine et pas bien pire que le comportement actuel.
There was a problem hiding this comment.
On est d'accord que cela ne concerne que la session de candidature ?
|
J’ai poussé un fixup pour les deux commentaires résolus :
|
|
Sans autre retour, je pense merger cette PR en l’état (après squash) demain. J’accorde très facilement des délais supplémentaires sur simple MP. |
| if session_kind is not None and session_kind != self.expected_session_kind: | ||
| logger.warning(f"Loading a {session_kind} while expecting a {self.expected_session_kind}.") | ||
| raise Http404 | ||
| self.kind_verified = True |
There was a problem hiding this comment.
On est d'accord que cela ne concerne que la session de candidature ?
rsebille
left a comment
There was a problem hiding this comment.
Toujours circonspect d'utiliser http404 mais c'est ce que font les wizard actuellement donc soit 🤷.
Will help land future changes, where more keys should be ignored according with `.endswith()`.
Multiple forms on the site are quite long, and were split over multiple pages, storing the intermediary data in the session. Data is only written to the database at the end of the editing process. In order to work well with tabs, the sessions are namespaced (usually stored under a UUID at the root of the session), and the user passes the namespace through the URL. Which means the user can read the UUID from the URL, and try reusing a session from an editing process in other views, allowing users to somewhat manipulate their session. Although most processes are expected to fail when given data from another editing process, it remains a security risk as developers cannot reasonably keep track of the intersection of session data for all editing processes on the site. To protect against such issues, some views (subclasses of WizardView) store a session_kind, and verify it when they load the user session. Generalize the verification to all `SessionNamespace`, to force all users of `SessionNamespace` to follow that pattern.
294afce to
3d0e0f8
Compare
🤔 Pourquoi ?
Sécurité : détecter les pollutions de sessions par les utilisateurs et s’en prémunir. La session est un endroit supposé sûr, hors du contrôle des utilisateurs.