For a TurboGears 2 web application, when the login form is submitted it POST's to /login_handler. If a user session already exists it will reuse the session id and set that as the cookie. If a session does not exist, it creates a new one. I am trying to intercept or modify the logic for /login_handler so that whenever a user POST's to that endpoint and authenticates, if they have a session already it will invalidate it and create a new one, thus giving a new unique session id to increase entropy and attempt to help prevent session fixation. I am testing this with Burp Suite and using the Sequencer to start a live capture and validate the results for the entropy of the session id.

TurboGears 2 uses repoze.who and beaker-py for authentication and session management. I've delved into the TG2 and repoze.who source code and found references to FastFormPlugin and AuthTktCookiePlugin which I believe is what handles the identification/authentication of the auth_tkt cookie for the session. I've tried to create my own simple identifier plugin that removes the environ['HTTP_COOKIE'] value but it still used the old session id.

class TestIdentifier(object):
    def identify(self, environ):
        path_info = environ['PATH_INFO']

        if path_info == "/login_handler":
            query = self._get_form_data(environ)

            try:
                credentials = {'login': query['login'],
                               'password': query['password'],
                               'max_age':query.get('remember')}
            except KeyError:
                credentials = None

            params = {}
            if 'came_from' in query:
                params['came_from'] = query['came_from']

            destination = _build_url(environ, "/post_login", params=params)
            environ['repoze.who.application'] = HTTPFound(location=destination)
            del environ['HTTP_COOKIE']
            return credentials
        elif path_info in ("/login", "/post_login"):
            query = self._get_form_data(environ)
            environ['repoze.who.logins'] = 0

        return None

    def _get_form_data(self, environ):
        request = Request(environ)
        query = dict(request.GET)
        query.update(request.POST)
        return query

I have also attempted a TurboGears application wrapper but the wrapper is never called when the /login_handler endpoint is hit, even when other endpoints are making their way into the wrapper.

class TestWrapper(ApplicationWrapper):
    def __init__(self, handler, config):
        super(TestWrapper, self).__init__(handler, config)

    def __call__(self, controller, environ, context):
        if context.request.path.startswith("/login_handler"):
            logging.info("I am never called")
        return self.next_handler(controller, environ, context)

TLDR; I'd like to be able to access the current turbogears session when the /login_handler is hit and invalidate the user session and get a new session id.

0

There are 0 answers