CSC/ECE 517 Fall 2009/wiki1b 8 rubysecurity
This article explores how the Ruby on Rails framework handles common dangerous programming errors committed in a web application and how it compares with other web application frameworks in terms of handling of these errors.
Introduction
Almost all real world data and transactions are now available as web services which are created in some web application framework. As the number of such services increase, so do the possibility that attackers might try to exploit new loopholes in the application that is developed. The consequences of such attacks are far reaching and destructive in terms of business and security perspective. The danger is so grave that during January this year that experts from more than 30 US and international cyber security organizations jointly released the consensus list of the 25 most dangerous programming errors that lead to security bugs and that enable cyber espionage and cyber crime. Ruby on Rails [citation needed], a MVC based application framework architecture, is used for designing web applications using Ruby language, comes with some features which can handle some of the common programming errors cited. In the next section we will see how each of these errors are handled according to their classification and in the third section we will see how Rails compares with other application framework in handling these errors.
Ruby on Rails's handling of the common programming errors
Synchronous to the classifiation of programming errors as cited in [citation], this section has three sub divisions or categories.
Insecure communication between components
This section contains the programming errors such as Improper Input validation, improper encoding of output,SQL injection etc.,
Improper Input Validation
Authorization is the process of checking whether a user has access to do what he wants to do. This automatically brings the issue of handling roles in the web application. If roles are not properly defined and implemented, an attacker can login as a genuine user by registering with your application and can perform unwanted reads / write which can lead to loss of sensitive information.
Validation in Rails is very simple and short. We have to use the function validates. Validation can be done with ActiveRecord [citation] which is the ORM layer supplied with rails that relieves the programmer of dealing with the underlying databse and is the solid model foundation of Rails MVC architecture. ActiveRecord comes with a number of helper classes for validation. Using these helper classes, to check that a variable in the model is not null, we use validates_presence_of: followed by the field names that need to be validated. To check the length of a variable we use validates.lengthof: function. The below code uses the validation helper methods of ActiveRecords which checks if the name of the student is not null or no symbols are present. It also checks whether the user with the same name already exists in the database as a new user is being created. The rest of the code is self-explanatory.
sample code for Input validation
class Student < ActiveRecord::Base validates_presence_of :name, :sex, :age, :weight validates_format_of :name, :with => /^\w+$/, :message => "is missing or invalid" validates_uniqueness_of :name, :on => :create, :message => "is already presnt" validates_inclusion_of :sex, :in => %w(M F), :message => 'must be M or F' validates_inclusion_of :age, :within => 18..40 validates_length_of :name, :allow_blank => false, :allow_nil => false, :maximum => 30 end
Without the validates helper method, the check for the format of the name can be done as
class Student < ActiveRecord:Base def validate unless name && name=~/^\w+$/ errors.add(:name, "is missing or invalid") end end end
[citation for : http://biodegradablegeek.com/2008/02/introduction-to-validations-validation-error-handling-in-rails/]
Improper Encoding or Escaping of Output
According to [citation needed : http://cwe.mitre.org/top25/#CWE-116], improper output encoding is the root for all injection basd attacks. The attacker can modify the output intended for other components in such a way that he /she can cause harm to the application, if the control information and metadata carried in the output is not properly seperated from the real data.
Failure to Preserve SQL Query Structure (aka 'SQL Injection')
If not much attention is paid as to how SQL queries are handled in the application code, attackers can modify / supply appropriate parameters so that they can gain access to sensitive information in the database such as Account database, which is not good from the security viewpoint. For example in Ruby, the following function poses a serious security threat if the value for the conditions method comes from an external source. The attacker can pass a SQL metacharacter as the input to breach his/her privilege.[citataion:book]
Users.find(:all, :conditions => "name like '%#{session[:user].name}'")
Rails recommends that in order to avoid SQL injections, never to substitute anything into an SQL statement using the ruby's #mechanism. Rails comes with a facility called blind variable for using in place of #. It is nothing but having a placeholder in place of #. If more than one placeholder is present in the query, ActiveRecord uses the corresponding input from the input array to substitute in the placeholder. The function from the above example can be replaced by [citataion:book]
Users.find(:all, :conditions => "name like '%?%'")
Failure to Preserve Web Page Structure (aka 'Cross-site Scripting')
Attackers are known to write simple javascript code in to an application's page using session cookies so that whenever a cookie destined for another legitimate user of the application is sent to that user, the attacker can redirect the cookie to be sent his/her computer. In this way an attacker can steal a legitimate users' identity. To prevent this Rails recommends that the application we create never blindly display any data coming from an external source to be blindly displayed on the application's page. It recommends the application to convert such HTML codes into plain texts berfore displaying.[citataion:book] Rails also comes with a helper method h(string) which is an alias for HTML escape, which performs the above mentioned escaping in Rails views. Rails also recommends using this helper method for any variable that is rendered in the view. The below code snippet shows how to render a user comment on to the application's view.[citataion:book]
Failure to Preserve OS Command Structure (aka 'OS Command Injection')
An attacker will try and execute execute malicious code when an appliaction uses data from the user as a parameter to execute system level commands resulting in breach of security. This is because an attacker can execute another command through the input to a first command by appending a semicolon(;) or a vertical bar (|). Ruby's exec(command), syscall(command), system(command) and \command are all vulnerable to such attacks. In order to avoid this Rails recommends programmers to use the system(command, parameters) method which passes command line parameters safely. For example, [citation : http://guides.rubyonrails.org/security.html#command-line-injection]
system("/bin/echo","hello; rm *") # prints "hello; rm *" and does not delete files
Cleartext Transmission of Sensitive Information
Cross-Site Request Forgery (CSRF)
Race Condition
Error Message Information Leak
CATEGORY: Porous Defenses
This category contains errors such as improper access control, Use of a Broken or Risky Cryptographic Algorithm , Hard-Coded Password, Use of Insufficiently Random Values and three more errors which will be covered in this section.