Skip to main content

Insecure object reference - User deletion

Need

Secure user deletion process and session management

Context

  • Usage of Ruby 2.7.2 as the programming language for development
  • Usage of Rails framework for building web applications

Description

Non compliant code

class UsersController < ApplicationController
def destroy
@user = User.find(params[:id])
@user.destroy
redirect_to root_url
end
end

The above code is a Ruby on Rails controller for handling user related actions. The destroy method is used to delete a user from the database. It first finds the user by their id, which is passed in the request parameters, and then calls the destroy method on the user object.

This code is vulnerable to insecure direct object reference (IDOR) because it does not check if the current user has the right to delete the specified user. Any authenticated user can delete any other user just by knowing their id. This can lead to unauthorized deletion of users, leaving the system inoperative.

Moreover, after the user is deleted, the session is not invalidated. This allows the deleted user to continue browsing the application until their session expires naturally. This could lead to further unauthorized actions being performed by the deleted user.

To fix this vulnerability, the application should check if the current user has the right to delete the specified user. Additionally, the session should be invalidated immediately after the user is deleted.

Steps

  • Implement authentication and authorization mechanisms to ensure that only authorized users can delete other users.
  • Validate the user's session before allowing the deletion of a user.
  • Consider implementing a confirmation step before deleting a user to prevent accidental deletions.
  • Update the session management to invalidate the session of a deleted user.

Compliant code

class UsersController < ApplicationController
before_action :set_user, only: [:destroy]
before_action :authenticate_user!
before_action :authorize_user, only: [:destroy]

def destroy
if @user.destroy
flash[:notice] = "User deleted successfully."
sign_out @user
else
flash[:alert] = "User deletion failed."
end
redirect_to root_url
end

private

def set_user
@user = User.find(params[:id])
end

def authorize_user
unless current_user.admin?
flash[:alert] = "You are not authorized to perform this action."
redirect_to root_url
end
end
end

The updated code includes several security measures to prevent insecure object reference vulnerabilities.

  1. before_action :set_user, only: [:destroy] - This line sets the user to be deleted before the destroy action is performed. This ensures that the user exists and can be deleted.

  2. before_action :authenticate_user! - This line ensures that a user is authenticated before they can perform any action. This prevents unauthorized users from deleting users.

  3. before_action :authorize_user, only: [:destroy] - This line ensures that the current user is authorized to delete users. In this case, only admin users are allowed to delete users. This prevents regular users from deleting other users.

  4. if @user.destroy - This line attempts to delete the user. If the deletion is successful, the user is signed out and a success message is displayed. If the deletion fails, an error message is displayed.

  5. sign_out @user - This line signs out the deleted user. This ensures that the user's session is invalidated upon deletion, preventing the user from continuing to browse the application.

  6. def authorize_user - This method checks if the current user is an admin. If not, the user is redirected to the root URL with an error message. This prevents unauthorized users from deleting users.

By implementing these measures, the application is protected against insecure object reference vulnerabilities related to user deletion.

References