From: <bc...@wo...> - 2000-12-31 13:26:23
|
[Samuele] >The patch idea is quite nice (I had not thought about such a possibility) >but unfortunately >there are some problems. >First a general remark: >Our java2 security support should be robust in every situation >(codesources/protection domains setup), >even if probably it will be mostly used for applets running within the >plug-in, or at least we should have a short formulation of what people >should not do. The actual codebase meets such a requirement: one can allow >(compiled) jython code to >use exec at the cost of granting createClassLoader permission, this implies >that both the code and >the exec-ed jython fragments must be fully trusted. > >In Sun doc it is stated that the use of doPrivileged should be very limited >and also the amount of code executed inside >such a privileged context should be limited too. The patch does something >very different using doPrivileged for every "jython function call" and >having the privileged region encompass the whole "call". I think (I'm not sure) that the advice SUN is giving only covers the doPrivileged method without an explicit AccessControlContext. The example SUM is supplying is that of a worker thread, and I assume that the complete work that the worker thread is about to perform should be executed with a doPrivileged call *with* explicit AccessControlContext. >a) A bad news about the patch is the perfomance cost of it: >On my machine with the patch in place the pystones number (using 50000 >iters ) goes down from ~4950 to ~2900. >I do know very little about how to read pystone results: but this seems to >me a "big" performance cost that is paid >globally. >[In any case I continue to list the "problems" of the patch, maybe there is >a solution that I do not see, and I think some >remarks are of more general interest] I'm sure some optimizing is possible. OTOH, even a high performance hit is acceptable as long as it is only incurred in very controlled situations: - Only when running under a seurity manager, and - Only if specificly enabled with a property / jythonc option or - Only when using dynamicly compiled code through exec. >b) Sun says nothing about using doPrivileged in the context of recursive >calls: I have no idea if there are problems with that too? >c) A final version of the patch should clearly avoid that code external to >jython runtime could exploit the created classloaders, > e.g. a method like BytecodeLoader.makeClass should then become package >protected etc. Absolutely. >d) With the patch as it is the (dynamically created) classes- loaded >through the BytecodeLoaders - are still put in the protection > domain of jython runtime: once the access to BytecodeLoader functionality >is sealed from outside they will/can be just > the adapters and proxies classes and PyCode-derived classes. > I don't see a way to exploit the fact that these will be in jython runtime >prot-dom. But I'm not sure that such a possibilty > does not exist. I agree that it is a potential problem, and that I can't rule out the possibility of an attack either. >e) Given that our support should work in a general setup: > - The patch solves the problem of reducing the permissions back to the ones >of the context of the code that used exec. > So if the created code is called from a context with more permissions it >cannot exploit any of these. That was the issue > showed by my example. >- On the other hand if the exec-created code is called from a context with >less permissions, given doPrivileged > definition, it will anyway run with the permissions of its creation >context. Yes, unfortunate; but I don't think it is a security problem. The high permission code that made the exec could just run the code itself. Still, it is bad design to run any code with too high permission. > In general java2 security design avoids this kind of situation (but gives >through doPrivileged a way to obtain this) > because then the user during coding should explicitly think about the >possible security holes that this behaviour opens. > >I think that what we need to achieve is the following: >that exec-created (and the other dynamically created code) should run under >the intersection of the permissions of the >creation and execution contexts. One then can use doPrivileged explicitly to >modify this. > >But reading java2 security doc it seems that: >- There is no way to take 2 AccessControlContext and build a third that >correspond to the intersection of them. >- There is no explicit/elegant way to extract the permissions in place given >a/the current AccessControlContext. > >Now I will try to explain an alternative design for a patch. I do not like >it very much, because it is not very elegant. >I hope that we can save one the of other approaches or find a derivation of >this or combination that do the job >in a reasonable way. This is just a sketch. > >Jython runtime should keep a global list PermCands of permissions (e.g. thro >ugh an HashSet). >There will be an api to add permissions to the list. >The init-functions (for proxies, etc.) that now take a classloader should >then take the proxy/... class too >and jython should automatically put all the permissions of the prot-dom of >that class in the list. >[Cheating at this level will bring no gain] > >The actual functionality of BytecodeLoader makeLoader, constructor and >makeClass/Code methods should be >completily isolated inside jython runtime: an idea for this is to have > >* a SingletonSealedLoader class with just a package protected constructor >and a method to retrieve the unique class >that is directly loaded through it: >the constructor will take the makeClass arguments and an >AccessControlContext acc. >* a static package protected function that calls AccessController.getContext >and then invoke through doPrivileged SingletonSealedLoader ctr with the >obtained current protection context. > >The constructor logic will do the following: >- if there is no security manager in place just define the class. >- if there is a security manager in place: define the class inside a >protection domain, > the permissions to grant will be computed this way: > > Only the permissions from the global set PermsCands for which >acc.checkPermission do not throw an exception > will be granted. Would this create a new ProtectionDomain for each dynamicly loaded class? What CodeSource would be used for the ProtectionDomain? >Clearly all this checks have a performance cost, especially when the >negative result exc is thrown. >The code can test wheter already AllPermission is ok to gain some speed in >this case. >The assumption is that the set will not be that big and in any case the cost >is local to the dynamic >creation of code. And zero if there is no security manager in place. That is good enough. Don't worry about the performance if the hit is only incurred when actually used. >So the permissions granted are all actually in place for the code that >issued the creation request. Yes, I think this is a safe way to store and later recreate the permissions of the code that wants to create code dynamicly. And yes, it's ugly <wink>. --------------------------------- Only slightly releated: what would happen if an evil applet could somehow get hold of a PyProxy or PyObject (perhaps through Applet.getAppletContext().getApplet("foo") ) and then started making modification to the applet with __setattr__ and __setitem__. The evil applet cannot introduce new code into the "foo" applet, but if foo it trusted and is a large application, the evil applet may find enough usefull methods and functions to build an attack. I haven't tried this yet, it's just a scary thought. regards, finn |