Search code examples
djangodjango-rest-frameworktiming-attack

Prevent django send_mail timimg attack


I have different REST-API views where I either send a mail (if an account exists) or do not send a mail. For example, the user can input the email in the forgot-password form and a mail is sent if the account exists.

I am using from django.core.mail import send_mail to send the mail.

The problem is, that this takes some time, and so requests for valid emails are generally longer than requests for non-exiting emails. This allows an attacker to compare the request times to find out if an account exists or not.

Is there any way that I can call send_mail() without sending the mail? Or what would be the fix to make request times equally long for both cases?

Note: I could check how long send_mail() needs on average and wait this time if I do not send the mail. As the app runs on different servers with different configs, this can not be generally done in my case. I would rather not store the average execution time per server in a database to solve this.


Solution

  • It's a common practice to use celery for tasks that require some time to be finished. Celery will run a task in a separate thread and a user doesn't need to wait while it is finished. In your specific case what will happen if you use celery:

    1. You send a task send_mail to celery and immediately return a successful response to a user.
    2. Celery receives a task and runs it in a separate thread.

    In this way, the response time for both cases will be the same.