river-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Peter Firmstone <peter.firmst...@zeus.net.au>
Subject Distributed network security
Date Thu, 28 Jun 2012 12:32:30 GMT
What follows is relatively hard core security, but it's relevant to anyone wishing to deploy
on untrusted networks.  I know some people don't like discussing security issues for fear
of turning off would be developers but security isn't mandatory, however considering that
River/Jini is already making extremely difficult tasks possible, I think it appropriate to
continue focusing on solving difficult issues, especially considering recent online coverage
and increasing awareness of java security issues.  In the long run this will make life easier
for developers.

Java 2 security infrastructure was originally designed around codebase trust, but it's also
extensible and customisable, JAAS was designed around the premise of user security concerns,
previously lacking from Java 2, code was assumed to be trusted in most cases, although it's
also still possible to restrict permission to a combination of principals and codesources
or certificates, but in practise, permission is generally granted to principals.  JAAS uses
the SubjectDomainCombiner to inject principals into every protection domain on the call stack
(well it replaces them actually, but that's an implementation detail).

To ensure that only trusted code is used by authorised principals, policy file permission
grants must be made that includes both the signer of the code and the principal authorised.
 Failure to include the code signer in the permission grant may allow untrusted code to gain
elevated permissions on the call stack by being executed by an authorised principal.  

In a distributed environment it is difficult if not impossible to know in advance which code
signers and principal grant combinations are required, these interactions and introductions
may occur dynamically at runtime.   For this reason, too much permission is often granted,
in order to allow the software to function intuitively or as anticipated by users, leaving
security holes for opportunistic attackers.

A user is bound to a single thread and all child threads inherit its context.  Executors and
Thread pools may execute tasks on behalf of users however user AccessControlContext must be
copied from submitting threads.  

SubjectDomainCombiner is extendable, it isn't final, JAAS behaviour can be subtly modified
without having to reinvent the wheel.

So what changes need to be made to SubjectDomainCombiner functionality to allow the mixing
of Principal grants with codebase or codesigner grants in the presence of untrusted code without
compromising security?

Instead of injecting Subject principals into every ProtectionDomain on the stack, add a new
ProtectionDomain, containing the Subject's Principals to the existing stack.  In the presence
of untrusted code, priviledge is reduced to the intersection of commonly held Permissions,
instead of being elevated to those of the principal.  ProtectionDomain would also need to
be subclassed, eg SubjectProtectionDomain, so the SubjectDomainCombiner could identify and
replace the SubjectProtectionDomain when running as another more privileged Subject in a privileged
context (equivalent to that effected by Subject.doAs).  This also requires that other ProtectionDomain's
without Principals will require all necessary permissions granted in policy statements.

Unfortunately it is much simpler to make all the necessary grants only to Principals and associate
them with Subjects upon login.  It takes considerably more effort to determine all the code
sources that require these permissions, a deployment simulation tool could greatly simplify
determining permission requirements during deployment, so it doesn't become an impediment
to adoption, but has rather the opposite affect.

According to current policy behaviour, a ProtectionDomain with a null CodeSource would not
be granted any Permission, ever!  A ProtectionDomain containing a CodeSource with null URL
can however be granted Permission, provided no codesource is specified in relevant policy
file grant statements.   A Principal only ProtectionDomain would need to have a CodeSource
with null URL, to avoid any unexpected behaviour when combined in the stack.

JAAS was designed so permissions are not granted until after a user has authenticated so trusted
code cannot perform privileged tasks such as connecting to a network until after a user is
logged in, however a system where trusted code is granted permission it already has sufficient
permission.  Authentication in this case would inject a ProtectionDomain on the stack that
reduces privileges.  Log-in represents a lessening of permission.  This will work if the only
way for the user to access the functionality the code provides is by logging in.

The question is, which is easier to control, untrusted code that may be able to gain privilege
by running on a user thread (a trojan) or trusted code logging in users?   The former is indeterminate
in an environment where untrusted or semi trusted third party code exists.

The beauty of SPKI/SDSI is it can be used as glue between separate domains of authority, allowing
each to use disparate systems and be responsible for delegating authority granted by external
entities within their own domain.

In SPKI/SDSI, a subject is represented by a public key, a user can have associated authorisation
certificates, these certificates can be delegated to authorise a user to perform tasks in
another administration domain belonging to another company.  Using the DynamicPolicyProvider
and PermissionGrant interface, an authority certificate having an expiry date, could be verified
and dynamically granted.

SPKI/SDSI allows the security framework to determine authorisation, without concerning itself
with authentication, simply by the association of authority certificates with a public key
(Subject), authority certificates only have value to the Subject that originally granted them
(typically an admin), so the authority that granted these certificates will be the administrator
of the domain where the certificates are presented as evidence of authorisation by some remote
client.  Since there may be a combination of different codebase signers in use at the same
time, it isn't practical to combine this grant with a signer, the code has to be assumed trusted,
however the reality is that not all code is trusted.  Instead a jar file could contain an
address where authorisation certificates can be retrieved.

The new security manager lends itself to the creation of a runtime security tool that can
create policy files based on least privilege principles under controlled conditions simulating
the deployment environment.   The policy file produced will need some editing for portability,
since all environment variables are expanded, it will be useful to enable developers to determine
security policy requirements for each ProtectionDomain and User role.

Adopting least privilege principles for tasks eliminates unidentified and existing security
bugs, such as deserialisation attacks, similar to CVE-2010-0094 RMIConnectionImpl and CVE-2008-5353
ZoneInfo object deserialization demonstrated by deserializing Calendar objects.  This happens
because ClassLoader.defineClass needs to load the class file before it can define the ProtectionDomain
so the deserialising class's ProtectionDomain is not on the stack, readObject() is called
with reflection, it isn't part of an inheritance hierarchy.   Sun's bug fix limited the permissions
to those that were required by the Calendar class. DownloadPermission cannot prevent this
BTW because readObject() is executed in a privileged context, a custom ClassLoader can be
created bypassing PreferredClassLoader.

Least privilege limits permissions to those required to perform intended tasks, even so called
trusted jvm library code can have limited privileges.  If you need to deseralize Calendar
objects, don't grant any unnecessary privileges, this fixes bugs without changing code.  Least
privileged principles limit privileged code blocks ability to do anything other than what's
absolutely necessary.

Even though the java 2 security architecture was designed to support least privilege, it is
seldom implemented that way in practise, increasing the opportunity for crackers to find exploits.

Although none of this will make it into the upcoming release, it may make the following and
I'd like to finish security prior to implementing UDT sockets to enable internet based services
and DNS SRV based discovery and codebases.

  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message