{"title":"Django 1.4.18 release notes","version":"dev","locale":"en","docname":"releases/1.4.18","url":"/en/dev/releases/1.4.18/","canonical":"https://djangodocs.dev/en/dev/releases/1.4.18/","summary":"Django 1.4.18 fixes several security issues in 1.4.17 as well as a regression on Python 2.5 in the 1.4.17 release.","html":"<h1>Django 1.4.18 release notes<a class=\"heading-anchor\" href=\"#django-1-4-18-release-notes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p><em>January 13, 2015</em></p>\n<p>Django 1.4.18 fixes several security issues in 1.4.17 as well as a regression\non Python 2.5 in the 1.4.17 release.</p>\n<section id=\"wsgi-header-spoofing-via-underscore-dash-conflation\">\n<h2>WSGI header spoofing via underscore/dash conflation<a class=\"heading-anchor\" href=\"#wsgi-header-spoofing-via-underscore-dash-conflation\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>When HTTP headers are placed into the WSGI environ, they are normalized by\nconverting to uppercase, converting all dashes to underscores, and prepending\n<code class=\"docutils literal notranslate\">HTTP_</code>. For instance, a header <code class=\"docutils literal notranslate\">X-Auth-User</code> would become\n<code class=\"docutils literal notranslate\">HTTP_X_AUTH_USER</code> in the WSGI environ (and thus also in Django’s\n<code class=\"docutils literal notranslate\">request.META</code> dictionary).</p>\n<p>Unfortunately, this means that the WSGI environ cannot distinguish between\nheaders containing dashes and headers containing underscores: <code class=\"docutils literal notranslate\">X-Auth-User</code>\nand <code class=\"docutils literal notranslate\">X-Auth_User</code> both become <code class=\"docutils literal notranslate\">HTTP_X_AUTH_USER</code>. This means that if a\nheader is used in a security-sensitive way (for instance, passing\nauthentication information along from a front-end proxy), even if the proxy\ncarefully strips any incoming value for <code class=\"docutils literal notranslate\">X-Auth-User</code>, an attacker may be\nable to provide an <code class=\"docutils literal notranslate\">X-Auth_User</code> header (with underscore) and bypass this\nprotection.</p>\n<p>In order to prevent such attacks, both Nginx and Apache 2.4+ strip all headers\ncontaining underscores from incoming requests by default. Django’s built-in\ndevelopment server now does the same. Django’s development server is not\nrecommended for production use, but matching the behavior of common production\nservers reduces the surface area for behavior changes during deployment.</p>\n</section>\n<section id=\"mitigated-possible-xss-attack-via-user-supplied-redirect-urls\">\n<h2>Mitigated possible XSS attack via user-supplied redirect URLs<a class=\"heading-anchor\" href=\"#mitigated-possible-xss-attack-via-user-supplied-redirect-urls\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django relies on user input in some cases (e.g.\n<code class=\"docutils literal notranslate\">django.contrib.auth.views.login()</code> and <a class=\"reference internal\" href=\"/en/dev/topics/i18n/\"><span class=\"doc\">i18n</span></a>)\nto redirect the user to an “on success” URL. The security checks for these\nredirects (namely <code class=\"docutils literal notranslate\">django.utils.http.is_safe_url()</code>) didn’t strip leading\nwhitespace on the tested URL and as such considered URLs like\n<code class=\"docutils literal notranslate\">\\njavascript:...</code> safe. If a developer relied on <code class=\"docutils literal notranslate\">is_safe_url()</code> to\nprovide safe redirect targets and put such a URL into a link, they could suffer\nfrom a XSS attack. This bug doesn’t affect Django currently, since we only put\nthis URL into the <code class=\"docutils literal notranslate\">Location</code> response header and browsers seem to ignore\nJavaScript there.</p>\n</section>\n<section id=\"denial-of-service-attack-against-django-views-static-serve\">\n<h2>Denial-of-service attack against <code class=\"docutils literal notranslate\">django.views.static.serve</code><a class=\"heading-anchor\" href=\"#denial-of-service-attack-against-django-views-static-serve\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>In older versions of Django, the <a class=\"reference internal\" href=\"/en/dev/ref/views/#django.views.static.serve\" title=\"django.views.static.serve\"><code class=\"xref py py-func docutils literal notranslate\">django.views.static.serve()</code></a> view read\nthe files it served one line at a time. Therefore, a big file with no newlines\nwould result in memory usage equal to the size of that file. An attacker could\nexploit this and launch a denial-of-service attack by simultaneously requesting\nmany large files. This view now reads the file in chunks to prevent large\nmemory usage.</p>\n<p>Note, however, that this view has always carried a warning that it is not\nhardened for production use and should be used only as a development aid. Now\nmay be a good time to audit your project and serve your files in production\nusing a real front-end web server if you are not doing so.</p>\n</section>\n<section id=\"bugfixes\">\n<h2>Bugfixes<a class=\"heading-anchor\" href=\"#bugfixes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<ul class=\"simple\">\n<li><p>To maintain compatibility with Python 2.5, Django’s vendored version of six,\n<code class=\"docutils literal notranslate\">django.utils.six</code>, has been downgraded to 1.8.0 which is the last\nversion to support Python 2.5.</p></li>\n</ul>\n</section>","rootId":"django-1-4-18-release-notes","toc":[{"title":"WSGI header spoofing via underscore/dash conflation","anchor":"wsgi-header-spoofing-via-underscore-dash-conflation","children":[]},{"title":"Mitigated possible XSS attack via user-supplied redirect URLs","anchor":"mitigated-possible-xss-attack-via-user-supplied-redirect-urls","children":[]},{"title":"Denial-of-service attack against django.views.static.serve","anchor":"denial-of-service-attack-against-django-views-static-serve","children":[]},{"title":"Bugfixes","anchor":"bugfixes","children":[]}],"breadcrumbs":[{"docname":"releases/index","title":"Release notes","url":"/en/dev/releases/"}],"prev":{"docname":"releases/1.4.19","title":"Django 1.4.19 release notes","url":"/en/dev/releases/1.4.19/"},"next":{"docname":"releases/1.4.17","title":"Django 1.4.17 release notes","url":"/en/dev/releases/1.4.17/"},"formats":{"html":"/en/dev/releases/1.4.18/","markdown":"/en/dev/releases/1.4.18.md","json":"/en/dev/releases/1.4.18.json"},"source":"https://github.com/django/django/blob/main/docs/releases/1.4.18.txt","official":"https://docs.djangoproject.com/en/dev/releases/1.4.18/","inVersions":["dev","6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9","1.8"],"inLocales":["en"]}