Ruby on Rails Remote Code Execution Vulnerability Analysis in CVE-2016-0752)
If your application uses a dynamic rendering path (such as render params [: id]), unfortunately, this application currently has a remote code execution vulnerability caused by local file inclusion, please quickly update your Rails to the latest version or refactor your controller.
In this article, we will demonstrate how attackers can execute remote commands in some cases due to defects in the Ruby on Rails framework.
The Rails controller is designed to implicitly render the View File mode based on the called method. For example, if the showframes in the execution controller are unspecified, the frame automatically uses the show.html. erb file for page rendering.
However, in most cases, developers determine the different content to be presented based on the file format (such as text, JSON, XML, or a completely different view file, the View File mentioned here refers to a template language file similar to ERB and HTML.
There are many ways to influence the View content. Here we only focus on the render method. The Rails operation documentation lists several methods to call the render method, including explicitly specifying files in a path through the file: option.
If you have read the solution documentation, (http://guides.rubyonrails.org/layouts_and_rendering.html), but are not sure you need such a feature, then I tell you that you are not the only one.
Let's take a look at the code section:
Def show
Render params [: template]
End
At first glance, the code is very simple. You may guess that the function of the method in this controller is to specify the value of the parameter "template" as the rendering template. It is unclear where Rails will find the specified template. Is it in the view directory, the application root directory, or other places? Does it need to specify a Template Name, a specific file name, or a complete file path? There are many other problems that can be solved only by viewing the implementation details.
Description
The dynamic rendering mechanism is a typical example of trying to implement multiple functions in the same function. This is the problem.
Assuming that the expected behavior of the rendering mechanism is rendering the app/views/user/# {params [: template]} file-This seems a reasonable idea. If we assign a dashboard value to the template, the application will try to load the app/views/user/dashboard.w.ext;template.ext is an extension allowed by ruby(.html?.haml=.html. erb, etc ).
Assume that the next user assigns the ../admin/dashboard to the parameter template. What are the expected results? This seems difficult to determine, but when we do this, we can see that the application throws an error where the template cannot be found.
By analyzing the preceding error, you can find that the application tries to find the view used to present the content in multiple paths, including RAILS_ROOT/app/views, RAILS_ROOT, and the file system root directory. This is a bit confusing. Why do we need to find the template file from the root directory of the system?
Hackers instinctively urged us to assign the/etc/passwd value to the parameter template and then confirm that we can read the content of the passwd file. At this moment, my friends and I were stunned.
If we can read the content of the passwd file, we can read the source code of the application and the content of the configuration file, such as the config/initializers/secrettoken. rb file.
Don't forget what caused this vulnerability, because you chose to dynamically set the template path.
Def show
Render params [: template]
End
Such a simple script is enough for attackers to read our source code and configuration file values, but unfortunately this is not the worst part.
As Jeff Jarmoc's paper "The Anatomy of a Rails Vulnerability-CVE-2014-0130: From Directory Traversal to Shell," (http://matasano.com/research/AnatomyOfRailsVuln-CVE-2014-0130.pdf) says, we can exploit this vulnerability to obtain the shell of the Rails application. Jeff's paper mentions a similar directory traversal caused by rendering mechanisms, or, more specifically, some versions of Rails can cause local file inclusion. In this article, we are concerned about the problems caused by explicit rendering, which is a vulnerability caused by developers.
Before going into the details, I want to point out that the vulnerability we want to focus on is file inclusion rather than directory traversal. The difference is that the files we load and execute (ERB) are different. Generally, the Directory Traversal Vulnerability returns an unexecutable content, such as a CSV file. Therefore, in essence, we can not only read the application's source code and other system-readable files, but also execute Ruby code. Being able to execute Ruby Code also means that we can execute system-level commands as servers.
From file inclusion to code execution, we need to use a log file tainting method ). Rails records the information of each request in a log file (such as development. log), including parameters. The content stored in the log file is in plaintext, so Ruby code can be incorporated. Attackers can add valid Ruby code to the parameters requested by the server to record these crafted Ruby code to the log file.
In the following example, we will initiate a valid request to the Web server and add the URL encoded value to the constructed parameter :.
By viewing the log, we can see that the value of the request parameter has been decoded into a key-Value Pair by the URL. This is a legal Ruby code that will be executed if called by the application.
We can exploit the File Inclusion Vulnerability to include the log file and then execute the Ruby code in it.
After the log contains the returned content, we can see the submitted parameter key-value pairs, and then our previous values are replaced with the values returned after ls execution, from this we can see that we can execute any system-level command with the permissions of the current server.
Solution
In fact, the simplest way to reduce the harm of this vulnerability is to patch the corresponding Ruby version.
In addition, if you have not patched the file, you can consider not to render any unacceptable files. You can create a key-value pair that only allows rendering of file names, make sure that the parameters submitted by the user are implemented in the allowed key-value pairs. Of course, this method needs to be configured in every instance of the application.
Def show
Template = params [: id]
Valid_templates = {
"Dashboard" => "dashboard ",
"Profile" => "profile ",
"Deals" => "deals"
}
If valid_templates.include? (Template)
Render "# {valid_templates [template]}"
Else
# Throw exception or 404
End
End
Another similar solution is to verify that the given file is in the specified directory.
Def show template = params [: id] d = Dir ["myfolder/*. erb"] if d. include? ("Myfolder/# {template}. erb") render "myfolder/# {template}" else # throw exception or 404 endend
Scan the application with Brakeman (http://brakemanscanner.org/), a static Rails scan tool that reports instances rendered through dynamic paths, this allows you to find out which controllers in your application are affected by this vulnerability.
To sum up
The rendering mechanism of Rails is a mysterious function. If you have not thoroughly analyzed its implementation details, it is difficult for you to understand this function or to find available vulnerabilities, unfortunately, the official documentation does not help much.
Similar to CVE-2014-0130, rendering with dynamic paths may cause directory traversal and code execution. I have encountered such a developer vulnerability many times during the evaluation and have seen it in many open Rails projects.
If you have not read the report of Jeff Jarmoc, I suggest you take a look. He has a deep research into vulnerabilities in CVE-2014-0130 and is good at risk assessment. Many of the content in this article is very similar to what he mentioned. After all, these vulnerabilities are very similar.
Finally, I have written a Metasploit module poc that can be used to detect and exploit this vulnerability in the application, you can find this module here: https://gist.github.com/forced-request/5158759a6418e6376afb