Stronger password change authentication
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.shortcuts import render, redirect
@login_required
def change_password(request):
if request.method == 'POST':
new_password = request.POST.get('new_password')
user = User.objects.get(username=request.user.username)
user.set_password(new_password)
user.save()
return redirect('home')
else:
return render(request, 'change_password.html')
The above code represents a Django view function
change_password
that allows logged in users to change their password. The function checks if the request method is POST and then retrieves the new password from the request data. It then retrieves the user object from the database using the username from the current user session. The password for the user is then set to the new password and the user object is saved, effectively changing the password.
The vulnerability here is that this function does not verify the identity of the user before changing the password. It only checks if the user is logged in, but does not ask for the current password or any other form of identity verification. This means that if a user's session is hijacked or if they leave their device unattended and logged in, another person could change the user's password without their knowledge.
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.contrib.auth.hashers import check_password
from django.shortcuts import render, redirect
@login_required
def change_password(request):
if request.method == 'POST':
current_password = request.POST.get('current_password')
new_password = request.POST.get('new_password')
user = User.objects.get(username=request.user.username)
if check_password(current_password, user.password):
user.set_password(new_password)
user.save()
return redirect('home')
else:
return render(request, 'change_password.html', {'error': 'Incorrect current password'})
else:
return render(request, 'change_password.html')
The updated code now includes a check for the current password before allowing the user to change their password.
In the POST method, we now retrieve the current password from the form data using
request.POST.get('current_password')
.
We then use Django's built-in
check_password
function to verify if the current password entered by the user matches the one stored in the database. This function takes two arguments: the plain-text password entered by the user and the hashed password stored in the database. It returns
True
if the passwords match and
False
otherwise.
If the passwords match, we allow the user to set a new password and save the changes. If they don't match, we return an error message to the user and render the password change form again.
This update ensures that the user's identity is verified before allowing a password change, thus fixing the vulnerability.
For additional security, consider implementing two-factor authentication or security questions.