Local file inclusion - Ruby

Local file inclusion - Ruby

Need

Prevention of unauthorized access to local files

Context

  • Requirement of Ruby 2.0 or higher for running the application
  • Usage of Ruby on Rails for building web applications

Description

Non compliant code

        def download
  file_path = params[:file_path]
  send_file file_path
end
        
        

In the code snippet above, we have a function download that is vulnerable to Local File Inclusion (LFI). This function is designed to download a file from the server to the client.

The file to be downloaded is specified by the file_path parameter, which is taken directly from the request parameters. This means that the client has control over what file is downloaded, and could potentially specify any file on the server.

The function uses the send_file method provided by Ruby on Rails to send the file to the client. This method does not perform any checks on the file path, and will happily send any file that the server has access to.

This means that an attacker could craft a request that includes a file path to a sensitive file on the server, such as /etc/passwd, and the server would send this file to the attacker. This is a classic example of a Local File Inclusion vulnerability.

Steps

  • Validate user input: Implement input validation to ensure that the file_path parameter is a valid and safe file path.
  • Sanitize user input: Use a sanitization function or library to remove any potentially malicious characters or sequences from the file_path parameter.
  • Restrict file access: Implement access controls to restrict the files that can be accessed through the download function. Only allow access to specific directories or files that are intended to be downloaded.
  • Use absolute file paths: Instead of using relative file paths, use absolute file paths to ensure that the file being accessed is located in the intended directory.
  • Implement file whitelisting: Maintain a whitelist of allowed file paths and validate that the requested file_path is present in the whitelist before allowing the download.
  • Implement file authorization: Check if the user has the necessary permissions to access the requested file before allowing the download.
  • Log and monitor file access: Implement logging and monitoring mechanisms to track and detect any suspicious or unauthorized file access attempts.

Compliant code

        # Define a whitelist of allowed file paths
ALLOWED_FILE_PATHS = ['/path/to/allowed/file1', '/path/to/allowed/file2']

def download
  file_path = params[:file_path]

  # Validate and sanitize the file_path parameter
  file_path = sanitize_file_path(file_path)

  # Check if the file_path is in the whitelist
  unless ALLOWED_FILE_PATHS.include?(file_path)
    render plain: "Access denied", status: :forbidden
    return
  end

  # Check if the user has the necessary permissions to access the file
  unless current_user.can_access?(file_path)
    render plain: "Access denied", status: :forbidden
    return
  end

  # Send the file
  send_file file_path
end

private

def sanitize_file_path(file_path)
  # Remove any potentially malicious characters or sequences
  file_path.gsub(/[^0-9A-Za-z.\\-\\/]/, '')
end
        
        

The updated code includes several measures to prevent local file inclusion vulnerabilities:

1. Input Validation and Sanitization: The sanitize_file_path method is used to remove any potentially malicious characters or sequences from the file_path parameter. This helps to ensure that the file path is safe and valid.

2. File Path Whitelisting: A whitelist of allowed file paths is defined and the file_path parameter is checked against this whitelist. If the file_path is not in the whitelist, the request is denied.

3. File Access Authorization: The current_user.can_access? method is used to check if the user has the necessary permissions to access the requested file. If the user does not have the necessary permissions, the request is denied.

These measures help to ensure that only valid, safe, and authorized file paths can be accessed through the download function. This prevents attackers from exploiting the function to read or execute files located on the server through relative path manipulation.

References