Dynamic Languages and Java/Security
From JVMLanguages
| Table of contents |
Introduction
In this chapter I will discuss security considerations for language integration. What does it mean for each of these projects when source code in the host language is trusted but the other code cannot be?
Sandboxing
Sandboxing is a technique of separating a subset of your code from the rest and giving this code restricted access to the available resources. This technique is supported to some degree by many languages, including Java, but it tends to be much more useful in situations of language integration. The reason for this is that the language that is being integrated with Java is often interpreted and is produced by a different source than the Java application. Therefore it often makes sense to limit what this code is allowed to do. Because your application is executing that code you can have full control over what the other language is allowed to do. There are a few different techniques for controlling this access. We will discuss three ways: code signing, access control (?), and capability-based security.
Perl's Safe module
Python
Ruby
Code Signing
Jar signing/sealing
.NET signing
Access Control
In Java, the AccessManager provides a centralized mediator that controls what activities can take place in the current sandbox. Often this AccessManager is simply following a policy laid out in a configuration file.
Explain what can be done with a wide-open AccessManager (mutating immutable objects, Unsafe to do memory analysis and illegal type conversions, etc.).
Capability-Based Security (Reachability)
Capability-based security, on the other hand, is the idea that you are allowed to do anything with an object once you obtain a reference to it. Security is implemented by limiting the scope of various objects to only those clients which require them.
This places quite a few additional constraints on the language which Java does not: no statics -- TODO: others? also, explain how to revoke objects.
E
Rune interpreter
Language support for Asynchronous Messaging
Eventually operator
Promises
Why is it that deadlock cannot occur? ("Data lock possibility")
Summoning pattern?
Integration features: can call directly, can call via E.call(obj, signature, [args]), "asType"
Type Safety
C++
There are three types of casts in C++:
static_cast
This is equivalent to a normal cast in C. The compiler will make some effort to verify that the cast is valid, but it will not catch all illegal cases (e.g., casting from void * to any other class). This cast will also perform type-coersion, for example to convert between int and float.
dynamic_cast
This cast is verified at run-time, so it should be completely safe. However, this requires the use of RTTI.
reinterpret_cast
This type of cast will simply trick the type system into changing the type of a variable, without any verification or adjustment of the data itself. This type of cast is useful for treating one data type as if it were another (e.g., getting the individual bytes that make up a double value).
const_cast
This cast can only be used to remove the const keyword from a type -- effectively making immutable objects mutable again. This will be mentioned in more detail under the Immutability section.
Java
All casts in Java are like dynamic_cast in C++. They verify the run-time type of the object before allowing the cast.
E
Guards
Immutability
C/C++
C and C++ provide support for enforcing immutability via the const keyword. This keyword can be used in a variety of different contexts:
//This specifies that obj will not be modified in this method. void foo (const ComplexObject &obj); //This specifies that the ComplexObject instance returned from this method should not be modified. const ComplexObject foo (); //This specifies that the target object itself will not be modified. void foo () const;
Ruby
Ruby also provides functionality for enforcing objects to remain immutable. All objects define a freeze() method which, when called, will set a flag on the object that ensures no fields on that object can ever change.
Ruby's freeze mechanism differs from C++'s const in several important ways. The most obvious difference is that freeze operates on objects, while const operates on types. This means that in C++ you can have one block of code treat an object as immutable while another block does not, whereas in Ruby once an object is frozen, it is always frozen. There is no way to unfreeze an object -- if you want to modify it you must clone the object. Every object starts out as unfrozen (even if it is cloned from a frozen object). This mechanism does not require that all methods that may act on an immutable object be declared in a certain way -- the mechanism is enforced at run-time. In some ways this is good, because you do not need to modify every method that may possibly be called, but it also means that mutability errors are checked are run-time and may not be caught without thorough testing.
E
E provides two methods that operate much like Ruby's freeze and clone called diverge and snapshot.
Java
Taint Checking
Taint Checking is the process of tracking the source of each value as it is passed around your application, and restricting the flow of that data based on its source. Taint checking is often useful in servers, and especially when developing dynamic web content.
Perl
Where is the taint bit stored? How can it be examined?
Limitations on Tainted Data
Cleaning Tainted Data
The only way to untaint data is to match it with a regular expression.
Ruby
Where is the taint bit stored? How can it be examined?
Limitations on Tainted Data
Cleaning Tainted Data

