The problem I'm dealing with below is: you have proxy trust, but don't
trust the *-api.jar (Service Interface) and a user with less privileges
than the proxy is accessing it.
The proxy can't perform a SecurityManager permission check against the
user's Principal because it will throw an Exception, even when the user
is a privileged, because the permission check is the intersection of all
ProtectionDomain's on the callers stack. The ProtectionDomain of
*-api.jar has no Permission's and is on the stack.
Below I discuss solutions to overcome Proxy's and Clients utilising
untrusted Service Interfaces (*-api.jar).
I think I have found a suitable solution. Clients and proxy's can use
it to perform Security checks and Privileged Actions, but the *-api.jar
classes can't take advantage of it to subvert Security because of
ClassLoader isolation.
Peter Firmstone wrote:
To overcome the problem of all SecurityManager.checkPermission(perm)
always throwing an Exception caused by a *-api.jar file being present
on the stack and having no Permissions:
I could create an implementation of DomainCombiner, that removes
ProtectionDomains of *-api.jar to create a new AccessControlContext
that can be passed to the two method argument of
SecurityManger.checkPermission(permission, context) or
AccessController.doPrivileged(action, context).
A utility class could create the new AccessControlContext.
I wouldn't need to worry if *-api.jar classes could access the
utility, because the ProtectionDomain of the *-api.jar would have no
permissions. The utility would only be used by classes that *-api.jar
can't see to perform privileged actions.
That way the *-api.jar ProtectionDomain could continue to have no
Permissions and we wouldn't need to verify their classes.
Any Security experts out there?
System ClassLoader
|
Extension ClassLoader (incl jsk-policy.jar)
|
Jini Platform ClassLoader (incl jsk-platform.jar,
*-api.jar)
|
_______________|________________
| |
Application ClassLoader Proxy ClassLoader's
Then when performing AccessController.doPrivileged, you can't escalate
privileges with it, but you can remove the *-api.jar ProtectionDomain
from the context.
Could you use this to execute a Trojan hidden in an *-api.jar by
calling it from a rogue proxy?
No, because it only affects subsequent access determinations, why
would you bother with the Trojan method, if you already had the
permissions to perform a security sensitive action?
The use of DomainCombiner to remove ProtectionDomain's sounds counter
intuitive (but appears workable, from reading the source: after
optimise() is called on the AccessControlContext).
This would be a better security solution than using ClassDep to verify
security, and will allow Proxy's to perform permission checks with a
new AccessControlContext, without *-api.jar ProtectionDomain's.
Yep security is hard. Phew!
Can anyone see any problems with it?
Remember this stuff has to exist on the internet, so it has to be
secure, we could allow dynamic grants, so if you trust an *-api.jar
you can be less pedantic?
It would only be for using untrusted Service API's. Eg, you might not
trust the Service API, however someone you do trust has implemented it
and you want to grant some trust to their proxy.
Proxy implementers will have to consider the case where a client
trusts them but not the Service API.
It might take some time to digest this.
Cheers,
Peter.
Peter Firmstone wrote:
Actually on Second thoughts, this security concern is unfounded
(paranoia perhaps, security is hard!), the ProtectionDomain of the
*-api.jar will be on the execution stack, the actual Permissions will
be those common to all ProtectionDomain's on the caller's stack, so
therefore having a ProtectionDomain with no permissions assigned to a
*-api.jar will cause the calling thread to have no permissions (as
the proxy sees it).
Therefore a proxy, if it is to utilise it's own permission grants, it
will need to use AccessController.doPrivileged()
That sounds better.
Anyway there will be no Permissions granted to any *-api.jar, ever as
I'm going to utilise the pre java 1.4 ProtectionDomain constructor,
that specifically prevents and excludes dynamic Policy grants. It
won't even consult the Policy.
I'm modifying DynamicPolicy to include grants by Certificate[], an
*-api.jar that is signed by a trusted certificate chain, still wont
gain any permissions. Can anyone see that as a problem?
The *-api.jar classes must not have dependencies on anything outside
of the Jini Platform, Java Platform or other *-api.jar classes. The
reason for this restriction, is if Someone want's to use OSGi or has
a dependency on another version of a library, the *-api.jar importing
an incompatible version, would obscure it's visibility and cause a
runtime error.
These restrictions shouldn't cause a problem for people as they're
easy to design around. It makes security simpler for developers
too. - You don't have to worry about the security of the code in
*-api.jar
Cheers,
Peter.
Peter Firmstone wrote:
Dennis Reedy wrote:
Chris, Dennis & Greg, your all spot on with the Service-spec.jar,
I'd like to add something to the jar Manifest of these Service
Interfaces, to ensure River loads it into the top level
ClassLoader. Any suggestions?
Why not just support the convention instead of adding configuration?
Ok.
There is one Security Concern that I will have to address with this
Approach:
ClassLoader Structure:
System ClassLoader
|
Extension ClassLoader (incl jsk-policy.jar)
|
Jini Platform ClassLoader (incl jsk-platform.jar,
*-api.jar)
|
_______________|________________
| |
Application ClassLoader Proxy ClassLoader's
The *-api.jar files will be placed into Jini Platform ClassLoader,
so the only files visible will be the jini platform classes, java
platform classes and any other *-api.jar classes.
The *-api.jar classes will have their own ProtectionDomain's without
any Permissions.
However this isn't enough to protect us from code that might be
included in the *-api.jar's that use the calling Threads Permissions
to perform security violating actions.
Due to these security concerns, we need to place some restrictions
on the API classes:
1. They must not be allowed to depend on anything other than Jini,
Java Platform and other Service-api.jar's
2. They must not be allowed to depend on any Platform classes that
could cause a Security Violation.
The Service API code really needs to be verified before loading, to
ensure that it does not utilise any platform classes that perform
security sensitive operations.
The ClassDep tool can run a Dependency Analysis on any *-api.jar to
ensure that no security sensitive classes are accessed, prior to
loading.
There is some residual risk that as the Java platform evolves, new
classes that perform Security Sensitive actions will be added, which
means the list of restricted classes will need to grow over time.
Could the list itself be contained in a Maven Repository, we could
sign, such a list.
Thoughts?
Peter.