From: <bc...@wo...> - 2000-12-27 20:49:59
|
[Samuele Pedroni] >I start this with the conclusion (maybe this already clear to everybody = >but it is better if it is stated somewhere): >the patch in alpha2 to BytecodeLoader logic that enables to run jython = >code - that uses >exec, execfile ... - under java2 plugin, if one gives enough permissions = >is really only intended to run=20 >fully trusted jython code that uses exec on python fragments fully = >trusted too. A good observation. >On the other side if one gives no permissions, we fall back to the old = >situation and everything is safe. This is worth repeating. If no special permission is granted in the policy file, jython 2.0 applets are as safe as any other applets. >For anyone knowing java2 security architecture, already the fact that = >createClassLoader permission >should be granted to achieve this, should be a sufficient explanation to = >the conclusion. >This permission can safely be granted only to really trusted code ... > >Having jython runtime around only make it easier to eventually exploit = >this. I'll argue that because the jython runtime needs access to different parts of the filesystem (registry & classes in python.home and directories in the classpath), having the jython runtime around makes the environment less safe. Even when the bug exposed by your example is fixed, adding grant codeBase "file:${python.home}/-" { permission java.security.AllPermission "",""; }; to a policy file will never be safe. More discretion will always be required. Regarding the bug, I think a solution is to store the protection domain from the proxy in the system state during Py.initProxy, Py.jgetattr and Py.jfindattr (and in the adapter calls, I think). BytecodeLoader2 will then use this saved protection domain when loading code. [This may open for an attack where the evil applet gets executed on the same thread as a trusted application and thus is able to create code though the BytecodeLoader2 with the protection domain of the trusted application. I'm unsure if it is possible to make the created code execute without the evil applet being on the stack. More analysis is needed] I've uploaded a patch which attempt to save to protection domain in this way. The patch isn't suitable for use because it assume java2 and does not cover the adapters. http://sourceforge.net/patch/index.php?func=detailpatch&patch_id=103025&group_id=12867 >PS: >To improve this (for the future: these are at least not little changes) = >(just some ideas that possibly work): >1) We should avoid to be obligated to grant createClassLoader permission = >to > the code that uses exec: maybe this is possible using privileged = >Blocks. > Then it becomes important that the code loaded by the exec > receives the same or less permissions than the "code that requested = >the exec". It should also cover the dynamically generated proxy classes which is also loaded by BytecodeLoader2. Even with privileged blocks, the problem as I see it, is to capture the permission of the originating applet and use it for the created code. That have to be thread safe, secure and efficient. >2) We could provide something like the codebase based logic of the = >SecureClassLoader > for jython code loading too. You think that is possible while maintaining the same API to the "exec" statement? regards, finn |
From: Samuele P. <pe...@in...> - 2000-12-27 22:24:15
|
Hi. Just two things to be pointed out. [Finn] > I'll argue that because the jython runtime needs access to different > parts of the filesystem (registry & classes in python.home and > directories in the classpath), having the jython runtime around makes > the environment less safe. > > Even when the bug exposed by your example is fixed, adding > > grant codeBase "file:${python.home}/-" { > permission java.security.AllPermission "",""; > }; >to a policy file will never be safe. More discretion will always be >required. No that's not the problem, as is it not a problem to give full permissions to java runtime used to run in the same application trusted and untrusted code. The java2 security rules are there to deal with this: at any point the intersection of the permissions of all code on the stack counts (that means the min common subset). And in case of thread creation permissions are properly propagated. Up to privileged blocks. > Regarding the bug, I think a solution is to store the protection domain > from the proxy in the system state during Py.initProxy, Py.jgetattr and > Py.jfindattr (and in the adapter calls, I think). BytecodeLoader2 will > then use this saved protection domain when loading code. > > [This may open for an attack where the evil applet gets executed on the > same thread as a trusted application and thus is able to create code > though the BytecodeLoader2 with the protection domain of the trusted > application. I'm unsure if it is possible to make the created code > execute without the evil applet being on the stack. More analysis is > needed] > > I've uploaded a patch which attempt to save to protection domain in this > way. The patch isn't suitable for use because it assume java2 and does > not cover the adapters. > > > http://sourceforge.net/patch/index.php?func=detailpatch&patch_id=103025&grou p_id=12867 > This does not solve the bug, which is more a missing feature than a bug. This is a possible solution to capture the applet permissions but I should repeat this again: The real point is that in order to allow an applet to use exec we should grant to it createClassLoader permission. Only if we can avoid this it make sense and it is worth to try to capture the permissions of the applet code. Because if there is a "security hole" around in applicative code, as in my example the code that invokes a method of a class instance implementing an interface obtained from "untrusted" code. Instead of using jython runtime that creates code with the right permissions, the untrusted code can create its own class loader and load things with permissions of its choice. See: http://www.java.sun.com/j2se/1.3/docs/guide/security/permissions.html#Runtim ePermission So for the moment it is simply dangerous to try to allow untrusted code to use exec. So to say AllPermission!=createClassLoader but to grant one of them to untrusted code is quite the same: foolish. regards, Samuele. PS: >>2) We could provide something like the codebase based logic of the = >>SecureClassLoader >> for jython code loading too. > >You think that is possible while maintaining the same API to the "exec" >statement? This was a general idea, not related to exec and the "bug". |
From: <bc...@wo...> - 2000-12-29 03:04:16
|
On Wed, 27 Dec 2000 23:23:15 +0100, you wrote: >Hi. > >Just two things to be pointed out. > >[Finn] >> I'll argue that because the jython runtime needs access to different >> parts of the filesystem (registry & classes in python.home and >> directories in the classpath), having the jython runtime around makes >> the environment less safe. >> >> Even when the bug exposed by your example is fixed, adding >> >> grant codeBase "file:${python.home}/-" { >> permission java.security.AllPermission "",""; >> }; >>to a policy file will never be safe. More discretion will always be >>required. > >No that's not the problem, as is it not a problem to give full permissions >to java runtime >used to run in the same application trusted and untrusted code. >The java2 security rules are there to deal with this: at any point the >intersection of the permissions >of all code on the stack counts (that means the min common subset). And in >case of thread >creation permissions are properly propagated. Up to privileged blocks. > >> Regarding the bug, I think a solution is to store the protection domain >> from the proxy in the system state during Py.initProxy, Py.jgetattr and >> Py.jfindattr (and in the adapter calls, I think). BytecodeLoader2 will >> then use this saved protection domain when loading code. >> >> [This may open for an attack where the evil applet gets executed on the >> same thread as a trusted application and thus is able to create code >> though the BytecodeLoader2 with the protection domain of the trusted >> application. I'm unsure if it is possible to make the created code >> execute without the evil applet being on the stack. More analysis is >> needed] >> >> I've uploaded a patch which attempt to save to protection domain in this >> way. The patch isn't suitable for use because it assume java2 and does >> not cover the adapters. >> >> >> >http://sourceforge.net/patch/index.php?func=detailpatch&patch_id=103025&grou >p_id=12867 >> >This does not solve the bug, which is more a missing feature than a bug. >This is a possible solution to capture the applet permissions but I should >repeat this again: > >The real point is that in order to allow an applet to use exec we should >grant to it createClassLoader permission. >Only if we can avoid this it make sense and it is worth to try to capture >the permissions of the applet code. > >Because if there is a "security hole" around in applicative code, as in my >example the code that invokes a method of a class instance implementing an >interface obtained from "untrusted" code. >Instead of using jython runtime that creates code with the right >permissions, the untrusted code can create its own class loader and load >things with permissions of its choice. >See: >http://www.java.sun.com/j2se/1.3/docs/guide/security/permissions.html#Runtim >ePermission > >So for the moment it is simply dangerous to try to allow untrusted code to >use exec. > >So to say AllPermission!=createClassLoader but to grant one of them to >untrusted code is quite the same: foolish. Ok. So by putting the "new BytecodeLoader" call in a privileged block we ensure that only the jython domain needs createClassLoader permission. The u-dom and t-dom does not. Then we have to make damn sure that the created code is executed with the permissions of the initial caller. Otherwise we have created a truck sized security hole. I now think the right place to put this restriction is at the PyCode level, instead of the Class level. For a second, imagine that we have yet another PyCode implementation which is doing a recusive interpretation of the parse tree. Such a PyCode implementation should also be covered by the access restriction of the code base which compiled the PyCode instance. In the patch, I now ensure that the execution of a PyTableCode is done with the AccessControlContext of the code that created the PyTableCode. The classloader is created in a privileged block, so the createClassLoader permission no longer require for u-dom and t-dom. The assignment of co_context should really be done in a non-public superclass of PyCode, so that PyCode subclasses can't assign a different context. I'm sure other things are missing as well. http://sourceforge.net/patch/index.php?func=detailpatch&patch_id=103025&group_id=12867 regards, finn |
From: Samuele P. <pe...@in...> - 2000-12-29 10:07:51
|
Hi. I will study the patch. I see some potential problems but maybe I'm interpreting wrong the java2 security doc. regards, Samuele. |
From: Samuele P. <pe...@in...> - 2000-12-31 02:34:05
|
Hi. [sorry for the length of this] [me] > I will study the patch. > I see some potential problems but maybe I'm interpreting wrong the java2 > security doc. 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". 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] 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. 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. 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. 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. 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. So the permissions granted are all actually in place for the code that issued the creation request. Review of all this is welcome regards, Samuele Pedroni. PS: * Clearly these tentatives of enabling exec for untrusted code will work only if jython is installed locally and will receive enough permissions. * A definitive support for java2 security should probably also do the following: both for loading of percompiled ($py.class) jython code and java classes from sys.path loading the jython runtime should assign a correct protection domain to the loaded classes through the SecureClassLoader.defineClass(...,CodeSource csrc) api. |
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 |
From: Samuele P. <pe...@in...> - 2001-01-01 00:38:41
|
Hi. [Finn] > [Samuele] .... > >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. (Just for general interest) I think they intend that at some very specific places the thread code uses doPriviled passing the needed (somewhere else captured) context. > >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. In general I agree with this. But if we cannot limit this penalty only to the case of the real use of dynamicly loaded code, I think we need a different approach. I imagine that offering the feature this way - to fully trusted applications running under the plug-in - but at the price of this global performance loss make few sense. > >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. I do not understand your comment. For me that's a security problem because the users then *must* understand the issue and deal with it. I repeat > > 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. The situation that I imagine is the use of exec to create/define a function. Then this function will always be executed with the permissions of the creation (exec) context. From my viewpoint that's bad. In general - with java2 security - code in a protection domain that do not have the permission to do something cannot achieve that, even calling code in another protection domain. The patch as it is breaks that in a too broad way. ... > >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? Yes and that's ugly too.I imagine that we will need to produce some kind of fake URL, I have not studied that yet. The problem is clear: the security api as it is is not well suited to support the dynamic creation/loading of code/classes at runtime. So we are not using it, we are hacking with it. > >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>. Yes, really ugly <wink>, but if we do not find a solution for the problems above we will have to try this too. Further, given that adapters are created lazily I imagine they will need some special treatment. I think just putting them in jython runtime prot-dom should be ok. > --------------------------------- > > 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. A "secure" applet context impl should allow mutual access only between applets that comes from the same code-source. It should be checked if that's the case of sun plug-in. Not tried yet. But reading the doc it seems to be the case. The fact that for implementation reasons and python philosophy all member of a python class are "public" from java side is somehow a general "security" issue. regards, Samuele Pedroni. |