Skip to content

Cross-site Request Forgery Demonstration using Vulnerable Django Backend

License

Notifications You must be signed in to change notification settings

andreasschmitz/csrf-exploit-demo

Repository files navigation

CSRF Vulnerable Application

This project contains a Django web-application with multiple Cross-site Request Forgery (CSRF) vulnerabilities and utility scripts to exploit them. The goal of this project is to educate people about Cross-site Request Forgery.

This project was created for the DjangoCon EU 2022 talk Everything you didn't want to know about Cross-site Request Forgery (CSRF) in Django. You can find my blog post with furter information about the talk and a link to the recording here: My DjangoCon Europe 2022 Talk About Cross-site Request Forgery.

Disclaimer: Please don't use this code for any production system. It contains a lot of vulnerable pieces. It is configured this way for educational purposes.

Setup & Requirements

This project was tested using Python 3.10.6. It should work with all Python versions supported by Django 4.1. I suggest to use pyenv to install and maintain Python versions. The backend resides in the vulnerable-backend directory. The dependencies can be installed using poetry or the attached requirements.txt file (pip install -r requirements.txt).

The db.sqlite3 file and media folder were added to this repository to offer a quick start.

The default credentials are:

  • alice: csrf1234
  • mallory: csrf1234
  • admin: csrf1234 (If you need to log in to the Admin http://localhost:8000/admin)

Try the Attack

  • Start the vulnerable backend server (vulnerable-backend directory) python manage.py runserver 8000
  • Start mallory's attack script claim-best-sleeping-place.py.
  • Start mallory's attack / ad server cd attack-stage; python -m http.server --bind 0.0.0.0 9000
  • Log in as alice http://localhost:8000 (credentials above)
  • With the same browser you just logged in open http://localhost:9000 and click on one of the "Buy Now" buttons to run the exploit. Check out the index.html file for more exploits and notes on how to run the exploit on page load.
  • Reset the attack by executing python manage.py reset_stage (inside the vulnerable-backend directory)

Trying out more realistic scenario

If you wish to try this out cross-site, e.g. by setting configuring your /etc/hosts, you need to also disable SameSite protection for the session cookie by setting SESSION_COOKIE_SAMESITE = 'None'. However, most modern browsers will require you to also set the secure attribute SESSION_COOKIE_SECURE=True, thus making the local setup way more complicated, because a HTTPS connection is required for this to work. My advice would be to not set the secure flag and either test this with an old browser or to disable (some of) the protections of one of your browsers while testing.

For me, the following worked

  • In Firefox 102 for macOS
    • set network.cookie.sameSite.noneRequiresSecure to false (about:config)
    • about:preferences#privacy > Enhanced Tracking Protection > Custom (disable cookie checkbox)
  • In the backend set SESSION_COOKIE_SAMESITE = 'None'.

Don't forget to undo the settings above after testing.

HTTP Basic Authentication

To try out the attacks using HTTP Basic Authentication instead of session cookies, you need to update vulnerable-backend/vulnerable_backend/settings.py. Just comment out the HttpBasicAuthenticationMiddleware string in the MIDDLEWARE variable. Afterwards HTTP Basic Authentication is required. Please do not use this middleware on production systems, it is just a quick hack to demonstrate that CSRF also works with HTTP Basic Authentication.

Frequently Asked Questions (FAQ)

Why does CSRF work?

In my DjangoCon talk Everything you didn't want to know about Cross-site Request Forgery (CSRF) in Django I explain CSRF and Prevention mechanisms in detail.

Images Attributions