CVE-2012-2144 (Python, published 2012-06-05T22:55Z)
Description: value: Session fixation vulnerability in OpenStack Dashboard (Horizon) folsom-1 and 2012.1 allows remote attackers to hijack web sessions via the sessionid cookie.
Severity: MEDIUM (CVSS v3 base score: )
Weakness: NVD-CWE-Other \u2014 Other
NVD is only using a subset of CWE for mapping instead of the entire CWE, and the weakness type is not covered by that subset.
Repository: https://github.com/openstack/horizon
Files changed:
horizon/exceptions.py
horizon/middleware.py
horizon/tests/auth_tests.py
horizon/users.py
horizon/views/auth.py
horizon/views/auth_forms.py
Commit message: Fixes lp978896 -- Session fixation security fix

Rotates session tokens on logout, and properly clears sessions
to prevent data leakage.

Change-Id: I52d03576d07b1e023a7730857156d0da1887b1df


Vulnerable code:
        request.session.clear()
        request.session.clear()
    request.session.clear()
                request.session.clear()

Fixed code:
        request.user_logout()
        # A quick and dirty way to log users out
        def user_logout(request):
            if hasattr(request, '_cached_user'):
                del request._cached_user
            # Use flush instead of clear, so we rotate session keys in
            # addition to clearing all the session data
            request.session.flush()
        request.__class__.user_logout = user_logout

import time


    def test_session_fixation(self):
        session_ids = []
        form_data = {'method': 'Login',
                     'region': 'http://localhost:5000/v2.0',
                     'password': self.user.password,
                     'username': self.user.name}

        self.mox.StubOutWithMock(api, 'token_create')
        self.mox.StubOutWithMock(api, 'tenant_list_for_token')
        self.mox.StubOutWithMock(api, 'token_create_scoped')

        aToken = self.tokens.unscoped_token
        bToken = self.tokens.scoped_token

        api.token_create(IsA(http.HttpRequest), "", self.user.name,
                         self.user.password).AndReturn(aToken)
        api.tenant_list_for_token(IsA(http.HttpRequest),
                                  aToken.id).AndReturn([self.tenants.first()])
        api.token_create_scoped(IsA(http.HttpRequest),
                                self.tenant.id,
                                aToken.id).AndReturn(bToken)

        api.token_create(IsA(http.HttpRequest), "", self.user.name,
                         self.user.password).AndReturn(aToken)
        api.tenant_list_for_token(IsA(http.HttpRequest),
                                  aToken.id).AndReturn([self.tenants.first()])
        api.token_create_scoped(IsA(http.HttpRequest),
                                self.tenant.id,
                                aToken.id).AndReturn(bToken)
        self.mox.ReplayAll()

        res = self.client.get(reverse('horizon:auth_login'))
        self.assertEqual(res.cookies.get('sessionid'), None)
        res = self.client.post(reverse('horizon:auth_login'), form_data)
        session_ids.append(res.cookies['sessionid'].value)

        self.assertEquals(self.client.session['user_name'],
                          self.user.name)
        self.client.session['foobar'] = 'MY TEST VALUE'
        res = self.client.get(reverse('horizon:auth_logout'))
        session_ids.append(res.cookies['sessionid'].value)
        self.assertEqual(len(self.client.session.items()), 0)
        # Sleep for 1 second so the session values are different if
        # using the signed_cookies backend.
        time.sleep(1)
        res = self.client.post(reverse('horizon:auth_login'), form_data)
        session_ids.append(res.cookies['sessionid'].value)
        # Make sure all 3 session id values are different
        self.assertEqual(len(session_ids), len(set(session_ids)))
        request.user_logout()
    request.user_logout()
        if 'user_name' in request.session:
            if request.session['user_name'] != data['username']:
                # To avoid reusing another user's session, create a
                # new, empty session if the existing session
                # corresponds to a different authenticated user.
                request.session.flush()
        # Always cycle the session key when viewing the login form to
        # prevent session fixation
        request.session.cycle_key()

                request.user_logout()