Server side template injection - Ruby

Server side template injection - Ruby

Need

Prevention of server-side template injection attacks

Context

  • Requirement of Ruby version 2.5.0 or higher for running the application
  • Usage of Rails framework for building web applications

Description

Non compliant code

        class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
    render params[:template]
  end
end
        
        

The above code is part of a Ruby on Rails application. It is a simple UsersController with a show action. This action retrieves a user record from the database based on the id provided in the request parameters.

However, the vulnerability lies in the render method call. Instead of rendering a static template, it renders a template based on the :template parameter from the request.

This means that an attacker could potentially inject a malicious template name into the request parameters, which could lead to a Server Side Template Injection (SSTI) attack.

For example, an attacker could create a request with a :template parameter that points to a template file which includes a Ruby code snippet that performs unwanted actions, such as deleting all users or revealing sensitive information.

This vulnerability is a serious security risk as it could lead to remote code execution (RCE) on the server side, data leakage, or even total system compromise.

Steps

  • Sanitize user input: Validate and sanitize any user input that is used to construct the template name. This can be done by using a whitelist approach, where only allowed template names are accepted.
  • Implement strict template rendering: Instead of directly rendering the template specified by the user, restrict the allowed templates to a predefined list. This can be achieved by using a switch statement or a mapping of allowed templates.
  • Use a safe template engine: If possible, switch to a template engine that automatically escapes user input by default, such as ERB in Ruby on Rails. This helps prevent template injection vulnerabilities.
  • Implement input validation: Validate the user input for the template name to ensure it matches the expected format. This can include checking for valid characters, length restrictions, or specific patterns.
  • Implement access controls: Ensure that only authorized users have access to the templates. This can be done by implementing proper authentication and authorization mechanisms.
  • Regularly update dependencies: Keep the Ruby on Rails framework and any used template engines up to date to benefit from security patches and fixes.
  • Perform security testing: Regularly conduct security testing, including vulnerability scanning and penetration testing, to identify and address any potential vulnerabilities in the application.

Compliant code

        class UsersController < ApplicationController
  TEMPLATES = ['template1', 'template2', 'template3'] # Add your valid templates here

  def show
    @user = User.find(params[:id])
    template = params[:template]

    if TEMPLATES.include?(template)
      render template
    else
      render 'error' # Render an error template or redirect as per your application's error handling
    end
  end
end
        
        

The updated code now includes a whitelist of valid templates ( TEMPLATES = ['template1', 'template2', 'template3']). This list should be populated with the names of all valid templates that the application uses.

When a request is made to the show action, the template parameter is checked against the whitelist. If the template name is included in the whitelist, the template is rendered. If not, an error template is rendered instead. This could also be a redirect to an error page or another form of error handling, depending on the application's requirements.

This approach ensures that only valid, predefined templates can be rendered, preventing an attacker from injecting malicious templates. It's a form of input validation that effectively mitigates the server-side template injection vulnerability.

Remember to keep your Ruby on Rails framework and any used template engines up to date to benefit from security patches and fixes. Also, regularly conduct security testing, including vulnerability scanning and penetration testing, to identify and address any potential vulnerabilities in your application.

References