Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Maintenance:4317
python-django.openSUSE_13.1_Update
0001-1.5.x-Stripped-headers-containing-undersco...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0001-1.5.x-Stripped-headers-containing-underscores-to-pre.patch of Package python-django.openSUSE_13.1_Update
From 3feaba416575f6197b6e08ecb239cf8b9317bbff Mon Sep 17 00:00:00 2001 From: Carl Meyer <carl@oddbird.net> Date: Wed, 10 Sep 2014 11:06:19 -0600 Subject: [PATCH 1/4] [1.5.x] Stripped headers containing underscores to prevent spoofing in WSGI environ. (bnc#913053, CVE-2015-0219) This is a security fix. WSGI header spoofing via underscore/dash conflation. `Full description <https://www.djangoproject.com/weblog/2015/jan/13/security/>` Thanks to Jedediah Smith for the report. cherry-picked-from: d7597b31d5c03106eeba4be14a33b32a5e25f4ee --- django/core/servers/basehttp.py | 11 +++++++ docs/howto/auth-remote-user.txt | 15 +++++++++ tests/servers/test_basehttp.py | 67 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 tests/servers/test_basehttp.py diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py index 9aed637..efc13d2 100644 --- a/django/core/servers/basehttp.py +++ b/django/core/servers/basehttp.py @@ -174,6 +174,17 @@ class WSGIRequestHandler(simple_server.WSGIRequestHandler, object): sys.stderr.write(msg) + def get_environ(self): + # Strip all headers with underscores in the name before constructing + # the WSGI environ. This prevents header-spoofing based on ambiguity + # between underscores and dashes both normalized to underscores in WSGI + # env vars. Nginx and Apache 2.4+ both do this as well. + for k, v in self.headers.items(): + if '_' in k: + del self.headers[k] + + return super(WSGIRequestHandler, self).get_environ() + def run(addr, port, wsgi_handler, ipv6=False, threading=False): server_address = (addr, port) diff --git a/docs/howto/auth-remote-user.txt b/docs/howto/auth-remote-user.txt index 09ae928..cbfc526 100644 --- a/docs/howto/auth-remote-user.txt +++ b/docs/howto/auth-remote-user.txt @@ -66,6 +66,21 @@ If your authentication mechanism uses a custom HTTP header and not class CustomHeaderMiddleware(RemoteUserMiddleware): header = 'HTTP_AUTHUSER' +.. warning:: + + Be very careful if using a ``RemoteUserMiddleware`` subclass with a custom + HTTP header. You must be sure that your front-end web server always sets or + strips that header based on the appropriate authentication checks, never + permitting an end-user to submit a fake (or "spoofed") header value. Since + the HTTP headers ``X-Auth-User`` and ``X-Auth_User`` (for example) both + normalize to the ``HTTP_X_AUTH_USER`` key in ``request.META``, you must + also check that your web server doesn't allow a spoofed header using + underscores in place of dashes. + + This warning doesn't apply to ``RemoteUserMiddleware`` in its default + configuration with ``header = 'REMOTE_USER'``, since a key that doesn't + start with ``HTTP_`` in ``request.META`` can only be set by your WSGI + server, not directly from an HTTP request header. ``RemoteUserBackend`` ===================== diff --git a/tests/servers/test_basehttp.py b/tests/servers/test_basehttp.py new file mode 100644 index 0000000..6bca608 --- /dev/null +++ b/tests/servers/test_basehttp.py @@ -0,0 +1,67 @@ +import sys + +from django.core.servers.basehttp import WSGIRequestHandler +from django.test import TestCase +from django.utils.six import BytesIO, StringIO + + +class Stub(object): + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + + +class WSGIRequestHandlerTestCase(TestCase): + + def test_strips_underscore_headers(self): + """WSGIRequestHandler ignores headers containing underscores. + + This follows the lead of nginx and Apache 2.4, and is to avoid + ambiguity between dashes and underscores in mapping to WSGI environ, + which can have security implications. + """ + def test_app(environ, start_response): + """A WSGI app that just reflects its HTTP environ.""" + start_response('200 OK', []) + http_environ_items = sorted( + '%s:%s' % (k, v) for k, v in environ.items() + if k.startswith('HTTP_') + ) + yield (','.join(http_environ_items)).encode('utf-8') + + rfile = BytesIO() + rfile.write(b"GET / HTTP/1.0\r\n") + rfile.write(b"Some-Header: good\r\n") + rfile.write(b"Some_Header: bad\r\n") + rfile.write(b"Other_Header: bad\r\n") + rfile.seek(0) + + # WSGIRequestHandler closes the output file; we need to make this a + # no-op so we can still read its contents. + class UnclosableBytesIO(BytesIO): + def close(self): + pass + + wfile = UnclosableBytesIO() + + def makefile(mode, *a, **kw): + if mode == 'rb': + return rfile + elif mode == 'wb': + return wfile + + request = Stub(makefile=makefile) + server = Stub(base_environ={}, get_app=lambda: test_app) + + # We don't need to check stderr, but we don't want it in test output + old_stderr = sys.stderr + sys.stderr = StringIO() + try: + # instantiating a handler runs the request as side effect + WSGIRequestHandler(request, '192.168.0.2', server) + finally: + sys.stderr = old_stderr + + wfile.seek(0) + body = list(wfile.readlines())[-1] + + self.assertEqual(body, b'HTTP_SOME_HEADER:good') -- 1.8.1.4
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor