title: Django admin interface doesn't perform server side checks to determine validity of csrf token
body: <p>I've just had some penetration testers decide that my Django admin is potentially exposed to a CSRF attack. Given that I only heard of a CSRF attack when they told me about this, I'm going with this being a configuration issue on my part only I can't seem to find where.</p>
  <p>Steps to reproduce:</p>
  <ol>
  <li>Download Burp Suite Community Edition</li>
  <li>Open Browser (from within Burp Suite)</li>
  <li>Sign into your Django admin portal</li>
  <li>Navigate to &quot;Authentication and Authorization&quot; -&gt; &quot;Users&quot;</li>
  <li>Select a user</li>
  <li>Modify the first name attribute (do not click save just yet)</li>
  <li>Turn &quot;Intercept On&quot; within Burp Suite (this will catch the request before it hits your django app)</li>
  <li>Back within the browser click &quot;Save&quot;</li>
  <li>Burp suite will catch the request, at this point you should be able to see something like</li>
  </ol>
  <pre><code>Cookie: csrftoken=HoBcgZfhlb1W5Km3F7NL37BKv9XkNvGYcYSO6h4LzZxF5ceLbShbcmiSl9py9iY2; sessionid=ioo36waf6i7sclcj33stv8lminx3u36e
  Connection: close
  
  csrfmiddlewaretoken=hUR7ZNj0UdeqOBUtoP973QVeQEeHd3KnMu8JP58u81K9O3MbUADxc5CmGEGVzQ2r&amp;username=dev&amp;first_name=tony&amp;last_name=&amp;email=&amp;is_active=on&amp;is_staff=on&amp;is_superuser=on&amp;last_login_0=2020-08-08&amp;last_login_1=09%3A19%3A32&amp;date_joined_0=2020-08-05&amp;date_joined_1=16%3A02%3A29&amp;initial-date_joined_0=2020-08-05&amp;initial-date_joined_1=16%3A02%3A29&amp;_save=Save
  </code></pre>
  <ol start="10">
  <li>Change the values within the csrftoken and csrfmiddlewaretoken to something else that is 64 char's in length (note, the values for both csrftoken and csrfmiddlewaretoken must match each other, but can be completely different to what they were originally) and for good measure change the value of first_name e.g.</li>
  </ol>
  <pre><code>Cookie: csrftoken=1234567812345678123456781234567812345678123456781234567812345678; sessionid=ioo36waf6i7sclcj33stv8lminx3u36e
  Connection: close
  
  csrfmiddlewaretoken=1234567812345678123456781234567812345678123456781234567812345678&amp;username=dev&amp;first_name=smellysocks&amp;last_name=&amp;email=&amp;is_active=on&amp;is_staff=on&amp;is_superuser=on&amp;last_login_0=2020-08-08&amp;last_login_1=09%3A19%3A32&amp;date_joined_0=2020-08-05&amp;date_joined_1=16%3A02%3A29&amp;initial-date_joined_0=2020-08-05&amp;initial-date_joined_1=16%3A02%3A29&amp;_save=Save
  </code></pre>
  <ol start="11">
  <li>Forward the request on to the django server</li>
  <li>You should see a message within Burp Suite saying &quot;The user was changed successfully.&quot;</li>
  <li>You can also validate within the admin portal that the user first name was updated successfully.</li>
  </ol>
  <p>The above steps demonstrate that Django is not validating the csrf token value.</p>
  <p>Currently, my settings.py contains</p>
  <pre><code># sets HttpOnly cookie
  SESSION_COOKIE_HTTPONLY = True
  # sets Secure true
  SESSION_COOKIE_SECURE = True
  # sets session timeout (currently at 15 minutes)
  SESSION_COOKIE_AGE = 15*60
  
  CSRF_COOKIE_SECURE = True
  X_FRAME_OPTIONS = 'DENY'
  SECURE_BROWSER_XSS_FILTER = True
  SECURE_CONTENT_TYPE_NOSNIFF = True
  CSRF_COOKIE_SAMESITE = 'Strict'
  </code></pre>
  <p>Any help will be greatly appreciated!</p>