From d0998d280ee5b38447ed5793590563f9f02e737e Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Tue, 6 Oct 2020 12:40:08 +0200 Subject: [PATCH 1/2] misc: check null characters in query-string and form data (#46625) --- src/authentic2/middleware.py | 20 ++++++++++++++++++++ src/authentic2/settings.py | 1 + tests/test_idp_saml2.py | 5 +++++ tests/test_login.py | 8 ++++++++ 4 files changed, 34 insertions(+) diff --git a/src/authentic2/middleware.py b/src/authentic2/middleware.py index 67638cd6..237146fc 100644 --- a/src/authentic2/middleware.py +++ b/src/authentic2/middleware.py @@ -31,6 +31,7 @@ from django.utils.functional import SimpleLazyObject from django.utils.translation import ugettext as _ from django.utils.six.moves.urllib import parse as urlparse from django.shortcuts import render +from django import http from . import app_settings, utils, plugins from .utils.service import get_service_from_request, get_service_from_session @@ -222,5 +223,24 @@ def journal_middleware(get_response): def middleware(request): request.journal = journal.Journal(request=request) return get_response(request) + return middleware + + +def null_character_middleware(get_response): + def middleware(request): + def check_query_dict(qd): + for key in qd: + for value in qd.getlist(key): + if '\0' in value: + return False + return True + if not check_query_dict(request.GET): + return http.HttpResponseBadRequest('null character in query string') + + if request.content_type == 'application/x-www-form-urlencoded': + if not check_query_dict(request.POST): + return http.HttpResponseBadRequest('null character in form data') + + return get_response(request) return middleware diff --git a/src/authentic2/settings.py b/src/authentic2/settings.py index ab8ce4fe..e49dd0da 100644 --- a/src/authentic2/settings.py +++ b/src/authentic2/settings.py @@ -88,6 +88,7 @@ TEMPLATES = [ MIDDLEWARE = ( + 'authentic2.middleware.null_character_middleware', 'authentic2.middleware.StoreRequestMiddleware', 'authentic2.middleware.RequestIdMiddleware', 'authentic2.middleware.ServiceAccessControlMiddleware', diff --git a/tests/test_idp_saml2.py b/tests/test_idp_saml2.py index 182bc38d..209a434a 100644 --- a/tests/test_idp_saml2.py +++ b/tests/test_idp_saml2.py @@ -968,3 +968,8 @@ uGnhj8v6XwvbjKZrL9kA+xf8ziazZfvvw/VGTm+IVFYB7d1x457jY5zjjXJvNyso owIDAQAB -----END PUBLIC KEY-----''' response = app.get('/idp/saml2/metadata') + + +def test_null_character_nonce(app, db): + response = app.get('/idp/saml2/continue/', params={'nonce': '\0'}, status=400) + assert response.text == 'null character in query string' diff --git a/tests/test_login.py b/tests/test_login.py index dc9e97a6..ad0a3633 100644 --- a/tests/test_login.py +++ b/tests/test_login.py @@ -318,3 +318,11 @@ def test_login_opened_session_cookie(db, app, settings, simple_user): for cookie in app.cookiejar: if cookie.name == 'A2_OPENED_SESSION': assert cookie.secure is True + + +def test_null_characters(app, db): + response = app.get('/login/') + response.form.set('username', 'xx\0xx') + response.form.set('password', 'whatever') + response = response.form.submit(name='login-password-submit', status=400) + assert response.text == 'null character in form data' -- 2.28.0