CSC/ECE 517 Fall 2009/wiki1a 10 wolf27-Manhattan

From Expertiza_Wiki
Revision as of 04:47, 12 September 2009 by Bsreera (talk | contribs) (→‎Introduction)
Jump to navigation Jump to search

Ruby and Java from a Security Perspective
Students: wolf27 and Manhattan


Introduction

It is widely held that the three “pillars” of a secure system are confidentiality, availability, and integrity. That is, is a users data safe from unauthorized viewing/disclosure; is the users data available when they want it; and is the data the same as what they expected. There are many techniques, algorithms, and methods available to ensure these three pillars. The language used to develop the software on a secure system can play a major role in how effective in how algorithms, etc. help protect the confidentiality, availability, and integrity of secure data. This article compares two popular languages, Ruby and Java with respect to some of features of each language that aid in developing a secure software system.


In Java, Security can be considered in three contexts:
1) Virtual Machine Security
2) Application Security
3) Network Security

Some of the key features regarding the above security issues are discussed in this article.

Ruby

“Safe Levels” in Ruby
Arguable one of Ruby’s features with respect to security is its “Safe Levels”. Ruby implements five levels of data checking to help prevent what its calls “tainted” variables from being used in other parts of the code where the system could be exploited.

All objects in Ruby are marked as “tainted” if they are derived from some external source. For example, an object is tainted if it read using ‘gets’, read from a file, is an environment variable, etc. Each Ruby object contains a method named, ‘tainted?’ as well as methods named ‘taint’ and ‘untaint’.

The ‘tainted?’ method is used to return a boolean value to indicate if the variable is tainted or not. Likewise, the ‘taint’ method is used to taint an untainted object and ‘untaint’ is used to remove a tainted label from an object. The code below shows a simple example of a String object becoming tainted.


#Tainted vs. Untainted
>> my_string = String.new             # A new string is created
=> ""
>> my_string.tainted?	              # The string is not tainted; there has been no external influence
=> false
>> my_string = "Hello"	              # Still no external influence
=> "Hello"
>> my_string.tainted?
=> false
>> my_string = my_string + gets       #Since part of the string now came from the console, it is tainted
World!
=> "Hello World!\n"
>> my_string.tainted?
=> true


To help manage tainted and untainted objects, Ruby define a built in constant named $SAFE that allows the user to define what “safe level”. The $SAFE variable is simply set at the beginning of the program in the way any other variable would be. For example,

$SAFE = 3

sets Ruby’s “safe level” to 3.

Each safe level allows (or disallows) certain actions, primarily based on whether an object is tainted or untainted. There are a few other operations that are also disallowed by Ruby at the various safe levels. Note that Ruby’s default safe level is 0, which means there all operates are allowed regardless of the the tainted status of the object. The books “Programming Ruby” [1] provides an excellent table to use as reference for the actives allowed and disallows at each safe level. Below are some highlight of each safe level.

$SAFE = 0
   Default “Safe Level”
   No additional security features
   All operations allowed on all untainted and tainted variables
$SAFE >= 1
   Calling the ‘glob’ or ‘eval’ methods on tainted strings is disallowed.
   Loading a file using a string that is tainted is disallowed.
   Executing system commands using a tainted string is disallowed.
$SAFE >= 2
   Loading a file from a source that is writable by ‘world’ is disallowed.
$SAFE >= 3
   All object created are tainted and no object may not be untainted using the untaint method.
$SAFE >= 4
   Essentially creates a Sandbox (an isolated, safe, place to run untrused code)
   Writing to files is disallowed
   Modifying global variable is disallowed.


Ruby’s Unbounded Polymorphism (a.k.a. Duck Typing) and Security
Ruby’s unbounded polymorphism functionally is arguably very powerful. However this power functionally could also create a potential problem with code developed. Since Ruby is a dynamically typed language, it is not possible to check and ensure that objects being used are of the expected type. If that object looks like another object, it can be treated as that object.

If not managed properly, an adversary or malicious piece of code could be executed unintentionally because of Ruby’s unbounded polymorphism. Consider the code below.

Class Good_code
     def good_method
          ... # some good code
     end
def another_good_method ... # some more good code end end

Class Bad_code def good_method ... #some BAD code, that looks good end
def another_good_method ... #some more bad code end end

def my_method(good_code) good_code.good_method good_code.another_good_method end
my_method(Bad_code.new)

In the example above, the malicious code will run, even though the developer of my_method thought and intended to only run code from the ‘good_code’ object. The developer must take greater caution when implementing code that takes another objects as to unintentionally execute a different object.

Automatic Bounds Checking
Ruby automatically checks bounds of data structures such as arrays. Bounds checking is very important to creating a secure system. If a user, intentionally or unintentionally, is able cause code to access an array index outside of the array, the system may crash, other data in memory may be overwritten, or unexpected (possibly private) data may be returned.

Cryptographic Libraries
The ability to perform basic cryptographic functions is necessary to help ensure the confidentially of data stored on a system (thought encryption) and the integrity of data (by cryptographic signature/hash). Ruby provides, built in, only a very limited set of cryptographic functionally. One such function is the String classes crypt method.

There are several open source library for performing cryptographic functions on objects available for Ruby such as crypt [2]. The crypt library provides access to such encryption algorithms AES, Blowfish, and IDEA.

Survey of Current and Past Publish Security Vulnerabilities
The official Ruby site [3] contains a security section that list a number of current and past security vulnerabilities found.


Java Security Features

Java language security constructs
Within a Java program, every entity −− that is, every object reference and every primitive data element −− has an access level associated with it.
Private : The entity can only be accessed by code that is contained within the class that defines the entity.
Protected : The entity can only be accessed by code that is contained within the class that defines the entity, by classes within the same package as the defining class, or by a subclass of the defining class.
Public : The entity can be accessed by code in any class.


Programs are not allowed to access arbitrary memory locations
For example, casting between an int and an Object is strictly illegal in Java.


Variables may not be used before they are initialized
If a program were able to read the value of an uninitialized variable, the effect would be the same as if it were able to read random memory locations. A Java class wishing to exploit this defect might then declare a huge uninitialized section of variables in an attempt to snoop the memory contents of the user's machine. To prevent this type of attack, all local variables in Java must be initialized before they are used, and all instance variables in Java are automatically initialized to a default value.


Objects cannot be arbitrarily cast into other objects
Consider the below example.

public class CreditCard {
private String acctNo;
} public class CreditCardSnoop {
public String acctNo;
}

Then the following code will not be allowed execute:

CreditCard cc = Wallet.getCreditCard( );
CreditCardSnoop snoop = (CreditCardSnoop) cc;
System.out.println("Ha! Your account number is " + snoop.acctNo);

Java does not allow arbitrary casting between objects; an object can only be cast to one of its superclasses or its subclasses.

To satisfy the compiler code can be changed as follows:

Object cc = Wallet.getCreditCard( );
CreditCardSnoop snoop = (CreditCardSnoop) cc;

In this case, the virtual machine will throw a ClassCastException when the snoop variable is assigned to thwart the attack.


The Bytecode Verifier
This is used to check whether the code compiled by the compiler is a legal java code. The Java verifier examines all such application byte code and, using a fancy set of heuristics, identifies code that doesn't play by the rules. Once byte code is verified, the virtual machine knows that it's safe to execute.

For example, consider the following classes

public class CreditCard {
public String acctNo = "0001 0002 0003 0004";
}
public class Test {
public static void main(String args[]) {
CreditCard cc = new CreditCard( );
System.out.println("Your account number is " + cc.acctNo);
}
}

If we run this code, we'll create a CreditCard object and print out its account number. If we change the definition of acctNo to be private and recompile only the CreditCard class. We then have two class files and the Test class file contains Java code that illegally accesses the private instance variable acctNo of the CreditCard class and hence will not be allowed to execute.


Java Cryptographic Extension(JCE)
JCE provides a framework and implementations for encryption, key generation and key agreement, and Message Authentication Code (MAC) algorithms. Support for encryption includes symmetric, asymmetric, block, and stream ciphers.


Java Authentication and Authorization Service (JAAS)
JAAS , as the name suggests is used for
1) For authentication of users, to reliably and securely determine who is currently executing Java code, regardless of whether the code is running as an application, an applet, a bean, or a servlet.
2) For authorization of users, to ensure they have the access control rights (permissions) required to perform the actions.


Java Secure Socket Extension (JSSE)
JSSE enables secure Internet communications. It provides a framework and an implementation for the Socket Security Layer(SSL) and Transport Layer Security(TLS) protocols and includes functionality for data encryption, server authentication, message integrity, and optional client authentication.

The Secure Sockets Layer(SSL) and Transport Layer Security(TLS) protocols are used to protect the privacy and integrity of data while it is transferred across a network.

References

[1] Hunt, Andrew and Thomas David. "Programming Ruby,The Pragmatic Programmer's Guide".
[2] "Crypt" Library Website: http://crypt[dot]rubyforge[dot]org/
[3] Ruby Website, Security Sections: http://www[dot]ruby-lang[dot]org/en/security/
[4] Scott Oaks. "Java Security".
[5] Sun website, Security Sections: http://java[dot]sun[dot]com/javase/technologies/security/