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.