Insecure deserialization - Ruby

Insecure deserialization - Ruby

Need

Secure deserialization process

Context

  • Usage of Ruby 2.7 as a programming language for development
  • Usage of Rails framework for building web applications
  • Usage of ActiveRecord for Object-Relational Mapping (ORM) in database operations

Description

Non compliant code

        class UsersController < ApplicationController
  def show
    @user = User.deserialize(params[:user])
  end
end

class User < ApplicationRecord
  def self.deserialize(user_hash)
    Marshal.load(user_hash)
  end
end
        
        

In the above code, the show method in UsersController is using the deserialize method from User model to deserialize the user object sent in the request parameters.

The deserialize method uses Marshal.load which is a built-in Ruby method for deserialization. The problem with this method is that it will deserialize any object that is passed to it without checking its validity or type.

This can lead to a number of security issues such as arbitrary code execution if an attacker is able to pass in a malicious object to be deserialized. This is because the Marshal.load method can deserialize any Ruby object, including those that can execute code.

In addition, since there is no type checking, an attacker could potentially pass in an object of a different type, causing unexpected behavior or errors in the application.

This is a classic example of the Insecure Deserialization vulnerability where user-supplied input is deserialized without any type of input validation or type checking.

Steps

  • Implement input validation to ensure that the deserialized object is of the expected type.
  • Use a safe deserialization library or framework that provides built-in protection against insecure deserialization.
  • Avoid using the Marshal.load method for deserialization as it can execute arbitrary code. Instead, consider using a safer alternative like JSON deserialization.
  • If using JSON deserialization, ensure that the deserialized data is properly validated and sanitized before use.
  • Consider implementing a whitelist approach where only specific classes or types are allowed to be deserialized.
  • Regularly update and patch the deserialization library or framework to benefit from the latest security enhancements.
  • Educate developers about the risks of insecure deserialization and provide guidelines on secure deserialization practices.

Compliant code

        require 'json'

class UsersController < ApplicationController
  def show
    @user = User.deserialize(params[:user])
  end
end

class User < ApplicationRecord
  def self.deserialize(user_json)
    user_hash = JSON.parse(user_json)
    validate_user_hash(user_hash)
    new(user_hash)
  end

  private

  def self.validate_user_hash(user_hash)
    required_keys = ['id', 'name', 'email'] # Add all required keys here
    missing_keys = required_keys - user_hash.keys
    raise "Missing keys: #{missing_keys.join(', ')}" unless missing_keys.empty?
  end
end
        
        

The original code was vulnerable to insecure deserialization attacks because it used the Marshal.load method to deserialize user objects without validating their content. This method can execute arbitrary code, which makes it a potential security risk.

The fixed code replaces Marshal.load with JSON.parse, a safer alternative for deserialization. It also adds a validate_user_hash method to ensure that the deserialized object includes all required keys. This method raises an exception if any required keys are missing.

This solution implements input validation to ensure that the deserialized object is of the expected type. It also uses a safe deserialization method that provides built-in protection against insecure deserialization.

Remember to always validate and sanitize deserialized data before use. Consider implementing a whitelist approach where only specific classes or types are allowed to be deserialized. Regularly update and patch the deserialization library or framework to benefit from the latest security enhancements.

Educate developers about the risks of insecure deserialization and provide guidelines on secure deserialization practices.

References