As of 2021, broken authentication is ranked #7 in the Open Web Application Security Project (OWASP) Top 10 list. Authentication system flaws can allow attackers to get access to user accounts and potentially compromise a whole system by utilizing an admin account.
In this post, we'll describe broken authentication. We'll also provide some examples and go through some of the strategies for making Django apps more secure. You should be able to apply what you learn to your Django applications.
Broken Authentication
Broken authentication refers to security breaches that develop as a result of how business applications authenticate users. One of the most commonly abused security-related components of a business system is its authentication systems.
In order to access additional information on most business apps, users must first authenticate their identities using their credentials. A session ID is issued to each logged-in user. This is a type of token that is used to track the activity of logged-in users, comparable to a temporary replacement for the user's original login credentials. Because session information is related to the logged-in user, it's critical to keep track of these session IDs to prevent attackers from impersonating the rightful owner of the session.
Examples
There are various ways in which attackers can gain access through compromised authentication systems.
Exploiting session management issues, such as failing to rotate session IDs after a successful login or failing to correctly invalidate session IDs upon logout
Attempting to brute force legitimate usernames or emails using known passwords
Allowing people to sign up for the site using passwords that are weak or popular, such as "123456"
Using weak credential recovery processes such as knowledge-based answers
Using weakly hashed passwords or plain text passwords
Prevention
Strict Password Policy
It's best to adopt a strict password policy with a minimum length of eight characters and a maximum length of sixty-four characters. Don't allow sequential passwords like "1234" or "asdf", the ever popular "password", or anything related to the organization or email address (if your business name is Stackhawk, for instance, the password should not include "stackhawk").
Using packages like Django-password-strength, you can enforce password checks in Django. Alternatively, you can utilize Django's default settings in the settings.py file, as seen below.
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {
'min_length': 11,
}
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
The UserAttributeSimilarityValidator makes sure that the user isn't using passwords that are similar to existing characteristics they have already provided in their user data, such as their name, email address, or role. As a result, an administrative user with the email address "admin@example.com" is unable to use passwords such as "admin", "admin123", "exampleAdmin", and so on.
MinimumLengthValidator in the above code snippet indicates that passwords must be at least eleven characters long. Hence, a user with the given email address "test@example.com" will be unable to sign up with the password "Gracey@me" because the password is only nine characters long.
CommonPasswordValidator prohibits users from using passwords that have been known to be hacked, such as "abcd12345".
NumericPasswordValidator restricts users from solely using numbers in their passwords, such as "0987654321".
In addition to maintaining strong password restrictions, how users log in and out of a business application is equally vital.
Session Management
It's crucial to control how the client or server keeps sessions. Using Django's built-in settings in settings.py, as illustrated below, is one way to manage how long session information lasts.
INSTALLED_APPS = [
...
'django.contrib.sessions',
...
]
MIDDLEWARE = [
...
'django.contrib.sessions.middleware.SessionMiddleware',
...
]
SESSION_COOKIE_AGE=1209600 # DEFAULT SESSION AGE OF 2 WEEKS
SESSION_COOKIE_SECURE=True
SESSION_EXPIRE_AT_BROWSER_CLOSE=True
Django supports settings parameters like SESSION_EXPIRE_AT_ BROWSER_CLOSE and SESSION_COOKIE_AGE to manage sessions. When the browser is closed, the former invalidates the session regardless of how old the session cookie is. The latter invalidates the session only when the session's cookie age is exceeded.
Because SESSION_EXPIRE_AT_BROWSER_CLOSE is set to True, the user may not only log out of the business application but also shut the browser without an attacker accessing the same session data kept in the browser, preventing a session hijacking.
Multifactor Authentication
In business applications, multifactor authentication (MFA) adds an extra layer of protection. Aside from using a username and password, you can utilize additional methods of identification.
There are three types of multifactor authentication:
What a user knows, such as their email address or password
What the user has, such as an SMS token
The user's identity, verified using a fingerprint, iris ID, or facial recognition
Django supports MFA via third-party packages, not as built-in Django packages. Two popular packages for MFA in Django are Django-mfa and Django-multifactor.
During the identification phase, you should avoid employing the same type of multifactor group more than once. If a user joins using their email and password, the second authentication method should be a token or a fingerprint. If the second element of authentication is a fingerprint, the third factor of authentication must be a token.
Vague Responses
It's common for people to forget their sign-up email or password. However, ensuring that any message to the user is vague is critical to prevent malicious users from abusing response loopholes. If, for example, a user tries to log in to a business application with the wrong password, it is typical to respond with a message saying, "The password is incorrect. Please try again." While this may be useful to a genuine user, it's a security hole that an attacker may take advantage of.
Now that the attacker is aware that the email address exists on the platform, he or she can attempt to brute force the account. So instead of providing specific responses during authentication, use vague responses. "Incorrect email or password," for example, would be a typical vague response if a user gets one or the other wrong. A potential attacker would therefore be unsure which is inaccurate.
Furthermore, rather than using alerts like "Email not registered," you might try using a less telling message like "Email sent" for users who try to recover lost passwords. You'll send emails if the email address exists in the application, but nothing will happen otherwise.
Identity Is Everything
In this post, we covered how attackers use session data and weak passwords to exploit authentication flaws. We also showed you how to protect yourself from these attackers by implementing stronger session management and password policies.
Poorly implemented authentication in applications introduces vulnerabilities for attacks. As the world continues to rely on the internet, weak authentication is pervasive, and protecting user identities is more critical than ever.
This post was written by Ifenna Okoye. Ifenna is a software developer with a particular interest in backend technologies including Python and Node.js.