Changeset - a0a9ae753cc4
[Not reviewed]
stable
0 2 0
Søren Løvborg - 10 years ago 2015-09-18 13:57:49
sorenl@unity3d.com
login: simplify came_from validation

Even though only server-relative came_from URLs were ever generated,
the login controller allowed fully qualified URLs (URLs including
scheme and server). To avoid an open HTTP redirect (CWE-601), the code
included logic to prevent redirects to other servers. By requiring
server-relative URLs, this logic can simply be removed.

Note: SCRIPT_NAME is still not validated and it is thus possible to redirect
from one app to another on the same netloc.
2 files changed with 5 insertions and 22 deletions:
0 comments (0 inline, 0 general)
kallithea/controllers/login.py
Show inline comments
 
@@ -55,27 +55,14 @@ class LoginController(BaseController):
 

	
 
    def __before__(self):
 
        super(LoginController, self).__before__()
 

	
 
    def _validate_came_from(self, came_from):
 
        """Return True if came_from is valid and can and should be used"""
 
        if not came_from:
 
            return False
 

	
 
        parsed = urlparse.urlparse(came_from)
 
        server_parsed = urlparse.urlparse(url.current())
 
        allowed_schemes = ['http', 'https']
 
        if parsed.scheme and parsed.scheme not in allowed_schemes:
 
            log.error('Suspicious URL scheme detected %s for url %s',
 
                     parsed.scheme, parsed)
 
            return False
 
        if server_parsed.netloc != parsed.netloc:
 
            log.error('Suspicious NETLOC detected %s for url %s server url '
 
                      'is: %s' % (parsed.netloc, parsed, server_parsed))
 
            return False
 
        return True
 
        url = urlparse.urlsplit(came_from)
 
        return not url.scheme and not url.netloc
 

	
 
    def index(self):
 
        c.came_from = safe_str(request.GET.pop('came_from', ''))
 
        if c.came_from:
 
            if not self._validate_came_from(c.came_from):
 
                log.error('Invalid came_from (not server-relative): %r', c.came_from)
kallithea/tests/functional/test_login.py
Show inline comments
 
@@ -102,24 +102,20 @@ class TestLoginController(TestController
 
    @parameterized.expand([
 
          ('data:text/html,<script>window.alert("xss")</script>',),
 
          ('mailto:test@example.com',),
 
          ('file:///etc/passwd',),
 
          ('ftp://ftp.example.com',),
 
          ('http://other.example.com/bl%C3%A5b%C3%A6rgr%C3%B8d',),
 
          ('//evil.example.com/',),
 
    ])
 
    def test_login_bad_came_froms(self, url_came_from):
 
        response = self.app.post(url(controller='login', action='index',
 
                                     came_from=url_came_from),
 
                                 {'username': TEST_USER_ADMIN_LOGIN,
 
                                  'password': TEST_USER_ADMIN_PASS})
 
        self.assertEqual(response.status, '302 Found')
 
        self.assertEqual(response._environ['paste.testing_variables']
 
                         ['tmpl_context'].came_from, '/')
 
        response = response.follow()
 

	
 
        self.assertEqual(response.status, '200 OK')
 
                                  'password': TEST_USER_ADMIN_PASS},
 
                                 status=400)
 

	
 
    def test_login_short_password(self):
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': TEST_USER_ADMIN_LOGIN,
 
                                  'password': 'as'})
 
        self.assertEqual(response.status, '200 OK')
0 comments (0 inline, 0 general)