Preventing untrusted code from leaving the sandbox

See http://www.contextis.com/files/are_you_my_type.pdf, which explains several exploits based on .NET serialization, where an untrusted object can be serialized inside the sandbox, cross AppDomain boundaries, and be de-serialized already in the fully trusted AppDomain.

The rule sandbox does not have a permanent, must-use communication channel with the parent AppDomain, but several things might involve serialization from the sandbox to the parent AppDomain:

  • Exceptions thrown from rule execution.
  • Results of rule tests returned from the Rule Test Engine, including exceptions if the test failed.
  • Calls from a rule into the InForm application through the COM interface.

Sandbox exceptions are caught inside the sandbox, and new exceptions are thrown to the parent AppDomain. The assumption is that all caught exceptions are already logged, and creating new exceptions will not result in the loss of information about errors.

If a test fails and an exception occurs, the exception is rewritten or replaced with a string error message. The Rule Test Harness uses only an exception message.

The Oracle Health Sciences InForm COM interface comes into the main fully trusted AppDomain as .NET COM Interop. This reference then passes into the sandbox. Several methods in this interface have object type parameters, which potentially can allow any object to pass in. Untrusted code can create a serializable object, and pass it into the InForm interface. The object can be de-serialized into the main fully trusted AppDomain.

However, InForm Interop assemblies do not allow partially trusted callers, so untrusted code cannot call them directly. There is no way to pass indirectly arbitrary objects into these calls, because the Oracle Health Sciences InForm application assumes they are integers.