You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@river.apache.org by Peter Firmstone <ji...@zeus.net.au> on 2010/10/18 03:08:38 UTC
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling
of smart proxy's
Notes for fix:
DownloadPermission protects against unauthenticated downloads
ClassLoadingPermission - new Permission to protect against
unauthenticated Class loading.
Issues we're addressing in the DOS hole:
* Eliminate unauthenticated URL downloads.
* Eliminate unmarshalling of unauthenticated code.
* Eliminate execution of unauthenticated code.
* Eliminate StackOverflowError's in the client thread, caused by
sending spurious garbage over InputStream's.
* Eliminate StackOverflowError's in the client thread, caused by
substituted jar files or URL's from DNS cache poisoning attacks etc.
How?
* Delay granting DownloadPermission, until remote endpoint has
authenticated itself, we trust the remote endpoint to advise a
suitable URL, if it authenticates.
* Authentication by annotating a reflective proxy (additional to the
Codebase String) from the remote endpoint, used for authentication
and to provide CodeSource Certificate[]'s. This may be different
to the Service, if a remote object is marshalled elsewhere (eg
another client).
* Delay granting ClassLoadingPermission, until remote endpoint has
authenticated itself and has provided the expected CodeSource
Certificate[]'s
* Perform unmarshalling in a controlled ExecutorService thread.
So all we're doing different is authenticating the remote end and if it
authenticates permit downloading and classloading.
There is one more scenario to consider, currently this is a mechanism to
protect against download and deserialization of unknown code for smart
proxy's. But what about Service that only use reflective proxy's and
don't require downloaded code?
But what if we don't want to grant download permission or class loading
permission to a Subject we authenticate?
Currently the unmarshalling code doesn't run as the Subject after
authentication, this means the Permission grant's are only dependent on
authentication, something Michal pointed out earlier when this was proposed.
Now this code can be easily changed so the granting permission operation
is run as the Subject after authentication, this would allow us to
distinguish between different Subjects.
The drawback is that performance won't be as good, but it seems the most
logical and powerful approach.
What do you think?
There is one last obstacle, if Certificates are used to sign the jar
files, how do you effectively prevent one Subject from using another
Subject's signed CodeSource's if Code signing is used for isolation of
separate Subjects namespaces? A service could deliberately attempt to
occupy the same namespace as another Service to attempt to gain
information via shared static variables. We need to prevent this occurring.
This has to be done with the ClassLoader, but during unmarshalling, the
service proxy has not yet been verified. The authentication proxy
delivered with the MarshalInputStream may not have the same Subject as
the Service, it could be a third party.
Could it be that when the smart proxy is unmarshalled, and executed as
it's Subject, it must contain a Certificate matching the signer of the
Codebase?
We're on the cusp of solving this problem, thoughts?
Cheers,
Peter.
Peter Firmstone (JIRA) wrote:
> Denial of Service during unmarshalling of smart proxy's
> -------------------------------------------------------
>
> Key: RIVER-362
> URL: https://issues.apache.org/jira/browse/RIVER-362
> Project: River
> Issue Type: Bug
> Environment: Untrusted networks
> Reporter: Peter Firmstone
>
>
> During unmarshalling of smart proxy's there's a period before the proxy has been verified (authenticated) where deserialization methods are executed on untrusted code, the potential exists for untrusted code to perform denial of service.
>
>
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling
of smart proxy's
Posted by Peter Firmstone <ji...@zeus.net.au>.
Thanks Michal,
If you log into JIRA, it has an upload feature, you can attach the code
directly to the issue and grant an AL2 license at the same time.
https://issues.apache.org/jira/browse/RIVER-362
Cheers,
Peter.
Michal Kleczek wrote:
> Folks,
>
> I've managed to create a prototype implementation of the idea of annotating
> classes with Modules.
> Working on this allowed me to learn quite a lot about inner workings of River
> - the original implementation that I've presented before had to be modified
> (not saying it had to be fixed :) ) but the main idea stayed the same. This
> time I think it really covers more use cases.
>
> Shortly:
> 1. We allow annotating classes with Modules. A Module is an object responsible
> for loading classes.
> 2. There is a new RMIClassLoaderSpi implementation which I called
> ModuleClassProvider
> 3. ModuleClassProvider manages installed Modules
> 4. It also can load classes based on String annotations which are expected to
> be either
> a) serialized and Base64 encoded Module - the Module is deserialized and
> handled as any other Module annotation
> b) an old style list of URLs - class loading is delegated to
> RequireDlPermProvider - in other words we either load classes from Modules
> (which are verified for trust before use) or from URLs but then we require
> appropriate DownloadPermissions
>
> Attached is a multi-module maven project. The modules are:
> 1. secure-marshall-stream (which is the implementation of all this + some not
> yet finished additional code)
> 2. jsk-module-platform which contains modified Jini classes so that it all
> works with existing Jini services (to be honest only ClassLoading really
> needed to change. MarshalInputStream/MarshalOutputStream/MarshalledInstance
> are changed only to avoid having serialized and Base64 encoded Modules as
> annotations
>
> To run it you need to put jsk-module-platform before jsk-platform on the
> classpath (and of course add secure-marshall-stream as well)
>
> Existing services can be exported with a ModuleExporter:
>
> private serviceILFactory =
> new ProxyTrustILFactory(serviceConstraints,
> RegistrarPermission.class);
> private moduleTrustILFactory =
> new ModuleTrustILFactory(serviceConstraints,
> null);
>
> serverExporter = new ModuleExporter(new BasicJeriExporter(serviceEndpoint,
> serviceILFactory), new BasicJeriExporter(serviceEndpoint,
> moduleTrustILFactory));
>
> I've done some basic scenario testing which was running Reggie and Service
> Browser installed by Jini 2.1 installer. Both Browser and Reggie policies did
> not grant any DownloadPermissions.
> When exported with BasicJeriExporter lookup of ServiceRegistrar by the Browser
> failed with missing DownloadPermission.
> When exported with ModuleExporter both Reggie and Browser used
> ProxyTrustVerifier to verifify Modules.
>
> Note - this is strictly a prototype - no comments / junit tests / code reviews
> and no real testing.
>
> If you have any questions / comments - you're very welcome.
>
> Michal
>
> On Monday 18 of October 2010 03:08:38 Peter Firmstone wrote:
>
>> Notes for fix:
>>
>> DownloadPermission protects against unauthenticated downloads
>> ClassLoadingPermission - new Permission to protect against
>> unauthenticated Class loading.
>>
>> Issues we're addressing in the DOS hole:
>>
>> * Eliminate unauthenticated URL downloads.
>> * Eliminate unmarshalling of unauthenticated code.
>> * Eliminate execution of unauthenticated code.
>> * Eliminate StackOverflowError's in the client thread, caused by
>> sending spurious garbage over InputStream's.
>> * Eliminate StackOverflowError's in the client thread, caused by
>> substituted jar files or URL's from DNS cache poisoning attacks etc.
>>
>> How?
>>
>> * Delay granting DownloadPermission, until remote endpoint has
>> authenticated itself, we trust the remote endpoint to advise a
>> suitable URL, if it authenticates.
>> * Authentication by annotating a reflective proxy (additional to the
>> Codebase String) from the remote endpoint, used for authentication
>> and to provide CodeSource Certificate[]'s. This may be different
>> to the Service, if a remote object is marshalled elsewhere (eg
>> another client).
>> * Delay granting ClassLoadingPermission, until remote endpoint has
>> authenticated itself and has provided the expected CodeSource
>> Certificate[]'s
>> * Perform unmarshalling in a controlled ExecutorService thread.
>>
>> So all we're doing different is authenticating the remote end and if it
>> authenticates permit downloading and classloading.
>>
>> There is one more scenario to consider, currently this is a mechanism to
>> protect against download and deserialization of unknown code for smart
>> proxy's. But what about Service that only use reflective proxy's and
>> don't require downloaded code?
>>
>> But what if we don't want to grant download permission or class loading
>> permission to a Subject we authenticate?
>>
>> Currently the unmarshalling code doesn't run as the Subject after
>> authentication, this means the Permission grant's are only dependent on
>> authentication, something Michal pointed out earlier when this was
>> proposed.
>>
>> Now this code can be easily changed so the granting permission operation
>> is run as the Subject after authentication, this would allow us to
>> distinguish between different Subjects.
>>
>> The drawback is that performance won't be as good, but it seems the most
>> logical and powerful approach.
>>
>> What do you think?
>>
>> There is one last obstacle, if Certificates are used to sign the jar
>> files, how do you effectively prevent one Subject from using another
>> Subject's signed CodeSource's if Code signing is used for isolation of
>> separate Subjects namespaces? A service could deliberately attempt to
>> occupy the same namespace as another Service to attempt to gain
>> information via shared static variables. We need to prevent this
>> occurring.
>>
>> This has to be done with the ClassLoader, but during unmarshalling, the
>> service proxy has not yet been verified. The authentication proxy
>> delivered with the MarshalInputStream may not have the same Subject as
>> the Service, it could be a third party.
>>
>> Could it be that when the smart proxy is unmarshalled, and executed as
>> it's Subject, it must contain a Certificate matching the signer of the
>> Codebase?
>>
>> We're on the cusp of solving this problem, thoughts?
>>
>> Cheers,
>>
>> Peter.
>>
>> Peter Firmstone (JIRA) wrote:
>>
>>> Denial of Service during unmarshalling of smart proxy's
>>> -------------------------------------------------------
>>>
>>> Key: RIVER-362
>>> URL: https://issues.apache.org/jira/browse/RIVER-362
>>>
>>> Project: River
>>>
>>> Issue Type: Bug
>>>
>>> Environment: Untrusted networks
>>>
>>> Reporter: Peter Firmstone
>>>
>>> During unmarshalling of smart proxy's there's a period before the proxy
>>> has been verified (authenticated) where deserialization methods are
>>> executed on untrusted code, the potential exists for untrusted code to
>>> perform denial of service.
>>>
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling
of smart proxy's
Posted by Peter Firmstone <ji...@zeus.net.au>.
Michal Kleczek wrote:
> Thanks for taking time to look at this.
>
> 1. I am open to _any_ refactoring (and changing the code completely) - my code
> is just a prototype. BTW - would it be possible to put it somewhere in SVN?
I'll create a place in skunk for you, probably won't be until the
weekend though.
> It
> would be much easier for me to contribute - I don't need a commit access -
> just a simple way to produce patches. (The version attached to JIRA needs
> patching badly since it does not work :) )
>
> 2. I am not sure I understand the compatibility issues. I assume we're talking
> about a scenario where there is a running service that has MarshalledInstance
> objects saved somewhere and we want to upgrade it?
>
Sort of I mean if there's an Registrar using the old version of
MarshalledInstance, clients with new versions will be able to
deserialize MarshalledInstance, but not it's contained object, because
the stream implementations are different. Actually I suspect it may be
able to resolve the class locally, using only the object byte array, not
too sure, haven't tested it, based on reading the code.
Clients using the earlier version of MarshalledInstance trying to access
a Registrar that uses a later version wouldn't be able to discover it's
proxy.
Reggie's proxy could use Preferred ClassLoading to allow the client to
use services utilising later versions of MarshalledInstance..
> I think it can be easily solved by making ModuleAnnotatedInputStream capable
> of reading both String and Module annotations.
I had some thoughts about making a boot Module part of the serialized
from of MarshalledInstance, where earlier clients can fall back on the
String annotation. Later versions ignore the string annotation if a
boot Module is present.
> String annotations could be
> translated to DefaultRmiModule instances installed and used as usual later on.
> I would even say that my version of RMIClassLoaderSpi should be changed so
> that it can handle both serialized and encoded Modules as well as old style
> String annotations (lists of URLs). It should also produce old style
> annotations for DefaultRmiModules - otherwise tools such as VisualVM are not
> going to work ( tested this :) )
>
> 3. I found the following code in River dependent on annotations being Strings
> (and RMIClassLoader as well):
> 1) Anything that makes use of MarshalledObject (for example DiscoveryV1,
> RemoteEventListener)
> 2) Reggie entries assume annotation is a string
> 3) Outrigger - I don't know the details - just checked it calls
> RMIClassLoader.getClassAnnotation()
> 4) ProxyTrustVerifier - does a check if a candidate proxy's ClassLoader is a
> proper RMI ClassLoader by comparing annotations produced by RMIClassLoader
>
> Looks to me it is not straightforward to remove River dependency on
> RMIClassLoader (and - to be honest - it was not my goal at all - I wanted to
> have a piece of code that would plug into existing River)
>
Gregg Wonderly provided an implementation, it reportedly worked quite
well, I've yet to reinstate it and run some tests, but it did pass a
significant number of tests, I'm waiting for trunk to stabilise, then
I'll play with it again.
> 4. We can easily support scenarios where a client uses old services (the ones
> not aware of Modules) - see p. 2. But I don't thing there is an easy way for a
> service that annotates it's objects with Modules to provide a way for an old
> client to use it.
>
See suggestion above.
> 5. Didn't thing too much about implementing all this as a URL handler - it
> looks pretty complicated to me - handling Manifest classpaths, multi URL
> codebases etc.
>
Ok, just thought I'd ask the question.
> 6. Placing constraints on Modules is certainly possible but I have no idea how
> useful it could be and how hard it would be to implement it.
> The only constraint on a Module we need right now (so that the functionality
> is on-pair with existing River) is Integrity.YES. We handle it by just having
> a boolean argument in Module methods.
Did have a look at the MarshalledInstance I attached earlier, it
contains a serialization verifier proxy, it's possible to have it
authenticate and throw an IOException during deserialization if it's not
authorized. It uses MessageDigests to confirm the byte array's haven't
changed during transit, it also clones the arrays to guard against
stolen references. This could utilise client and server constraints for
privacy, authentication and minimum server principal.
If deserialization of MarshalledInstance, followed by unmarshalling of
it's contained object is done isolated within an Executor thread that
handles StackOverflowError's, then we're about as bullet proof as we can
get. The attacker will probably look for OS vulnerabilities instead and
steal a trusted identity.
If a client has an earlier version of MarshalledInstance, it simply
deserializes it and discards the proxy, but it still works as expected,
the client just doesn't have the Denial of Service deserialization and
codebase download attack protection.
> It made implementation easy (since it is
> similar to what we have in River right now). Also - I've got no idea how to
> implement other constraints - we would have do something really smart in
> PreferredClassLoader.
>
Getting Class loading right is important to avoid class visibility
problems. Because the service impl, proxy and client all share the same
common Service API, if they're all in child classloaders relative to the
ServiceAPI, then we won't have any classloading issues, since were using
common superclass and interface methods to communicate between different
namespaces.
> 7. I am not following on how you could get rid of CachingProxyTrust since you
> need to verify two objects.
>
Perhaps I've confused the issue, I'm referring to annotating the module
repeatedly with every object in the stream, rather than just once within
the MarshalledInstance serialized form.
Cheers,
Peter.
> Thanks,
> Michal
>
> On Tuesday 02 of November 2010 14:52:57 Peter Firmstone wrote:
>
>> Thanks Michal, that was helpful, sorry for taking so long to reply.
>>
>> Having chewed the details, I think now it is safe for me to comment, I'm
>> wondering if your open to some refactoring?
>>
>> You've managed to produce a lot of code in a very short time, your
>> productivity is quite impressive and you seem proficient using Secure
>> Jini Services.
>>
>> I've been thinking about your use of objects as annotations, which I
>> readily took to, something that's bothering me is backward
>> compatibility, an Object could be changed to a String, but a String is
>> final and existing implementations are stuck with it. MarshalledInstance
>> is part of the Discovery 2 Protocol, and Reggie, so it's serialized form
>> matters to remote foreign parties.
>>
>> The current way that MarshalledInstance Serialized Form is implemented
>> leaves it open to expansion due to readObject's implementation. This
>> means we can add fields without breaking backward compatibility. The
>> earlier implementations can utilise the existing fields and drop any
>> superfluous objects they don't know about.
>>
>> I'm wondering if it's possible to implement a Module URL scheme, similar
>> to Codebase Services?
>>
>> I've also wondered if using an authenticating verifier proxy during
>> deserialization of MarshalledInstance would be enough, saving the need
>> to Cache using the caching proxy trust verifier. MarshalledInstance is
>> the point of contact for Discovery and Lookup, if we require
>> authentication and verification, then that might be sufficient for
>> MarshalledInstance.
>>
>> We can utilise your Module annotated streams via Jeri, unbeknown to
>> external implementations.
>>
>> I've attached a very rough example draft rudimentary untested
>> MarshalledInstance (TODO: server min principal authentication) which
>> uses defensive copying and message digests to confirm the deserialized
>> state as part of the private implementation of MarshalledInstance. This
>> makes object integrity the responsibility of the Object itself, rather
>> than an external mechanism. So in this case privacy is the
>> responsibility of external mechanisms, but object integrity is an
>> internal concern.
>>
>> Gregg Wonderly created a CodebaseAnnotationClassloader (I think that's
>> the name I mentioned earlier), this might remove the need to use
>> RMIClassLoaderSPI and provide the opportunity to add some additional
>> functionality.
>>
>> See below for some more comments:
>>
>> Best Regards,
>>
>> Peter.
>>
>> Michal Kleczek wrote:
>>
>>> On Thursday 28 of October 2010 10:36:38 Peter Firmstone wrote:
>>>
>>>> Ok Interesting, anyone implementing a Service should be quite capable of
>>>> implementing equals, we should then specify that equals and hashcode
>>>> methods should be implemented for ProxyTrust.
>>>>
>>>> For my benefit can you go over the process of how your new code works?
>>>> I'm interested in the choices you've made & why.
>>>>
>>> Sure.
>>> Several choices were made because:
>>> 1. I wanted to reuse as much as possible from existing River
>>> 2. I wanted to have a working prototype fast :)
>>>
>>> Anyway:
>>> 1. The main idea is to have annotations as objects that could be verified
>>> using standard River proxy verification facilities. To be honest the
>>> idea of having Module interface that enables plugging different
>>> classloading mechanisms is something completely optional.
>>> 2. For the client the basic scenario is:
>>> a) The client gets a serialized object
>>> b) When it is deserialized annotations (Modules) are read and "installed"
>>> c) Installing a Module means:
>>> c1) checking if it was already installed
>>> c2) if not - prepare it using VerifyingProxyPreparer (I've choosen not to
>>> place any InvocationConstraints on Modules - I don't think it is
>>> necessary)
>>>
>> I'm curious why client MethodConstraints aren't needed?
>>
>>
>>> d) after a Module is installed it is used to load classes
>>> 3. There are several places in River that depend on annotations being
>>> Strings provided by RMIClassLoader. The most important places are
>>> a) Discovery
>>> b) Reggie implementation
>>> c) ProxyTrustVerifier
>>> Since I did not want to modify this code I had to implement
>>> RMIClassLoaderSpi so that it would provide serialized Modules as
>>> Strings. I've choosen to simply serialize them to byte arrays and Base64
>>> encode them.
>>> 4. There are two important Module implementations available:
>>> a) DefaultRmiModule
>>> b) ProxyTrustModule
>>> DefaultRmiModule can be trusted by the client without contacting any
>>> service - it uses RequireDlPermissionClassProvider to load classes.
>>> ProxyTrustModule on the other hand uses a simple PreferredClassProvider
>>> to load classes. It is a smart proxy that implements
>>> getProxyTrustIterator() so that it can be verified by
>>> ProxyTrustVerifier.
>>>
>>> On the server before we can annotate our objects with modules we have to
>>> register a Module that will be used as annotation.
>>> If the server does not register any Module - DefaultRmiModule is going to
>>> be used as annotation.
>>> The server can register a ProxyTrustModule as annotation - to do that it
>>> first must export an object that can be contacted to obtain a Module
>>> verifier. In other words - a service must either:
>>> a) export two ProxyTrusts (one for Modules and another one for the
>>> service itself)
>>> b) its ProxyTrust must provide a verifier that is able to verify both a
>>> Module and a service proxy
>>>
>>> To make it possible to use my code with existing services without
>>> modifying them I've decided to implement a special ModuleExporter which
>>> will override the service ServerProxyTrust implementation so that
>>> getProxyVerifier will return a Verifier capable of verifying both a
>>> Module and the service proxy. This verifier works as follows:
>>> 1. Check if an object being verified is a Module.
>>> 2. If so - delegate to a module verifier
>>> 3. If not it means we're verifying a service proxy so delegate to a
>>> default verifier.
>>> The problem is though that when this verifier is deserialized the module
>>> that is capable of loading the service proxy verifier is not yet
>>> installed (the client got this verifier to verify a Module before it can
>>> load any classes). That's why I called it LazyCompositeVerifier - the
>>> default verifier is not deserialized until it is actually needed.
>>>
>>> The only problem left is that every time a client gets a service proxy it
>>> will issue a remote call twice to get a verifier: first to get a
>>> verifier for a Module and then to get a verifier for a service proxy.
>>> But it is going to be the same verifier!!! So I've decided to implement
>>> a CachingProxyTrust that 1) can be trusted by the client without the
>>> need to issue any remote call (so we need a CachingProxyTrustVerifier
>>> configured on the client)
>>> 2) Will cache a verifier it obtains from its delegate
>>>
>>> The problem with CachingProxyTrust is that it has to be used by:
>>> a) a Module
>>> b) a service proxy
>>> That's why we need OverrideProxy - it is returned from ModuleExporter to
>>> the service so that the service is unaware of the CachingProxyTrust but
>>> still can use it to obtain its verifier. To trust OverrideProxy the
>>> client has to have OverrideProxyVerifier configured locally.
>>>
>>> I hope I clarified everything a little bit...
>>>
>>> Michal
>>>
>
>
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling
of smart proxy's
Posted by Peter Firmstone <ji...@zeus.net.au>.
Hi Michal,
Your code's included in svn at:
https://svn.apache.org/repos/asf/incubator/river/jtsk/skunk/river-modules
If you upload patches to Jira, I'll add them for you.
Cheers,
Peter.
Michal Kleczek wrote:
> Thanks for taking time to look at this.
>
> 1. I am open to _any_ refactoring (and changing the code completely) - my code
> is just a prototype. BTW - would it be possible to put it somewhere in SVN? It
> would be much easier for me to contribute - I don't need a commit access -
> just a simple way to produce patches. (The version attached to JIRA needs
> patching badly since it does not work :) )
>
> 2. I am not sure I understand the compatibility issues. I assume we're talking
> about a scenario where there is a running service that has MarshalledInstance
> objects saved somewhere and we want to upgrade it?
> I think it can be easily solved by making ModuleAnnotatedInputStream capable
> of reading both String and Module annotations. String annotations could be
> translated to DefaultRmiModule instances installed and used as usual later on.
> I would even say that my version of RMIClassLoaderSpi should be changed so
> that it can handle both serialized and encoded Modules as well as old style
> String annotations (lists of URLs). It should also produce old style
> annotations for DefaultRmiModules - otherwise tools such as VisualVM are not
> going to work ( tested this :) )
>
> 3. I found the following code in River dependent on annotations being Strings
> (and RMIClassLoader as well):
> 1) Anything that makes use of MarshalledObject (for example DiscoveryV1,
> RemoteEventListener)
> 2) Reggie entries assume annotation is a string
> 3) Outrigger - I don't know the details - just checked it calls
> RMIClassLoader.getClassAnnotation()
> 4) ProxyTrustVerifier - does a check if a candidate proxy's ClassLoader is a
> proper RMI ClassLoader by comparing annotations produced by RMIClassLoader
>
> Looks to me it is not straightforward to remove River dependency on
> RMIClassLoader (and - to be honest - it was not my goal at all - I wanted to
> have a piece of code that would plug into existing River)
>
> 4. We can easily support scenarios where a client uses old services (the ones
> not aware of Modules) - see p. 2. But I don't thing there is an easy way for a
> service that annotates it's objects with Modules to provide a way for an old
> client to use it.
>
> 5. Didn't thing too much about implementing all this as a URL handler - it
> looks pretty complicated to me - handling Manifest classpaths, multi URL
> codebases etc.
>
> 6. Placing constraints on Modules is certainly possible but I have no idea how
> useful it could be and how hard it would be to implement it.
> The only constraint on a Module we need right now (so that the functionality
> is on-pair with existing River) is Integrity.YES. We handle it by just having
> a boolean argument in Module methods. It made implementation easy (since it is
> similar to what we have in River right now). Also - I've got no idea how to
> implement other constraints - we would have do something really smart in
> PreferredClassLoader :)
>
> 7. I am not following on how you could get rid of CachingProxyTrust since you
> need to verify two objects.
>
> Thanks,
> Michal
>
> On Tuesday 02 of November 2010 14:52:57 Peter Firmstone wrote:
>
>> Thanks Michal, that was helpful, sorry for taking so long to reply.
>>
>> Having chewed the details, I think now it is safe for me to comment, I'm
>> wondering if your open to some refactoring?
>>
>> You've managed to produce a lot of code in a very short time, your
>> productivity is quite impressive and you seem proficient using Secure
>> Jini Services.
>>
>> I've been thinking about your use of objects as annotations, which I
>> readily took to, something that's bothering me is backward
>> compatibility, an Object could be changed to a String, but a String is
>> final and existing implementations are stuck with it. MarshalledInstance
>> is part of the Discovery 2 Protocol, and Reggie, so it's serialized form
>> matters to remote foreign parties.
>>
>> The current way that MarshalledInstance Serialized Form is implemented
>> leaves it open to expansion due to readObject's implementation. This
>> means we can add fields without breaking backward compatibility. The
>> earlier implementations can utilise the existing fields and drop any
>> superfluous objects they don't know about.
>>
>> I'm wondering if it's possible to implement a Module URL scheme, similar
>> to Codebase Services?
>>
>> I've also wondered if using an authenticating verifier proxy during
>> deserialization of MarshalledInstance would be enough, saving the need
>> to Cache using the caching proxy trust verifier. MarshalledInstance is
>> the point of contact for Discovery and Lookup, if we require
>> authentication and verification, then that might be sufficient for
>> MarshalledInstance.
>>
>> We can utilise your Module annotated streams via Jeri, unbeknown to
>> external implementations.
>>
>> I've attached a very rough example draft rudimentary untested
>> MarshalledInstance (TODO: server min principal authentication) which
>> uses defensive copying and message digests to confirm the deserialized
>> state as part of the private implementation of MarshalledInstance. This
>> makes object integrity the responsibility of the Object itself, rather
>> than an external mechanism. So in this case privacy is the
>> responsibility of external mechanisms, but object integrity is an
>> internal concern.
>>
>> Gregg Wonderly created a CodebaseAnnotationClassloader (I think that's
>> the name I mentioned earlier), this might remove the need to use
>> RMIClassLoaderSPI and provide the opportunity to add some additional
>> functionality.
>>
>> See below for some more comments:
>>
>> Best Regards,
>>
>> Peter.
>>
>> Michal Kleczek wrote:
>>
>>> On Thursday 28 of October 2010 10:36:38 Peter Firmstone wrote:
>>>
>>>> Ok Interesting, anyone implementing a Service should be quite capable of
>>>> implementing equals, we should then specify that equals and hashcode
>>>> methods should be implemented for ProxyTrust.
>>>>
>>>> For my benefit can you go over the process of how your new code works?
>>>> I'm interested in the choices you've made & why.
>>>>
>>> Sure.
>>> Several choices were made because:
>>> 1. I wanted to reuse as much as possible from existing River
>>> 2. I wanted to have a working prototype fast :)
>>>
>>> Anyway:
>>> 1. The main idea is to have annotations as objects that could be verified
>>> using standard River proxy verification facilities. To be honest the
>>> idea of having Module interface that enables plugging different
>>> classloading mechanisms is something completely optional.
>>> 2. For the client the basic scenario is:
>>> a) The client gets a serialized object
>>> b) When it is deserialized annotations (Modules) are read and "installed"
>>> c) Installing a Module means:
>>> c1) checking if it was already installed
>>> c2) if not - prepare it using VerifyingProxyPreparer (I've choosen not to
>>> place any InvocationConstraints on Modules - I don't think it is
>>> necessary)
>>>
>> I'm curious why client MethodConstraints aren't needed?
>>
>>
>>> d) after a Module is installed it is used to load classes
>>> 3. There are several places in River that depend on annotations being
>>> Strings provided by RMIClassLoader. The most important places are
>>> a) Discovery
>>> b) Reggie implementation
>>> c) ProxyTrustVerifier
>>> Since I did not want to modify this code I had to implement
>>> RMIClassLoaderSpi so that it would provide serialized Modules as
>>> Strings. I've choosen to simply serialize them to byte arrays and Base64
>>> encode them.
>>> 4. There are two important Module implementations available:
>>> a) DefaultRmiModule
>>> b) ProxyTrustModule
>>> DefaultRmiModule can be trusted by the client without contacting any
>>> service - it uses RequireDlPermissionClassProvider to load classes.
>>> ProxyTrustModule on the other hand uses a simple PreferredClassProvider
>>> to load classes. It is a smart proxy that implements
>>> getProxyTrustIterator() so that it can be verified by
>>> ProxyTrustVerifier.
>>>
>>> On the server before we can annotate our objects with modules we have to
>>> register a Module that will be used as annotation.
>>> If the server does not register any Module - DefaultRmiModule is going to
>>> be used as annotation.
>>> The server can register a ProxyTrustModule as annotation - to do that it
>>> first must export an object that can be contacted to obtain a Module
>>> verifier. In other words - a service must either:
>>> a) export two ProxyTrusts (one for Modules and another one for the
>>> service itself)
>>> b) its ProxyTrust must provide a verifier that is able to verify both a
>>> Module and a service proxy
>>>
>>> To make it possible to use my code with existing services without
>>> modifying them I've decided to implement a special ModuleExporter which
>>> will override the service ServerProxyTrust implementation so that
>>> getProxyVerifier will return a Verifier capable of verifying both a
>>> Module and the service proxy. This verifier works as follows:
>>> 1. Check if an object being verified is a Module.
>>> 2. If so - delegate to a module verifier
>>> 3. If not it means we're verifying a service proxy so delegate to a
>>> default verifier.
>>> The problem is though that when this verifier is deserialized the module
>>> that is capable of loading the service proxy verifier is not yet
>>> installed (the client got this verifier to verify a Module before it can
>>> load any classes). That's why I called it LazyCompositeVerifier - the
>>> default verifier is not deserialized until it is actually needed.
>>>
>>> The only problem left is that every time a client gets a service proxy it
>>> will issue a remote call twice to get a verifier: first to get a
>>> verifier for a Module and then to get a verifier for a service proxy.
>>> But it is going to be the same verifier!!! So I've decided to implement
>>> a CachingProxyTrust that 1) can be trusted by the client without the
>>> need to issue any remote call (so we need a CachingProxyTrustVerifier
>>> configured on the client)
>>> 2) Will cache a verifier it obtains from its delegate
>>>
>>> The problem with CachingProxyTrust is that it has to be used by:
>>> a) a Module
>>> b) a service proxy
>>> That's why we need OverrideProxy - it is returned from ModuleExporter to
>>> the service so that the service is unaware of the CachingProxyTrust but
>>> still can use it to obtain its verifier. To trust OverrideProxy the
>>> client has to have OverrideProxyVerifier configured locally.
>>>
>>> I hope I clarified everything a little bit...
>>>
>>> Michal
>>>
>
>
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling of smart proxy's
Posted by Michal Kleczek <mi...@xpro.biz>.
Thanks for taking time to look at this.
1. I am open to _any_ refactoring (and changing the code completely) - my code
is just a prototype. BTW - would it be possible to put it somewhere in SVN? It
would be much easier for me to contribute - I don't need a commit access -
just a simple way to produce patches. (The version attached to JIRA needs
patching badly since it does not work :) )
2. I am not sure I understand the compatibility issues. I assume we're talking
about a scenario where there is a running service that has MarshalledInstance
objects saved somewhere and we want to upgrade it?
I think it can be easily solved by making ModuleAnnotatedInputStream capable
of reading both String and Module annotations. String annotations could be
translated to DefaultRmiModule instances installed and used as usual later on.
I would even say that my version of RMIClassLoaderSpi should be changed so
that it can handle both serialized and encoded Modules as well as old style
String annotations (lists of URLs). It should also produce old style
annotations for DefaultRmiModules - otherwise tools such as VisualVM are not
going to work ( tested this :) )
3. I found the following code in River dependent on annotations being Strings
(and RMIClassLoader as well):
1) Anything that makes use of MarshalledObject (for example DiscoveryV1,
RemoteEventListener)
2) Reggie entries assume annotation is a string
3) Outrigger - I don't know the details - just checked it calls
RMIClassLoader.getClassAnnotation()
4) ProxyTrustVerifier - does a check if a candidate proxy's ClassLoader is a
proper RMI ClassLoader by comparing annotations produced by RMIClassLoader
Looks to me it is not straightforward to remove River dependency on
RMIClassLoader (and - to be honest - it was not my goal at all - I wanted to
have a piece of code that would plug into existing River)
4. We can easily support scenarios where a client uses old services (the ones
not aware of Modules) - see p. 2. But I don't thing there is an easy way for a
service that annotates it's objects with Modules to provide a way for an old
client to use it.
5. Didn't thing too much about implementing all this as a URL handler - it
looks pretty complicated to me - handling Manifest classpaths, multi URL
codebases etc.
6. Placing constraints on Modules is certainly possible but I have no idea how
useful it could be and how hard it would be to implement it.
The only constraint on a Module we need right now (so that the functionality
is on-pair with existing River) is Integrity.YES. We handle it by just having
a boolean argument in Module methods. It made implementation easy (since it is
similar to what we have in River right now). Also - I've got no idea how to
implement other constraints - we would have do something really smart in
PreferredClassLoader :)
7. I am not following on how you could get rid of CachingProxyTrust since you
need to verify two objects.
Thanks,
Michal
On Tuesday 02 of November 2010 14:52:57 Peter Firmstone wrote:
> Thanks Michal, that was helpful, sorry for taking so long to reply.
>
> Having chewed the details, I think now it is safe for me to comment, I'm
> wondering if your open to some refactoring?
>
> You've managed to produce a lot of code in a very short time, your
> productivity is quite impressive and you seem proficient using Secure
> Jini Services.
>
> I've been thinking about your use of objects as annotations, which I
> readily took to, something that's bothering me is backward
> compatibility, an Object could be changed to a String, but a String is
> final and existing implementations are stuck with it. MarshalledInstance
> is part of the Discovery 2 Protocol, and Reggie, so it's serialized form
> matters to remote foreign parties.
>
> The current way that MarshalledInstance Serialized Form is implemented
> leaves it open to expansion due to readObject's implementation. This
> means we can add fields without breaking backward compatibility. The
> earlier implementations can utilise the existing fields and drop any
> superfluous objects they don't know about.
>
> I'm wondering if it's possible to implement a Module URL scheme, similar
> to Codebase Services?
>
> I've also wondered if using an authenticating verifier proxy during
> deserialization of MarshalledInstance would be enough, saving the need
> to Cache using the caching proxy trust verifier. MarshalledInstance is
> the point of contact for Discovery and Lookup, if we require
> authentication and verification, then that might be sufficient for
> MarshalledInstance.
>
> We can utilise your Module annotated streams via Jeri, unbeknown to
> external implementations.
>
> I've attached a very rough example draft rudimentary untested
> MarshalledInstance (TODO: server min principal authentication) which
> uses defensive copying and message digests to confirm the deserialized
> state as part of the private implementation of MarshalledInstance. This
> makes object integrity the responsibility of the Object itself, rather
> than an external mechanism. So in this case privacy is the
> responsibility of external mechanisms, but object integrity is an
> internal concern.
>
> Gregg Wonderly created a CodebaseAnnotationClassloader (I think that's
> the name I mentioned earlier), this might remove the need to use
> RMIClassLoaderSPI and provide the opportunity to add some additional
> functionality.
>
> See below for some more comments:
>
> Best Regards,
>
> Peter.
>
> Michal Kleczek wrote:
> > On Thursday 28 of October 2010 10:36:38 Peter Firmstone wrote:
> >> Ok Interesting, anyone implementing a Service should be quite capable of
> >> implementing equals, we should then specify that equals and hashcode
> >> methods should be implemented for ProxyTrust.
> >>
> >> For my benefit can you go over the process of how your new code works?
> >> I'm interested in the choices you've made & why.
> >
> > Sure.
> > Several choices were made because:
> > 1. I wanted to reuse as much as possible from existing River
> > 2. I wanted to have a working prototype fast :)
> >
> > Anyway:
> > 1. The main idea is to have annotations as objects that could be verified
> > using standard River proxy verification facilities. To be honest the
> > idea of having Module interface that enables plugging different
> > classloading mechanisms is something completely optional.
> > 2. For the client the basic scenario is:
> > a) The client gets a serialized object
> > b) When it is deserialized annotations (Modules) are read and "installed"
> > c) Installing a Module means:
> > c1) checking if it was already installed
> > c2) if not - prepare it using VerifyingProxyPreparer (I've choosen not to
> > place any InvocationConstraints on Modules - I don't think it is
> > necessary)
>
> I'm curious why client MethodConstraints aren't needed?
>
> > d) after a Module is installed it is used to load classes
> > 3. There are several places in River that depend on annotations being
> > Strings provided by RMIClassLoader. The most important places are
> > a) Discovery
> > b) Reggie implementation
> > c) ProxyTrustVerifier
> > Since I did not want to modify this code I had to implement
> > RMIClassLoaderSpi so that it would provide serialized Modules as
> > Strings. I've choosen to simply serialize them to byte arrays and Base64
> > encode them.
> > 4. There are two important Module implementations available:
> > a) DefaultRmiModule
> > b) ProxyTrustModule
> > DefaultRmiModule can be trusted by the client without contacting any
> > service - it uses RequireDlPermissionClassProvider to load classes.
> > ProxyTrustModule on the other hand uses a simple PreferredClassProvider
> > to load classes. It is a smart proxy that implements
> > getProxyTrustIterator() so that it can be verified by
> > ProxyTrustVerifier.
> >
> > On the server before we can annotate our objects with modules we have to
> > register a Module that will be used as annotation.
> > If the server does not register any Module - DefaultRmiModule is going to
> > be used as annotation.
> > The server can register a ProxyTrustModule as annotation - to do that it
> > first must export an object that can be contacted to obtain a Module
> > verifier. In other words - a service must either:
> > a) export two ProxyTrusts (one for Modules and another one for the
> > service itself)
> > b) its ProxyTrust must provide a verifier that is able to verify both a
> > Module and a service proxy
> >
> > To make it possible to use my code with existing services without
> > modifying them I've decided to implement a special ModuleExporter which
> > will override the service ServerProxyTrust implementation so that
> > getProxyVerifier will return a Verifier capable of verifying both a
> > Module and the service proxy. This verifier works as follows:
> > 1. Check if an object being verified is a Module.
> > 2. If so - delegate to a module verifier
> > 3. If not it means we're verifying a service proxy so delegate to a
> > default verifier.
> > The problem is though that when this verifier is deserialized the module
> > that is capable of loading the service proxy verifier is not yet
> > installed (the client got this verifier to verify a Module before it can
> > load any classes). That's why I called it LazyCompositeVerifier - the
> > default verifier is not deserialized until it is actually needed.
> >
> > The only problem left is that every time a client gets a service proxy it
> > will issue a remote call twice to get a verifier: first to get a
> > verifier for a Module and then to get a verifier for a service proxy.
> > But it is going to be the same verifier!!! So I've decided to implement
> > a CachingProxyTrust that 1) can be trusted by the client without the
> > need to issue any remote call (so we need a CachingProxyTrustVerifier
> > configured on the client)
> > 2) Will cache a verifier it obtains from its delegate
> >
> > The problem with CachingProxyTrust is that it has to be used by:
> > a) a Module
> > b) a service proxy
> > That's why we need OverrideProxy - it is returned from ModuleExporter to
> > the service so that the service is unaware of the CachingProxyTrust but
> > still can use it to obtain its verifier. To trust OverrideProxy the
> > client has to have OverrideProxyVerifier configured locally.
> >
> > I hope I clarified everything a little bit...
> >
> > Michal
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling
of smart proxy's
Posted by Peter Firmstone <ji...@zeus.net.au>.
Thanks Michal, that was helpful, sorry for taking so long to reply.
Having chewed the details, I think now it is safe for me to comment, I'm
wondering if your open to some refactoring?
You've managed to produce a lot of code in a very short time, your
productivity is quite impressive and you seem proficient using Secure
Jini Services.
I've been thinking about your use of objects as annotations, which I
readily took to, something that's bothering me is backward
compatibility, an Object could be changed to a String, but a String is
final and existing implementations are stuck with it. MarshalledInstance
is part of the Discovery 2 Protocol, and Reggie, so it's serialized form
matters to remote foreign parties.
The current way that MarshalledInstance Serialized Form is implemented
leaves it open to expansion due to readObject's implementation. This
means we can add fields without breaking backward compatibility. The
earlier implementations can utilise the existing fields and drop any
superfluous objects they don't know about.
I'm wondering if it's possible to implement a Module URL scheme, similar
to Codebase Services?
I've also wondered if using an authenticating verifier proxy during
deserialization of MarshalledInstance would be enough, saving the need
to Cache using the caching proxy trust verifier. MarshalledInstance is
the point of contact for Discovery and Lookup, if we require
authentication and verification, then that might be sufficient for
MarshalledInstance.
We can utilise your Module annotated streams via Jeri, unbeknown to
external implementations.
I've attached a very rough example draft rudimentary untested
MarshalledInstance (TODO: server min principal authentication) which
uses defensive copying and message digests to confirm the deserialized
state as part of the private implementation of MarshalledInstance. This
makes object integrity the responsibility of the Object itself, rather
than an external mechanism. So in this case privacy is the
responsibility of external mechanisms, but object integrity is an
internal concern.
Gregg Wonderly created a CodebaseAnnotationClassloader (I think that's
the name I mentioned earlier), this might remove the need to use
RMIClassLoaderSPI and provide the opportunity to add some additional
functionality.
See below for some more comments:
Best Regards,
Peter.
Michal Kleczek wrote:
> On Thursday 28 of October 2010 10:36:38 Peter Firmstone wrote:
>
>> Ok Interesting, anyone implementing a Service should be quite capable of
>> implementing equals, we should then specify that equals and hashcode
>> methods should be implemented for ProxyTrust.
>>
>> For my benefit can you go over the process of how your new code works?
>> I'm interested in the choices you've made & why.
>>
>>
>
> Sure.
> Several choices were made because:
> 1. I wanted to reuse as much as possible from existing River
> 2. I wanted to have a working prototype fast :)
>
> Anyway:
> 1. The main idea is to have annotations as objects that could be verified using
> standard River proxy verification facilities. To be honest the idea of having
> Module interface that enables plugging different classloading mechanisms is
> something completely optional.
> 2. For the client the basic scenario is:
> a) The client gets a serialized object
> b) When it is deserialized annotations (Modules) are read and "installed"
> c) Installing a Module means:
> c1) checking if it was already installed
> c2) if not - prepare it using VerifyingProxyPreparer (I've choosen not to
> place any InvocationConstraints on Modules - I don't think it is necessary)
>
I'm curious why client MethodConstraints aren't needed?
> d) after a Module is installed it is used to load classes
> 3. There are several places in River that depend on annotations being Strings
> provided by RMIClassLoader. The most important places are
> a) Discovery
> b) Reggie implementation
> c) ProxyTrustVerifier
> Since I did not want to modify this code I had to implement RMIClassLoaderSpi
> so that it would provide serialized Modules as Strings. I've choosen to simply
> serialize them to byte arrays and Base64 encode them.
> 4. There are two important Module implementations available:
> a) DefaultRmiModule
> b) ProxyTrustModule
> DefaultRmiModule can be trusted by the client without contacting any service -
> it uses RequireDlPermissionClassProvider to load classes.
> ProxyTrustModule on the other hand uses a simple PreferredClassProvider to
> load classes. It is a smart proxy that implements getProxyTrustIterator() so
> that it can be verified by ProxyTrustVerifier.
>
> On the server before we can annotate our objects with modules we have to
> register a Module that will be used as annotation.
> If the server does not register any Module - DefaultRmiModule is going to be
> used as annotation.
> The server can register a ProxyTrustModule as annotation - to do that it first
> must export an object that can be contacted to obtain a Module verifier.
> In other words - a service must either:
> a) export two ProxyTrusts (one for Modules and another one for the service
> itself)
> b) its ProxyTrust must provide a verifier that is able to verify both a Module
> and a service proxy
>
> To make it possible to use my code with existing services without modifying
> them I've decided to implement a special ModuleExporter which will override
> the service ServerProxyTrust implementation so that getProxyVerifier will
> return a Verifier capable of verifying both a Module and the service proxy.
> This verifier works as follows:
> 1. Check if an object being verified is a Module.
> 2. If so - delegate to a module verifier
> 3. If not it means we're verifying a service proxy so delegate to a default
> verifier.
> The problem is though that when this verifier is deserialized the module that
> is capable of loading the service proxy verifier is not yet installed (the
> client got this verifier to verify a Module before it can load any classes).
> That's why I called it LazyCompositeVerifier - the default verifier is not
> deserialized until it is actually needed.
>
> The only problem left is that every time a client gets a service proxy it will
> issue a remote call twice to get a verifier: first to get a verifier for a Module
> and then to get a verifier for a service proxy. But it is going to be the same
> verifier!!! So I've decided to implement a CachingProxyTrust that
> 1) can be trusted by the client without the need to issue any remote call (so
> we need a CachingProxyTrustVerifier configured on the client)
> 2) Will cache a verifier it obtains from its delegate
>
> The problem with CachingProxyTrust is that it has to be used by:
> a) a Module
> b) a service proxy
> That's why we need OverrideProxy - it is returned from ModuleExporter to the
> service so that the service is unaware of the CachingProxyTrust but still can
> use it to obtain its verifier. To trust OverrideProxy the client has to have
> OverrideProxyVerifier configured locally.
>
> I hope I clarified everything a little bit...
>
> Michal
>
>
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling of smart proxy's
Posted by Michal Kleczek <mi...@xpro.biz>.
On Thursday 28 of October 2010 10:36:38 Peter Firmstone wrote:
> Ok Interesting, anyone implementing a Service should be quite capable of
> implementing equals, we should then specify that equals and hashcode
> methods should be implemented for ProxyTrust.
>
> For my benefit can you go over the process of how your new code works?
> I'm interested in the choices you've made & why.
>
Sure.
Several choices were made because:
1. I wanted to reuse as much as possible from existing River
2. I wanted to have a working prototype fast :)
Anyway:
1. The main idea is to have annotations as objects that could be verified using
standard River proxy verification facilities. To be honest the idea of having
Module interface that enables plugging different classloading mechanisms is
something completely optional.
2. For the client the basic scenario is:
a) The client gets a serialized object
b) When it is deserialized annotations (Modules) are read and "installed"
c) Installing a Module means:
c1) checking if it was already installed
c2) if not - prepare it using VerifyingProxyPreparer (I've choosen not to
place any InvocationConstraints on Modules - I don't think it is necessary)
d) after a Module is installed it is used to load classes
3. There are several places in River that depend on annotations being Strings
provided by RMIClassLoader. The most important places are
a) Discovery
b) Reggie implementation
c) ProxyTrustVerifier
Since I did not want to modify this code I had to implement RMIClassLoaderSpi
so that it would provide serialized Modules as Strings. I've choosen to simply
serialize them to byte arrays and Base64 encode them.
4. There are two important Module implementations available:
a) DefaultRmiModule
b) ProxyTrustModule
DefaultRmiModule can be trusted by the client without contacting any service -
it uses RequireDlPermissionClassProvider to load classes.
ProxyTrustModule on the other hand uses a simple PreferredClassProvider to
load classes. It is a smart proxy that implements getProxyTrustIterator() so
that it can be verified by ProxyTrustVerifier.
On the server before we can annotate our objects with modules we have to
register a Module that will be used as annotation.
If the server does not register any Module - DefaultRmiModule is going to be
used as annotation.
The server can register a ProxyTrustModule as annotation - to do that it first
must export an object that can be contacted to obtain a Module verifier.
In other words - a service must either:
a) export two ProxyTrusts (one for Modules and another one for the service
itself)
b) its ProxyTrust must provide a verifier that is able to verify both a Module
and a service proxy
To make it possible to use my code with existing services without modifying
them I've decided to implement a special ModuleExporter which will override
the service ServerProxyTrust implementation so that getProxyVerifier will
return a Verifier capable of verifying both a Module and the service proxy.
This verifier works as follows:
1. Check if an object being verified is a Module.
2. If so - delegate to a module verifier
3. If not it means we're verifying a service proxy so delegate to a default
verifier.
The problem is though that when this verifier is deserialized the module that
is capable of loading the service proxy verifier is not yet installed (the
client got this verifier to verify a Module before it can load any classes).
That's why I called it LazyCompositeVerifier - the default verifier is not
deserialized until it is actually needed.
The only problem left is that every time a client gets a service proxy it will
issue a remote call twice to get a verifier: first to get a verifier for a Module
and then to get a verifier for a service proxy. But it is going to be the same
verifier!!! So I've decided to implement a CachingProxyTrust that
1) can be trusted by the client without the need to issue any remote call (so
we need a CachingProxyTrustVerifier configured on the client)
2) Will cache a verifier it obtains from its delegate
The problem with CachingProxyTrust is that it has to be used by:
a) a Module
b) a service proxy
That's why we need OverrideProxy - it is returned from ModuleExporter to the
service so that the service is unaware of the CachingProxyTrust but still can
use it to obtain its verifier. To trust OverrideProxy the client has to have
OverrideProxyVerifier configured locally.
I hope I clarified everything a little bit...
Michal
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling
of smart proxy's
Posted by Peter Firmstone <ji...@zeus.net.au>.
Michal Kleczek wrote:
> On Tuesday 26 of October 2010 15:27:17 Peter Firmstone wrote:
>
>> Hi Michal,
>>
>> Sorry for taking time to respond, I've been busy and am still digesting
>> the code.
>>
>> Michal Kleczek wrote:
>>
>>> In my code there is a simple hack to force creating a different
>>> ClassLoader for each unique Module - before calling to a delegate
>>> RMIClassProviderSpi I set a TCCL to a new ClassLoader that is unique to
>>> the Module. (That is also the reason I had to provide a slightly
>>> modified version of BasicJeriTrustVerifier so that not the proxy
>>> ClassLoader but also its parent are verified) See AbstractRmiModule for
>>> details.
>>>
>>> Module uniqueness: two Modules are considered the same iff their equals
>>> returns true.
>>>
>>> In case of ProxyTrustModule (which is the most interesting) - two
>>> ProxyTrustModules are equal when their codebases are equal and their
>>> ProxyTrusts are equal. so for two different services - each providing its
>>> own ProxyTrust for Modules - we create two different ClassLoaders
>>> regardless of the codebases. (This is not based on Subject but on
>>> service proxy identity) Basing it on Subject would be a little tricky
>>> IMHO because actual service Principals are dependent on what the client
>>> requires.
>>>
>> Ok I see your point, we should be using service proxy identity, not the
>> Subject. A server might use a number of subjects. Since not all proxy's
>> are services, would it be better to use the BasicObjectEndpoint identity.
>>
>> ProxyTrust, doesn't by default implement equals or hashcode, if the
>> client is handed a reference to a remote object, that is a smart proxy,
>> from another client, it could end up with two separate instances if
>> ProxyTrust uses the default Object equals implementation.
>>
>> So thinking about it a little more, perhaps we could use the Uuid of the
>> BasicObjectEndpoint?
>>
>
> Hmm... I've checked BasicInvoationHandler and it implements equals for its
> proxies by (among other stuff) comparing object endpoints.
> So in basic scenario (when ProxyTrust is a simple Jeri proxy) all is fine.
> For smart proxies I would simply require "sensible" implementation of equals.
>
> It is in the interest of a service to provide a client with the right Module
> identity - otherwise the service just won't work properly (but it will not
> affect client's security). Equals for me seems to be the easiest and general
> enough. I wouldn't want to base it on some internal stuff since that would
> preclude Modules that are not Jeri based etc...
>
> Michal
>
>
Ok Interesting, anyone implementing a Service should be quite capable of
implementing equals, we should then specify that equals and hashcode
methods should be implemented for ProxyTrust.
For my benefit can you go over the process of how your new code works?
I'm interested in the choices you've made & why.
I still would like to wrap the ClassLoader in a GuardObject, this way
less trusted code (you don't want it to see the ClassLoader) cannot
obtain a ClassLoader reference, but it can delegate the functionality by
passing the GuardObject to more trusted code.
A little off topic, but based on what we can do if we solve the DOS
problem. I was just thinking today that we could create an Internet
Service Browser, that discovered any service available over the
internet, utilising ServiceUI, with which users can interact. Just like
Web servers and Web browsers, a River Service browser, wouldn't need to
implement service (unless it advertised trusted services perhaps), it
could be a lightweight app for minimal download. It would be the web
browser for services. This could be done using DNS-SD to discover
Unicast addresses of Lookup services. This would render the app store
model obsolete, anyone could advertise their service applications with
their own lookup service. It would blur the lines between applications
and internet web sites. We would also need delayed unmarshalling of
proxy's or partial unmarshalling (only deserialize Entry's) until the
desired service is found.
I'm wondering how we could use PGP Certificates web of trust and utilise
JAAS to associate with local Principals? Would these local Principals
have standard names, representing levels of trust? For maximum trust
you would expect the Service to authenticate with all these Principals.
How could we authenticate the Service with these principals?
If a friend trusts and uses a service, can we use and trust that service
too? Might that trust be the number of Principals our friends
authenticates the service with? Or would we use a lesser trust? Could
this be a role of an extended lookup service, to find services that have
some kind of trust relationship? Or would it be some kind of trust service?
If we can spell out these trust levels, then the service implementer
knows which Principals are needed to gain certain permissions. These
principal based permission grants could be configured by default in the
client.
Services might also expect clients to authenticate with these services.
Any ideas?
Thanks,
Peter.
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling of smart proxy's
Posted by Michal Kleczek <mi...@xpro.biz>.
On Tuesday 26 of October 2010 15:27:17 Peter Firmstone wrote:
> Hi Michal,
>
> Sorry for taking time to respond, I've been busy and am still digesting
> the code.
>
> Michal Kleczek wrote:
> > In my code there is a simple hack to force creating a different
> > ClassLoader for each unique Module - before calling to a delegate
> > RMIClassProviderSpi I set a TCCL to a new ClassLoader that is unique to
> > the Module. (That is also the reason I had to provide a slightly
> > modified version of BasicJeriTrustVerifier so that not the proxy
> > ClassLoader but also its parent are verified) See AbstractRmiModule for
> > details.
> >
> > Module uniqueness: two Modules are considered the same iff their equals
> > returns true.
> >
> > In case of ProxyTrustModule (which is the most interesting) - two
> > ProxyTrustModules are equal when their codebases are equal and their
> > ProxyTrusts are equal. so for two different services - each providing its
> > own ProxyTrust for Modules - we create two different ClassLoaders
> > regardless of the codebases. (This is not based on Subject but on
> > service proxy identity) Basing it on Subject would be a little tricky
> > IMHO because actual service Principals are dependent on what the client
> > requires.
>
> Ok I see your point, we should be using service proxy identity, not the
> Subject. A server might use a number of subjects. Since not all proxy's
> are services, would it be better to use the BasicObjectEndpoint identity.
>
> ProxyTrust, doesn't by default implement equals or hashcode, if the
> client is handed a reference to a remote object, that is a smart proxy,
> from another client, it could end up with two separate instances if
> ProxyTrust uses the default Object equals implementation.
>
> So thinking about it a little more, perhaps we could use the Uuid of the
> BasicObjectEndpoint?
Hmm... I've checked BasicInvoationHandler and it implements equals for its
proxies by (among other stuff) comparing object endpoints.
So in basic scenario (when ProxyTrust is a simple Jeri proxy) all is fine.
For smart proxies I would simply require "sensible" implementation of equals.
It is in the interest of a service to provide a client with the right Module
identity - otherwise the service just won't work properly (but it will not
affect client's security). Equals for me seems to be the easiest and general
enough. I wouldn't want to base it on some internal stuff since that would
preclude Modules that are not Jeri based etc...
Michal
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling of smart proxy's
Posted by Michal Kleczek <mi...@xpro.biz>.
Changed package names to org.apache.river.modules.
Added Apache licence headers to source files (BTW - found a pretty cool Maven
plugin to do it).
Attached zipped source to Jira item.
Regards,
Michal
On Tuesday 19 of October 2010 10:13:27 Peter Firmstone wrote:
> Michal Kleczek wrote:
> > I will.
> > Just let me know if I should change package names, add licence note to
> > source files etc.
>
> Yes add the apache license header to each file.
>
> > And what is the policy of using external libraries. This code uses:
> > 1. commons-codec - which is Apache project
> > 2. Google Code Guava (formerly Google Collections) - which is not Apache
> > but its licence is Apache Licence
>
> We can distribute the binary lib jar's in these cases.
>
> > Regards,
> > Michal
> >
> > On Tuesday 19 of October 2010 09:44:14 Peter Firmstone wrote:
> >> Hi Michal,
> >>
> >> If you upload the code to Jira, I'll create a place on svn where we can
> >> all explore & contribute patches etc.
> >>
> >> Cheers,
> >>
> >> Peter.
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling
of smart proxy's
Posted by Peter Firmstone <ji...@zeus.net.au>.
Michal Kleczek wrote:
> I will.
> Just let me know if I should change package names, add licence note to source
> files etc.
>
Yes add the apache license header to each file.
> And what is the policy of using external libraries. This code uses:
> 1. commons-codec - which is Apache project
> 2. Google Code Guava (formerly Google Collections) - which is not Apache but
> its licence is Apache Licence
>
We can distribute the binary lib jar's in these cases.
> Regards,
> Michal
>
> On Tuesday 19 of October 2010 09:44:14 Peter Firmstone wrote:
>
>> Hi Michal,
>>
>> If you upload the code to Jira, I'll create a place on svn where we can
>> all explore & contribute patches etc.
>>
>> Cheers,
>>
>> Peter.
>>
>>
>
>
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling of smart proxy's
Posted by Michal Kleczek <mi...@xpro.biz>.
I will.
Just let me know if I should change package names, add licence note to source
files etc.
And what is the policy of using external libraries. This code uses:
1. commons-codec - which is Apache project
2. Google Code Guava (formerly Google Collections) - which is not Apache but
its licence is Apache Licence
Regards,
Michal
On Tuesday 19 of October 2010 09:44:14 Peter Firmstone wrote:
> Hi Michal,
>
> If you upload the code to Jira, I'll create a place on svn where we can
> all explore & contribute patches etc.
>
> Cheers,
>
> Peter.
>
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling
of smart proxy's
Posted by Peter Firmstone <ji...@zeus.net.au>.
Hi Michal,
If you upload the code to Jira, I'll create a place on svn where we can
all explore & contribute patches etc.
Cheers,
Peter.
Michal Kleczek wrote:
> In my code there is a simple hack to force creating a different ClassLoader for
> each unique Module - before calling to a delegate RMIClassProviderSpi I set a
> TCCL to a new ClassLoader that is unique to the Module. (That is also the
> reason I had to provide a slightly modified version of BasicJeriTrustVerifier so
> that not the proxy ClassLoader but also its parent are verified)
> See AbstractRmiModule for details.
>
> Module uniqueness: two Modules are considered the same iff their equals returns
> true.
>
> In case of ProxyTrustModule (which is the most interesting) - two
> ProxyTrustModules are equal when their codebases are equal and their
> ProxyTrusts are equal. so for two different services - each providing its own
> ProxyTrust for Modules - we create two different ClassLoaders regardless of the
> codebases. (This is not based on Subject but on service proxy identity)
> Basing it on Subject would be a little tricky IMHO because actual service
> Principals are dependent on what the client requires.
>
> We can sign codebases using SignedRmiModule which - beside codebase - carries
> signature information with it and can be verified locally by
> SignedRmiModuleVerifier (not yet finished). I also thought about delegating
> signature verification work to a (remote) service that would be carried by
> SignedRmiModule and verified for trust before used by the client to verify the
> actual signature.
>
> The whole design was based on Jini 2.1 so no dynamic CodeBase grants are
> necessary.
>
> Regards,
> Michal
>
> On Tuesday 19 of October 2010 03:10:50 Peter Firmstone wrote:
>
>> Michal,
>>
>> You compose an incredible amount of code in a very short time, I haven't
>> yet digested it.
>>
>> I'm still trying to figure out how a Service proxy's namespace can be
>> restricted to a single Subject (the Service authenticates itself with).
>>
>> To avoid security vulnerabilities, caused by shared class state.
>>
>> Classes within a ClassLoader belonging to a particular Service should
>> have no visibility outside their ClassLoader, external classes should
>> only be able to interact via Service API, they shouldn't be able to
>> create objects using constructors from within the service proxy's
>> namespace. The Service proxy needs to have isolated visibility.
>>
>> Objects within the proxy's private namespace are constructed during
>> deserialization.
>>
>> We could require that a proxy codebase must be signed, we could also
>> require that the Subject, when it authenticates has the same Certificate
>> as the codebase. Since Certificate's have chains of trust, which can
>> grow longer, it would only be the first Certificate in each
>> Certificate[] array (Subject and CodeSource) that would be checked.
>>
>> Using Codebase Certificate's has an advantage over message digests
>> because the implementation can change.
>>
>> After a smart proxy has been unmarshalled, if it is discovered that the
>> Certificates don't match, this indicates the proxy has been downloaded
>> into the wrong namespace, this proxy can be safely discarded.
>>
>> Cheers,
>>
>> Peter.
>>
>> Michal Kleczek wrote:
>>
>>> Folks,
>>>
>>> I've managed to create a prototype implementation of the idea of
>>> annotating classes with Modules.
>>> Working on this allowed me to learn quite a lot about inner workings of
>>> River - the original implementation that I've presented before had to be
>>> modified (not saying it had to be fixed :) ) but the main idea stayed
>>> the same. This time I think it really covers more use cases.
>>>
>>> Shortly:
>>> 1. We allow annotating classes with Modules. A Module is an object
>>> responsible for loading classes.
>>> 2. There is a new RMIClassLoaderSpi implementation which I called
>>> ModuleClassProvider
>>> 3. ModuleClassProvider manages installed Modules
>>> 4. It also can load classes based on String annotations which are
>>> expected to be either
>>> a) serialized and Base64 encoded Module - the Module is deserialized and
>>> handled as any other Module annotation
>>> b) an old style list of URLs - class loading is delegated to
>>> RequireDlPermProvider - in other words we either load classes from
>>> Modules (which are verified for trust before use) or from URLs but then
>>> we require appropriate DownloadPermissions
>>>
>>> Attached is a multi-module maven project. The modules are:
>>> 1. secure-marshall-stream (which is the implementation of all this + some
>>> not yet finished additional code)
>>> 2. jsk-module-platform which contains modified Jini classes so that it
>>> all works with existing Jini services (to be honest only ClassLoading
>>> really needed to change.
>>> MarshalInputStream/MarshalOutputStream/MarshalledInstance are changed
>>> only to avoid having serialized and Base64 encoded Modules as
>>> annotations
>>>
>>> To run it you need to put jsk-module-platform before jsk-platform on the
>>> classpath (and of course add secure-marshall-stream as well)
>>>
>>> Existing services can be exported with a ModuleExporter:
>>> private serviceILFactory =
>>>
>>> new ProxyTrustILFactory(serviceConstraints,
>>>
>>> RegistrarPermission.class);
>>>
>>> private moduleTrustILFactory =
>>>
>>> new ModuleTrustILFactory(serviceConstraints,
>>>
>>> null);
>>>
>>> serverExporter = new ModuleExporter(new
>>> BasicJeriExporter(serviceEndpoint,
>>>
>>> serviceILFactory), new BasicJeriExporter(serviceEndpoint,
>>> moduleTrustILFactory));
>>>
>>> I've done some basic scenario testing which was running Reggie and
>>> Service Browser installed by Jini 2.1 installer. Both Browser and Reggie
>>> policies did not grant any DownloadPermissions.
>>> When exported with BasicJeriExporter lookup of ServiceRegistrar by the
>>> Browser failed with missing DownloadPermission.
>>> When exported with ModuleExporter both Reggie and Browser used
>>> ProxyTrustVerifier to verifify Modules.
>>>
>>> Note - this is strictly a prototype - no comments / junit tests / code
>>> reviews and no real testing.
>>>
>>> If you have any questions / comments - you're very welcome.
>>>
>>> Michal
>>>
>>> On Monday 18 of October 2010 03:08:38 Peter Firmstone wrote:
>>>
>>>> Notes for fix:
>>>>
>>>> DownloadPermission protects against unauthenticated downloads
>>>> ClassLoadingPermission - new Permission to protect against
>>>> unauthenticated Class loading.
>>>>
>>>> Issues we're addressing in the DOS hole:
>>>> * Eliminate unauthenticated URL downloads.
>>>> * Eliminate unmarshalling of unauthenticated code.
>>>> * Eliminate execution of unauthenticated code.
>>>> * Eliminate StackOverflowError's in the client thread, caused by
>>>>
>>>> sending spurious garbage over InputStream's.
>>>>
>>>> * Eliminate StackOverflowError's in the client thread, caused by
>>>>
>>>> substituted jar files or URL's from DNS cache poisoning attacks
>>>> etc.
>>>>
>>>> How?
>>>>
>>>> * Delay granting DownloadPermission, until remote endpoint has
>>>>
>>>> authenticated itself, we trust the remote endpoint to advise a
>>>> suitable URL, if it authenticates.
>>>>
>>>> * Authentication by annotating a reflective proxy (additional to the
>>>>
>>>> Codebase String) from the remote endpoint, used for authentication
>>>> and to provide CodeSource Certificate[]'s. This may be different
>>>> to the Service, if a remote object is marshalled elsewhere (eg
>>>> another client).
>>>>
>>>> * Delay granting ClassLoadingPermission, until remote endpoint has
>>>>
>>>> authenticated itself and has provided the expected CodeSource
>>>> Certificate[]'s
>>>>
>>>> * Perform unmarshalling in a controlled ExecutorService thread.
>>>>
>>>> So all we're doing different is authenticating the remote end and if it
>>>> authenticates permit downloading and classloading.
>>>>
>>>> There is one more scenario to consider, currently this is a mechanism to
>>>> protect against download and deserialization of unknown code for smart
>>>> proxy's. But what about Service that only use reflective proxy's and
>>>> don't require downloaded code?
>>>>
>>>> But what if we don't want to grant download permission or class loading
>>>> permission to a Subject we authenticate?
>>>>
>>>> Currently the unmarshalling code doesn't run as the Subject after
>>>> authentication, this means the Permission grant's are only dependent on
>>>> authentication, something Michal pointed out earlier when this was
>>>> proposed.
>>>>
>>>> Now this code can be easily changed so the granting permission operation
>>>> is run as the Subject after authentication, this would allow us to
>>>> distinguish between different Subjects.
>>>>
>>>> The drawback is that performance won't be as good, but it seems the most
>>>> logical and powerful approach.
>>>>
>>>> What do you think?
>>>>
>>>> There is one last obstacle, if Certificates are used to sign the jar
>>>> files, how do you effectively prevent one Subject from using another
>>>> Subject's signed CodeSource's if Code signing is used for isolation of
>>>> separate Subjects namespaces? A service could deliberately attempt to
>>>> occupy the same namespace as another Service to attempt to gain
>>>> information via shared static variables. We need to prevent this
>>>> occurring.
>>>>
>>>> This has to be done with the ClassLoader, but during unmarshalling, the
>>>> service proxy has not yet been verified. The authentication proxy
>>>> delivered with the MarshalInputStream may not have the same Subject as
>>>> the Service, it could be a third party.
>>>>
>>>> Could it be that when the smart proxy is unmarshalled, and executed as
>>>> it's Subject, it must contain a Certificate matching the signer of the
>>>> Codebase?
>>>>
>>>> We're on the cusp of solving this problem, thoughts?
>>>>
>>>> Cheers,
>>>>
>>>> Peter.
>>>>
>>>> Peter Firmstone (JIRA) wrote:
>>>>
>>>>> Denial of Service during unmarshalling of smart proxy's
>>>>> -------------------------------------------------------
>>>>>
>>>>> Key: RIVER-362
>>>>> URL: https://issues.apache.org/jira/browse/RIVER-362
>>>>>
>>>>> Project: River
>>>>>
>>>>> Issue Type: Bug
>>>>>
>>>>> Environment: Untrusted networks
>>>>>
>>>>> Reporter: Peter Firmstone
>>>>>
>>>>> During unmarshalling of smart proxy's there's a period before the proxy
>>>>> has been verified (authenticated) where deserialization methods are
>>>>> executed on untrusted code, the potential exists for untrusted code to
>>>>> perform denial of service.
>>>>>
>
>
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling
of smart proxy's
Posted by Peter Firmstone <ji...@zeus.net.au>.
Hi Michal,
Sorry for taking time to respond, I've been busy and am still digesting
the code.
Michal Kleczek wrote:
> In my code there is a simple hack to force creating a different ClassLoader for
> each unique Module - before calling to a delegate RMIClassProviderSpi I set a
> TCCL to a new ClassLoader that is unique to the Module. (That is also the
> reason I had to provide a slightly modified version of BasicJeriTrustVerifier so
> that not the proxy ClassLoader but also its parent are verified)
> See AbstractRmiModule for details.
>
> Module uniqueness: two Modules are considered the same iff their equals returns
> true.
>
> In case of ProxyTrustModule (which is the most interesting) - two
> ProxyTrustModules are equal when their codebases are equal and their
> ProxyTrusts are equal. so for two different services - each providing its own
> ProxyTrust for Modules - we create two different ClassLoaders regardless of the
> codebases. (This is not based on Subject but on service proxy identity)
> Basing it on Subject would be a little tricky IMHO because actual service
> Principals are dependent on what the client requires.
>
Ok I see your point, we should be using service proxy identity, not the
Subject. A server might use a number of subjects. Since not all proxy's
are services, would it be better to use the BasicObjectEndpoint identity.
ProxyTrust, doesn't by default implement equals or hashcode, if the
client is handed a reference to a remote object, that is a smart proxy,
from another client, it could end up with two separate instances if
ProxyTrust uses the default Object equals implementation.
So thinking about it a little more, perhaps we could use the Uuid of the
BasicObjectEndpoint?
Doing so has a significant drawback, limiting sharing of common bytecode.
If we weren't worried about security, for efficiency reasons we'd keep
all services with identical code in the same ClassLoader, or name space,
the security risk is the service proxy object of one provider could
communicate with another with different privileges using class variables.
Another reason for not using the Subject, even if there was no immediate
security risk due to sharing of class variables, the services within the
ProtectionDomain must have identical permissions, under identical
circumstances, but because all proxy's cannot be discovered and verified
at the same time, this would not be easily possible.
So it might be wise to remain on the conservative side and designate a
ClassLoader for each unique remote object, and cache codebases, to
reduce downloading.
Regards,
Peter.
> We can sign codebases using SignedRmiModule which - beside codebase - carries
> signature information with it and can be verified locally by
> SignedRmiModuleVerifier (not yet finished). I also thought about delegating
> signature verification work to a (remote) service that would be carried by
> SignedRmiModule and verified for trust before used by the client to verify the
> actual signature.
>
> The whole design was based on Jini 2.1 so no dynamic CodeBase grants are
> necessary.
>
> Regards,
> Michal
>
> On Tuesday 19 of October 2010 03:10:50 Peter Firmstone wrote:
>
>> Michal,
>>
>> You compose an incredible amount of code in a very short time, I haven't
>> yet digested it.
>>
>> I'm still trying to figure out how a Service proxy's namespace can be
>> restricted to a single Subject (the Service authenticates itself with).
>>
>> To avoid security vulnerabilities, caused by shared class state.
>>
>> Classes within a ClassLoader belonging to a particular Service should
>> have no visibility outside their ClassLoader, external classes should
>> only be able to interact via Service API, they shouldn't be able to
>> create objects using constructors from within the service proxy's
>> namespace. The Service proxy needs to have isolated visibility.
>>
>> Objects within the proxy's private namespace are constructed during
>> deserialization.
>>
>> We could require that a proxy codebase must be signed, we could also
>> require that the Subject, when it authenticates has the same Certificate
>> as the codebase. Since Certificate's have chains of trust, which can
>> grow longer, it would only be the first Certificate in each
>> Certificate[] array (Subject and CodeSource) that would be checked.
>>
>> Using Codebase Certificate's has an advantage over message digests
>> because the implementation can change.
>>
>> After a smart proxy has been unmarshalled, if it is discovered that the
>> Certificates don't match, this indicates the proxy has been downloaded
>> into the wrong namespace, this proxy can be safely discarded.
>>
>> Cheers,
>>
>> Peter.
>>
>> Michal Kleczek wrote:
>>
>>> Folks,
>>>
>>> I've managed to create a prototype implementation of the idea of
>>> annotating classes with Modules.
>>> Working on this allowed me to learn quite a lot about inner workings of
>>> River - the original implementation that I've presented before had to be
>>> modified (not saying it had to be fixed :) ) but the main idea stayed
>>> the same. This time I think it really covers more use cases.
>>>
>>> Shortly:
>>> 1. We allow annotating classes with Modules. A Module is an object
>>> responsible for loading classes.
>>> 2. There is a new RMIClassLoaderSpi implementation which I called
>>> ModuleClassProvider
>>> 3. ModuleClassProvider manages installed Modules
>>> 4. It also can load classes based on String annotations which are
>>> expected to be either
>>> a) serialized and Base64 encoded Module - the Module is deserialized and
>>> handled as any other Module annotation
>>> b) an old style list of URLs - class loading is delegated to
>>> RequireDlPermProvider - in other words we either load classes from
>>> Modules (which are verified for trust before use) or from URLs but then
>>> we require appropriate DownloadPermissions
>>>
>>> Attached is a multi-module maven project. The modules are:
>>> 1. secure-marshall-stream (which is the implementation of all this + some
>>> not yet finished additional code)
>>> 2. jsk-module-platform which contains modified Jini classes so that it
>>> all works with existing Jini services (to be honest only ClassLoading
>>> really needed to change.
>>> MarshalInputStream/MarshalOutputStream/MarshalledInstance are changed
>>> only to avoid having serialized and Base64 encoded Modules as
>>> annotations
>>>
>>> To run it you need to put jsk-module-platform before jsk-platform on the
>>> classpath (and of course add secure-marshall-stream as well)
>>>
>>> Existing services can be exported with a ModuleExporter:
>>> private serviceILFactory =
>>>
>>> new ProxyTrustILFactory(serviceConstraints,
>>>
>>> RegistrarPermission.class);
>>>
>>> private moduleTrustILFactory =
>>>
>>> new ModuleTrustILFactory(serviceConstraints,
>>>
>>> null);
>>>
>>> serverExporter = new ModuleExporter(new
>>> BasicJeriExporter(serviceEndpoint,
>>>
>>> serviceILFactory), new BasicJeriExporter(serviceEndpoint,
>>> moduleTrustILFactory));
>>>
>>> I've done some basic scenario testing which was running Reggie and
>>> Service Browser installed by Jini 2.1 installer. Both Browser and Reggie
>>> policies did not grant any DownloadPermissions.
>>> When exported with BasicJeriExporter lookup of ServiceRegistrar by the
>>> Browser failed with missing DownloadPermission.
>>> When exported with ModuleExporter both Reggie and Browser used
>>> ProxyTrustVerifier to verifify Modules.
>>>
>>> Note - this is strictly a prototype - no comments / junit tests / code
>>> reviews and no real testing.
>>>
>>> If you have any questions / comments - you're very welcome.
>>>
>>> Michal
>>>
>>> On Monday 18 of October 2010 03:08:38 Peter Firmstone wrote:
>>>
>>>> Notes for fix:
>>>>
>>>> DownloadPermission protects against unauthenticated downloads
>>>> ClassLoadingPermission - new Permission to protect against
>>>> unauthenticated Class loading.
>>>>
>>>> Issues we're addressing in the DOS hole:
>>>> * Eliminate unauthenticated URL downloads.
>>>> * Eliminate unmarshalling of unauthenticated code.
>>>> * Eliminate execution of unauthenticated code.
>>>> * Eliminate StackOverflowError's in the client thread, caused by
>>>>
>>>> sending spurious garbage over InputStream's.
>>>>
>>>> * Eliminate StackOverflowError's in the client thread, caused by
>>>>
>>>> substituted jar files or URL's from DNS cache poisoning attacks
>>>> etc.
>>>>
>>>> How?
>>>>
>>>> * Delay granting DownloadPermission, until remote endpoint has
>>>>
>>>> authenticated itself, we trust the remote endpoint to advise a
>>>> suitable URL, if it authenticates.
>>>>
>>>> * Authentication by annotating a reflective proxy (additional to the
>>>>
>>>> Codebase String) from the remote endpoint, used for authentication
>>>> and to provide CodeSource Certificate[]'s. This may be different
>>>> to the Service, if a remote object is marshalled elsewhere (eg
>>>> another client).
>>>>
>>>> * Delay granting ClassLoadingPermission, until remote endpoint has
>>>>
>>>> authenticated itself and has provided the expected CodeSource
>>>> Certificate[]'s
>>>>
>>>> * Perform unmarshalling in a controlled ExecutorService thread.
>>>>
>>>> So all we're doing different is authenticating the remote end and if it
>>>> authenticates permit downloading and classloading.
>>>>
>>>> There is one more scenario to consider, currently this is a mechanism to
>>>> protect against download and deserialization of unknown code for smart
>>>> proxy's. But what about Service that only use reflective proxy's and
>>>> don't require downloaded code?
>>>>
>>>> But what if we don't want to grant download permission or class loading
>>>> permission to a Subject we authenticate?
>>>>
>>>> Currently the unmarshalling code doesn't run as the Subject after
>>>> authentication, this means the Permission grant's are only dependent on
>>>> authentication, something Michal pointed out earlier when this was
>>>> proposed.
>>>>
>>>> Now this code can be easily changed so the granting permission operation
>>>> is run as the Subject after authentication, this would allow us to
>>>> distinguish between different Subjects.
>>>>
>>>> The drawback is that performance won't be as good, but it seems the most
>>>> logical and powerful approach.
>>>>
>>>> What do you think?
>>>>
>>>> There is one last obstacle, if Certificates are used to sign the jar
>>>> files, how do you effectively prevent one Subject from using another
>>>> Subject's signed CodeSource's if Code signing is used for isolation of
>>>> separate Subjects namespaces? A service could deliberately attempt to
>>>> occupy the same namespace as another Service to attempt to gain
>>>> information via shared static variables. We need to prevent this
>>>> occurring.
>>>>
>>>> This has to be done with the ClassLoader, but during unmarshalling, the
>>>> service proxy has not yet been verified. The authentication proxy
>>>> delivered with the MarshalInputStream may not have the same Subject as
>>>> the Service, it could be a third party.
>>>>
>>>> Could it be that when the smart proxy is unmarshalled, and executed as
>>>> it's Subject, it must contain a Certificate matching the signer of the
>>>> Codebase?
>>>>
>>>> We're on the cusp of solving this problem, thoughts?
>>>>
>>>> Cheers,
>>>>
>>>> Peter.
>>>>
>>>> Peter Firmstone (JIRA) wrote:
>>>>
>>>>> Denial of Service during unmarshalling of smart proxy's
>>>>> -------------------------------------------------------
>>>>>
>>>>> Key: RIVER-362
>>>>> URL: https://issues.apache.org/jira/browse/RIVER-362
>>>>>
>>>>> Project: River
>>>>>
>>>>> Issue Type: Bug
>>>>>
>>>>> Environment: Untrusted networks
>>>>>
>>>>> Reporter: Peter Firmstone
>>>>>
>>>>> During unmarshalling of smart proxy's there's a period before the proxy
>>>>> has been verified (authenticated) where deserialization methods are
>>>>> executed on untrusted code, the potential exists for untrusted code to
>>>>> perform denial of service.
>>>>>
>
>
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling of smart proxy's
Posted by Michal Kleczek <mi...@xpro.biz>.
In my code there is a simple hack to force creating a different ClassLoader for
each unique Module - before calling to a delegate RMIClassProviderSpi I set a
TCCL to a new ClassLoader that is unique to the Module. (That is also the
reason I had to provide a slightly modified version of BasicJeriTrustVerifier so
that not the proxy ClassLoader but also its parent are verified)
See AbstractRmiModule for details.
Module uniqueness: two Modules are considered the same iff their equals returns
true.
In case of ProxyTrustModule (which is the most interesting) - two
ProxyTrustModules are equal when their codebases are equal and their
ProxyTrusts are equal. so for two different services - each providing its own
ProxyTrust for Modules - we create two different ClassLoaders regardless of the
codebases. (This is not based on Subject but on service proxy identity)
Basing it on Subject would be a little tricky IMHO because actual service
Principals are dependent on what the client requires.
We can sign codebases using SignedRmiModule which - beside codebase - carries
signature information with it and can be verified locally by
SignedRmiModuleVerifier (not yet finished). I also thought about delegating
signature verification work to a (remote) service that would be carried by
SignedRmiModule and verified for trust before used by the client to verify the
actual signature.
The whole design was based on Jini 2.1 so no dynamic CodeBase grants are
necessary.
Regards,
Michal
On Tuesday 19 of October 2010 03:10:50 Peter Firmstone wrote:
> Michal,
>
> You compose an incredible amount of code in a very short time, I haven't
> yet digested it.
>
> I'm still trying to figure out how a Service proxy's namespace can be
> restricted to a single Subject (the Service authenticates itself with).
>
> To avoid security vulnerabilities, caused by shared class state.
>
> Classes within a ClassLoader belonging to a particular Service should
> have no visibility outside their ClassLoader, external classes should
> only be able to interact via Service API, they shouldn't be able to
> create objects using constructors from within the service proxy's
> namespace. The Service proxy needs to have isolated visibility.
>
> Objects within the proxy's private namespace are constructed during
> deserialization.
>
> We could require that a proxy codebase must be signed, we could also
> require that the Subject, when it authenticates has the same Certificate
> as the codebase. Since Certificate's have chains of trust, which can
> grow longer, it would only be the first Certificate in each
> Certificate[] array (Subject and CodeSource) that would be checked.
>
> Using Codebase Certificate's has an advantage over message digests
> because the implementation can change.
>
> After a smart proxy has been unmarshalled, if it is discovered that the
> Certificates don't match, this indicates the proxy has been downloaded
> into the wrong namespace, this proxy can be safely discarded.
>
> Cheers,
>
> Peter.
>
> Michal Kleczek wrote:
> > Folks,
> >
> > I've managed to create a prototype implementation of the idea of
> > annotating classes with Modules.
> > Working on this allowed me to learn quite a lot about inner workings of
> > River - the original implementation that I've presented before had to be
> > modified (not saying it had to be fixed :) ) but the main idea stayed
> > the same. This time I think it really covers more use cases.
> >
> > Shortly:
> > 1. We allow annotating classes with Modules. A Module is an object
> > responsible for loading classes.
> > 2. There is a new RMIClassLoaderSpi implementation which I called
> > ModuleClassProvider
> > 3. ModuleClassProvider manages installed Modules
> > 4. It also can load classes based on String annotations which are
> > expected to be either
> > a) serialized and Base64 encoded Module - the Module is deserialized and
> > handled as any other Module annotation
> > b) an old style list of URLs - class loading is delegated to
> > RequireDlPermProvider - in other words we either load classes from
> > Modules (which are verified for trust before use) or from URLs but then
> > we require appropriate DownloadPermissions
> >
> > Attached is a multi-module maven project. The modules are:
> > 1. secure-marshall-stream (which is the implementation of all this + some
> > not yet finished additional code)
> > 2. jsk-module-platform which contains modified Jini classes so that it
> > all works with existing Jini services (to be honest only ClassLoading
> > really needed to change.
> > MarshalInputStream/MarshalOutputStream/MarshalledInstance are changed
> > only to avoid having serialized and Base64 encoded Modules as
> > annotations
> >
> > To run it you need to put jsk-module-platform before jsk-platform on the
> > classpath (and of course add secure-marshall-stream as well)
> >
> > Existing services can be exported with a ModuleExporter:
> > private serviceILFactory =
> >
> > new ProxyTrustILFactory(serviceConstraints,
> >
> > RegistrarPermission.class);
> >
> > private moduleTrustILFactory =
> >
> > new ModuleTrustILFactory(serviceConstraints,
> >
> > null);
> >
> > serverExporter = new ModuleExporter(new
> > BasicJeriExporter(serviceEndpoint,
> >
> > serviceILFactory), new BasicJeriExporter(serviceEndpoint,
> > moduleTrustILFactory));
> >
> > I've done some basic scenario testing which was running Reggie and
> > Service Browser installed by Jini 2.1 installer. Both Browser and Reggie
> > policies did not grant any DownloadPermissions.
> > When exported with BasicJeriExporter lookup of ServiceRegistrar by the
> > Browser failed with missing DownloadPermission.
> > When exported with ModuleExporter both Reggie and Browser used
> > ProxyTrustVerifier to verifify Modules.
> >
> > Note - this is strictly a prototype - no comments / junit tests / code
> > reviews and no real testing.
> >
> > If you have any questions / comments - you're very welcome.
> >
> > Michal
> >
> > On Monday 18 of October 2010 03:08:38 Peter Firmstone wrote:
> >> Notes for fix:
> >>
> >> DownloadPermission protects against unauthenticated downloads
> >> ClassLoadingPermission - new Permission to protect against
> >> unauthenticated Class loading.
> >>
> >> Issues we're addressing in the DOS hole:
> >> * Eliminate unauthenticated URL downloads.
> >> * Eliminate unmarshalling of unauthenticated code.
> >> * Eliminate execution of unauthenticated code.
> >> * Eliminate StackOverflowError's in the client thread, caused by
> >>
> >> sending spurious garbage over InputStream's.
> >>
> >> * Eliminate StackOverflowError's in the client thread, caused by
> >>
> >> substituted jar files or URL's from DNS cache poisoning attacks
> >> etc.
> >>
> >> How?
> >>
> >> * Delay granting DownloadPermission, until remote endpoint has
> >>
> >> authenticated itself, we trust the remote endpoint to advise a
> >> suitable URL, if it authenticates.
> >>
> >> * Authentication by annotating a reflective proxy (additional to the
> >>
> >> Codebase String) from the remote endpoint, used for authentication
> >> and to provide CodeSource Certificate[]'s. This may be different
> >> to the Service, if a remote object is marshalled elsewhere (eg
> >> another client).
> >>
> >> * Delay granting ClassLoadingPermission, until remote endpoint has
> >>
> >> authenticated itself and has provided the expected CodeSource
> >> Certificate[]'s
> >>
> >> * Perform unmarshalling in a controlled ExecutorService thread.
> >>
> >> So all we're doing different is authenticating the remote end and if it
> >> authenticates permit downloading and classloading.
> >>
> >> There is one more scenario to consider, currently this is a mechanism to
> >> protect against download and deserialization of unknown code for smart
> >> proxy's. But what about Service that only use reflective proxy's and
> >> don't require downloaded code?
> >>
> >> But what if we don't want to grant download permission or class loading
> >> permission to a Subject we authenticate?
> >>
> >> Currently the unmarshalling code doesn't run as the Subject after
> >> authentication, this means the Permission grant's are only dependent on
> >> authentication, something Michal pointed out earlier when this was
> >> proposed.
> >>
> >> Now this code can be easily changed so the granting permission operation
> >> is run as the Subject after authentication, this would allow us to
> >> distinguish between different Subjects.
> >>
> >> The drawback is that performance won't be as good, but it seems the most
> >> logical and powerful approach.
> >>
> >> What do you think?
> >>
> >> There is one last obstacle, if Certificates are used to sign the jar
> >> files, how do you effectively prevent one Subject from using another
> >> Subject's signed CodeSource's if Code signing is used for isolation of
> >> separate Subjects namespaces? A service could deliberately attempt to
> >> occupy the same namespace as another Service to attempt to gain
> >> information via shared static variables. We need to prevent this
> >> occurring.
> >>
> >> This has to be done with the ClassLoader, but during unmarshalling, the
> >> service proxy has not yet been verified. The authentication proxy
> >> delivered with the MarshalInputStream may not have the same Subject as
> >> the Service, it could be a third party.
> >>
> >> Could it be that when the smart proxy is unmarshalled, and executed as
> >> it's Subject, it must contain a Certificate matching the signer of the
> >> Codebase?
> >>
> >> We're on the cusp of solving this problem, thoughts?
> >>
> >> Cheers,
> >>
> >> Peter.
> >>
> >> Peter Firmstone (JIRA) wrote:
> >>> Denial of Service during unmarshalling of smart proxy's
> >>> -------------------------------------------------------
> >>>
> >>> Key: RIVER-362
> >>> URL: https://issues.apache.org/jira/browse/RIVER-362
> >>>
> >>> Project: River
> >>>
> >>> Issue Type: Bug
> >>>
> >>> Environment: Untrusted networks
> >>>
> >>> Reporter: Peter Firmstone
> >>>
> >>> During unmarshalling of smart proxy's there's a period before the proxy
> >>> has been verified (authenticated) where deserialization methods are
> >>> executed on untrusted code, the potential exists for untrusted code to
> >>> perform denial of service.
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling
of smart proxy's
Posted by Peter Firmstone <ji...@zeus.net.au>.
Michal,
You compose an incredible amount of code in a very short time, I haven't
yet digested it.
I'm still trying to figure out how a Service proxy's namespace can be
restricted to a single Subject (the Service authenticates itself with).
To avoid security vulnerabilities, caused by shared class state.
Classes within a ClassLoader belonging to a particular Service should
have no visibility outside their ClassLoader, external classes should
only be able to interact via Service API, they shouldn't be able to
create objects using constructors from within the service proxy's
namespace. The Service proxy needs to have isolated visibility.
Objects within the proxy's private namespace are constructed during
deserialization.
We could require that a proxy codebase must be signed, we could also
require that the Subject, when it authenticates has the same Certificate
as the codebase. Since Certificate's have chains of trust, which can
grow longer, it would only be the first Certificate in each
Certificate[] array (Subject and CodeSource) that would be checked.
Using Codebase Certificate's has an advantage over message digests
because the implementation can change.
After a smart proxy has been unmarshalled, if it is discovered that the
Certificates don't match, this indicates the proxy has been downloaded
into the wrong namespace, this proxy can be safely discarded.
Cheers,
Peter.
Michal Kleczek wrote:
> Folks,
>
> I've managed to create a prototype implementation of the idea of annotating
> classes with Modules.
> Working on this allowed me to learn quite a lot about inner workings of River
> - the original implementation that I've presented before had to be modified
> (not saying it had to be fixed :) ) but the main idea stayed the same. This
> time I think it really covers more use cases.
>
> Shortly:
> 1. We allow annotating classes with Modules. A Module is an object responsible
> for loading classes.
> 2. There is a new RMIClassLoaderSpi implementation which I called
> ModuleClassProvider
> 3. ModuleClassProvider manages installed Modules
> 4. It also can load classes based on String annotations which are expected to
> be either
> a) serialized and Base64 encoded Module - the Module is deserialized and
> handled as any other Module annotation
> b) an old style list of URLs - class loading is delegated to
> RequireDlPermProvider - in other words we either load classes from Modules
> (which are verified for trust before use) or from URLs but then we require
> appropriate DownloadPermissions
>
> Attached is a multi-module maven project. The modules are:
> 1. secure-marshall-stream (which is the implementation of all this + some not
> yet finished additional code)
> 2. jsk-module-platform which contains modified Jini classes so that it all
> works with existing Jini services (to be honest only ClassLoading really
> needed to change. MarshalInputStream/MarshalOutputStream/MarshalledInstance
> are changed only to avoid having serialized and Base64 encoded Modules as
> annotations
>
> To run it you need to put jsk-module-platform before jsk-platform on the
> classpath (and of course add secure-marshall-stream as well)
>
> Existing services can be exported with a ModuleExporter:
>
> private serviceILFactory =
> new ProxyTrustILFactory(serviceConstraints,
> RegistrarPermission.class);
> private moduleTrustILFactory =
> new ModuleTrustILFactory(serviceConstraints,
> null);
>
> serverExporter = new ModuleExporter(new BasicJeriExporter(serviceEndpoint,
> serviceILFactory), new BasicJeriExporter(serviceEndpoint,
> moduleTrustILFactory));
>
> I've done some basic scenario testing which was running Reggie and Service
> Browser installed by Jini 2.1 installer. Both Browser and Reggie policies did
> not grant any DownloadPermissions.
> When exported with BasicJeriExporter lookup of ServiceRegistrar by the Browser
> failed with missing DownloadPermission.
> When exported with ModuleExporter both Reggie and Browser used
> ProxyTrustVerifier to verifify Modules.
>
> Note - this is strictly a prototype - no comments / junit tests / code reviews
> and no real testing.
>
> If you have any questions / comments - you're very welcome.
>
> Michal
>
> On Monday 18 of October 2010 03:08:38 Peter Firmstone wrote:
>
>> Notes for fix:
>>
>> DownloadPermission protects against unauthenticated downloads
>> ClassLoadingPermission - new Permission to protect against
>> unauthenticated Class loading.
>>
>> Issues we're addressing in the DOS hole:
>>
>> * Eliminate unauthenticated URL downloads.
>> * Eliminate unmarshalling of unauthenticated code.
>> * Eliminate execution of unauthenticated code.
>> * Eliminate StackOverflowError's in the client thread, caused by
>> sending spurious garbage over InputStream's.
>> * Eliminate StackOverflowError's in the client thread, caused by
>> substituted jar files or URL's from DNS cache poisoning attacks etc.
>>
>> How?
>>
>> * Delay granting DownloadPermission, until remote endpoint has
>> authenticated itself, we trust the remote endpoint to advise a
>> suitable URL, if it authenticates.
>> * Authentication by annotating a reflective proxy (additional to the
>> Codebase String) from the remote endpoint, used for authentication
>> and to provide CodeSource Certificate[]'s. This may be different
>> to the Service, if a remote object is marshalled elsewhere (eg
>> another client).
>> * Delay granting ClassLoadingPermission, until remote endpoint has
>> authenticated itself and has provided the expected CodeSource
>> Certificate[]'s
>> * Perform unmarshalling in a controlled ExecutorService thread.
>>
>> So all we're doing different is authenticating the remote end and if it
>> authenticates permit downloading and classloading.
>>
>> There is one more scenario to consider, currently this is a mechanism to
>> protect against download and deserialization of unknown code for smart
>> proxy's. But what about Service that only use reflective proxy's and
>> don't require downloaded code?
>>
>> But what if we don't want to grant download permission or class loading
>> permission to a Subject we authenticate?
>>
>> Currently the unmarshalling code doesn't run as the Subject after
>> authentication, this means the Permission grant's are only dependent on
>> authentication, something Michal pointed out earlier when this was
>> proposed.
>>
>> Now this code can be easily changed so the granting permission operation
>> is run as the Subject after authentication, this would allow us to
>> distinguish between different Subjects.
>>
>> The drawback is that performance won't be as good, but it seems the most
>> logical and powerful approach.
>>
>> What do you think?
>>
>> There is one last obstacle, if Certificates are used to sign the jar
>> files, how do you effectively prevent one Subject from using another
>> Subject's signed CodeSource's if Code signing is used for isolation of
>> separate Subjects namespaces? A service could deliberately attempt to
>> occupy the same namespace as another Service to attempt to gain
>> information via shared static variables. We need to prevent this
>> occurring.
>>
>> This has to be done with the ClassLoader, but during unmarshalling, the
>> service proxy has not yet been verified. The authentication proxy
>> delivered with the MarshalInputStream may not have the same Subject as
>> the Service, it could be a third party.
>>
>> Could it be that when the smart proxy is unmarshalled, and executed as
>> it's Subject, it must contain a Certificate matching the signer of the
>> Codebase?
>>
>> We're on the cusp of solving this problem, thoughts?
>>
>> Cheers,
>>
>> Peter.
>>
>> Peter Firmstone (JIRA) wrote:
>>
>>> Denial of Service during unmarshalling of smart proxy's
>>> -------------------------------------------------------
>>>
>>> Key: RIVER-362
>>> URL: https://issues.apache.org/jira/browse/RIVER-362
>>>
>>> Project: River
>>>
>>> Issue Type: Bug
>>>
>>> Environment: Untrusted networks
>>>
>>> Reporter: Peter Firmstone
>>>
>>> During unmarshalling of smart proxy's there's a period before the proxy
>>> has been verified (authenticated) where deserialization methods are
>>> executed on untrusted code, the potential exists for untrusted code to
>>> perform denial of service.
>>>
Re: [jira] Created: (RIVER-362) Denial of Service during unmarshalling of smart proxy's
Posted by Michal Kleczek <mi...@xpro.biz>.
Folks,
I've managed to create a prototype implementation of the idea of annotating
classes with Modules.
Working on this allowed me to learn quite a lot about inner workings of River
- the original implementation that I've presented before had to be modified
(not saying it had to be fixed :) ) but the main idea stayed the same. This
time I think it really covers more use cases.
Shortly:
1. We allow annotating classes with Modules. A Module is an object responsible
for loading classes.
2. There is a new RMIClassLoaderSpi implementation which I called
ModuleClassProvider
3. ModuleClassProvider manages installed Modules
4. It also can load classes based on String annotations which are expected to
be either
a) serialized and Base64 encoded Module - the Module is deserialized and
handled as any other Module annotation
b) an old style list of URLs - class loading is delegated to
RequireDlPermProvider - in other words we either load classes from Modules
(which are verified for trust before use) or from URLs but then we require
appropriate DownloadPermissions
Attached is a multi-module maven project. The modules are:
1. secure-marshall-stream (which is the implementation of all this + some not
yet finished additional code)
2. jsk-module-platform which contains modified Jini classes so that it all
works with existing Jini services (to be honest only ClassLoading really
needed to change. MarshalInputStream/MarshalOutputStream/MarshalledInstance
are changed only to avoid having serialized and Base64 encoded Modules as
annotations
To run it you need to put jsk-module-platform before jsk-platform on the
classpath (and of course add secure-marshall-stream as well)
Existing services can be exported with a ModuleExporter:
private serviceILFactory =
new ProxyTrustILFactory(serviceConstraints,
RegistrarPermission.class);
private moduleTrustILFactory =
new ModuleTrustILFactory(serviceConstraints,
null);
serverExporter = new ModuleExporter(new BasicJeriExporter(serviceEndpoint,
serviceILFactory), new BasicJeriExporter(serviceEndpoint,
moduleTrustILFactory));
I've done some basic scenario testing which was running Reggie and Service
Browser installed by Jini 2.1 installer. Both Browser and Reggie policies did
not grant any DownloadPermissions.
When exported with BasicJeriExporter lookup of ServiceRegistrar by the Browser
failed with missing DownloadPermission.
When exported with ModuleExporter both Reggie and Browser used
ProxyTrustVerifier to verifify Modules.
Note - this is strictly a prototype - no comments / junit tests / code reviews
and no real testing.
If you have any questions / comments - you're very welcome.
Michal
On Monday 18 of October 2010 03:08:38 Peter Firmstone wrote:
> Notes for fix:
>
> DownloadPermission protects against unauthenticated downloads
> ClassLoadingPermission - new Permission to protect against
> unauthenticated Class loading.
>
> Issues we're addressing in the DOS hole:
>
> * Eliminate unauthenticated URL downloads.
> * Eliminate unmarshalling of unauthenticated code.
> * Eliminate execution of unauthenticated code.
> * Eliminate StackOverflowError's in the client thread, caused by
> sending spurious garbage over InputStream's.
> * Eliminate StackOverflowError's in the client thread, caused by
> substituted jar files or URL's from DNS cache poisoning attacks etc.
>
> How?
>
> * Delay granting DownloadPermission, until remote endpoint has
> authenticated itself, we trust the remote endpoint to advise a
> suitable URL, if it authenticates.
> * Authentication by annotating a reflective proxy (additional to the
> Codebase String) from the remote endpoint, used for authentication
> and to provide CodeSource Certificate[]'s. This may be different
> to the Service, if a remote object is marshalled elsewhere (eg
> another client).
> * Delay granting ClassLoadingPermission, until remote endpoint has
> authenticated itself and has provided the expected CodeSource
> Certificate[]'s
> * Perform unmarshalling in a controlled ExecutorService thread.
>
> So all we're doing different is authenticating the remote end and if it
> authenticates permit downloading and classloading.
>
> There is one more scenario to consider, currently this is a mechanism to
> protect against download and deserialization of unknown code for smart
> proxy's. But what about Service that only use reflective proxy's and
> don't require downloaded code?
>
> But what if we don't want to grant download permission or class loading
> permission to a Subject we authenticate?
>
> Currently the unmarshalling code doesn't run as the Subject after
> authentication, this means the Permission grant's are only dependent on
> authentication, something Michal pointed out earlier when this was
> proposed.
>
> Now this code can be easily changed so the granting permission operation
> is run as the Subject after authentication, this would allow us to
> distinguish between different Subjects.
>
> The drawback is that performance won't be as good, but it seems the most
> logical and powerful approach.
>
> What do you think?
>
> There is one last obstacle, if Certificates are used to sign the jar
> files, how do you effectively prevent one Subject from using another
> Subject's signed CodeSource's if Code signing is used for isolation of
> separate Subjects namespaces? A service could deliberately attempt to
> occupy the same namespace as another Service to attempt to gain
> information via shared static variables. We need to prevent this
> occurring.
>
> This has to be done with the ClassLoader, but during unmarshalling, the
> service proxy has not yet been verified. The authentication proxy
> delivered with the MarshalInputStream may not have the same Subject as
> the Service, it could be a third party.
>
> Could it be that when the smart proxy is unmarshalled, and executed as
> it's Subject, it must contain a Certificate matching the signer of the
> Codebase?
>
> We're on the cusp of solving this problem, thoughts?
>
> Cheers,
>
> Peter.
>
> Peter Firmstone (JIRA) wrote:
> > Denial of Service during unmarshalling of smart proxy's
> > -------------------------------------------------------
> >
> > Key: RIVER-362
> > URL: https://issues.apache.org/jira/browse/RIVER-362
> >
> > Project: River
> >
> > Issue Type: Bug
> >
> > Environment: Untrusted networks
> >
> > Reporter: Peter Firmstone
> >
> > During unmarshalling of smart proxy's there's a period before the proxy
> > has been verified (authenticated) where deserialization methods are
> > executed on untrusted code, the potential exists for untrusted code to
> > perform denial of service.