Skip to main content

Hidden fields manipulation

Need

Prevention of unauthorized manipulation of hidden fields

Context

  • Usage of Python 3 for developing applications and scripts
  • Usage of Django for building web applications

Description

Non compliant code

from django import forms

class UserProfileForm(forms.Form):
username = forms.CharField()
secret_key = forms.CharField(widget=forms.HiddenInput())

def user_profile(request):
if request.method == 'POST':
form = UserProfileForm(request.POST)
if form.is_valid():
user = User.objects.get(username=form.cleaned_data['username'])
user.secret_key = form.cleaned_data['secret_key']
user.save()
else:
form = UserProfileForm()
return render(request, 'edit_profile.html', {'form': form})

The above code is a Django form that is used to edit a user profile. The form contains a hidden field secret_key which is not visible to the regular user on the front end. However, this hidden field can be manipulated by a malicious user to change the value of secret_key for a particular user.

When the form is submitted, the user_profile view function gets the POST data, validates the form and if it's valid, it gets the user object and updates the secret_key with the value from the form. This means that if a malicious user manipulates the secret_key in the form data, it will be saved in the database, potentially causing undesired behaviors in the application, such as unauthorized access or data corruption.

This vulnerability, known as Hidden Field Manipulation, is a serious security risk as it allows an attacker to modify hidden form data before it's sent to the server, potentially leading to unauthorized access or modification of sensitive data.

Steps

  • Remove the secret_key field from the form. It should not be editable from the client side.
  • If the secret_key needs to be updated, create a separate function or method that handles this process securely on the server side.
  • Ensure that only authorized users can update sensitive information. Implement proper authentication and authorization checks.
  • Consider using Django's built-in User model for handling user data, which includes many security features.
  • Always validate and sanitize user input to prevent other types of attacks.

Compliant code

from django import forms
from django.contrib.auth.decorators import login_required

class UserProfileForm(forms.Form):
username = forms.CharField()

@login_required
def user_profile(request):
if request.method == 'POST':
form = UserProfileForm(request.POST)
if form.is_valid():
user = User.objects.get(username=form.cleaned_data['username'])
if user == request.user:
user.save()
else:
return HttpResponseForbidden("You are not allowed to edit this user.")
else:
form = UserProfileForm()
return render(request, 'edit_profile.html', {'form': form})

def update_secret_key(user):
# This is a server-side function to update the secret_key
# Add your own logic here
pass

The updated code removes the secret_key field from the UserProfileForm. This field should not be editable from the client side as it can lead to security vulnerabilities.

The user_profile view now includes the @login_required decorator, which ensures that only authenticated users can access this view.

Inside the user_profile view, we check if the user trying to update the profile is the same as the logged-in user. If not, a HttpResponseForbidden is returned, preventing unauthorized users from updating other users' profiles.

A new function update_secret_key is added. This function should contain the logic to update the secret_key securely on the server side. This function should only be called from trusted server-side code, not from client-side code.

Remember to always validate and sanitize user input to prevent other types of attacks. Django's form system provides a lot of built-in validation, but you should always add your own specific checks as needed.

References