{"title":"Django 1.6.10 release notes","version":"dev","locale":"en","docname":"releases/1.6.10","url":"/en/dev/releases/1.6.10/","canonical":"https://djangodocs.dev/en/dev/releases/1.6.10/","summary":"Django 1.6.10 fixes several security issues in 1.6.9. When HTTP headers are placed into the WSGI environ, they are normalized by converting to uppercase…","html":"<h1>Django 1.6.10 release notes<a class=\"heading-anchor\" href=\"#django-1-6-10-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.6.10 fixes several security issues in 1.6.9.</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=\"database-denial-of-service-with-modelmultiplechoicefield\">\n<h2>Database denial-of-service with <code class=\"docutils literal notranslate\">ModelMultipleChoiceField</code><a class=\"heading-anchor\" href=\"#database-denial-of-service-with-modelmultiplechoicefield\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Given a form that uses <code class=\"docutils literal notranslate\">ModelMultipleChoiceField</code> and\n<code class=\"docutils literal notranslate\">show_hidden_initial=True</code> (not a documented API), it was possible for a user\nto cause an unreasonable number of SQL queries by submitting duplicate values\nfor the field’s data. The validation logic in <code class=\"docutils literal notranslate\">ModelMultipleChoiceField</code> now\ndeduplicates submitted values to address this issue.</p>\n</section>","rootId":"django-1-6-10-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":"Database denial-of-service with ModelMultipleChoiceField","anchor":"database-denial-of-service-with-modelmultiplechoicefield","children":[]}],"breadcrumbs":[{"docname":"releases/index","title":"Release notes","url":"/en/dev/releases/"}],"prev":{"docname":"releases/1.6.11","title":"Django 1.6.11 release notes","url":"/en/dev/releases/1.6.11/"},"next":{"docname":"releases/1.6.9","title":"Django 1.6.9 release notes","url":"/en/dev/releases/1.6.9/"},"formats":{"html":"/en/dev/releases/1.6.10/","markdown":"/en/dev/releases/1.6.10.md","json":"/en/dev/releases/1.6.10.json"},"source":"https://github.com/django/django/blob/main/docs/releases/1.6.10.txt","official":"https://docs.djangoproject.com/en/dev/releases/1.6.10/","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"]}